【发布时间】:2016-12-10 23:12:48
【问题描述】:
所以昨天我正在练习我在过去几天学到的东西,并决定创建一个脚本来扫描本地网络中的所有 IP 并检查正在使用的 IP。
我使用 subprocess 使用带有给定超时的“ping”命令,以及其他一些库,例如 docopt、threading 和 time,用于处理命令行参数、线程、等待代码等常见任务......
这是脚本:
""" ipcheck.py - Getting available IPs in a network.
Usage:
ipcheck.py -h | --help
ipcheck.py PREFIX
ipcheck.py [(-n <pack_num> PREFIX) | (-t <timeout> PREFIX)]
Options:
-h --help Show the program's usage.
-n --packnum Number of packets to be sent.
-t --timeout Timeout in miliseconds for the request.
"""
import sys, os, time, threading
from threading import Thread
from threading import Event
import subprocess
import docopt
ips = [] # Global ping variable
def ping(ip, e, n=1, time_out=1000):
global ips
# FIX SO PLATFORM INDEPENDENT
# Use subprocess to ping an IP
try:
dump_file = open('dump.txt', 'w')
subprocess.check_call("ping -q -w%d -c%s %s" % (int(time_out), int(n), ip),
shell=True, stdout=dump_file, stderr=dump_file)
except subprocess.CalledProcessError as err:
# Ip did not receive packets
print("The IP [%s] is NOT AVAILABLE" % ip)
return
else:
# Ip received packets, so available
print("The IP [%s] is AVAILABLE" % ip)
#ips.append(ip)
finally:
# File has to be closed anyway
dump_file.close()
# Also set the event as ping finishes
e.set()
ips.append(1)
def usage():
print("Helped init")
def main(e):
# variables needed
timeout = 1000
N_THREADS = 10
# Get arguments for parsing
arguments = docopt.docopt(__doc__)
# Parse the arguments
if arguments['--help'] or len(sys.argv[1:]) < 1:
usage()
sys.exit(0)
elif arguments['--packnum']:
n_packets = arguments['--packnum']
elif arguments['--timeout']:
timeout = arguments['--timeout']
prefix = arguments['PREFIX']
# Just an inner function to reuse in the main
# loop.
def create_thread(threads, ip, e):
# Just code to crete a ping thread
threads.append(Thread(target=ping, args=(ip, e)))
threads[-1].setDaemon(True)
threads[-1].start()
return
# Do the threading stuff
threads = []
# Loop to check all the IP's
for i in range(1, 256):
if len(threads) < N_THREADS:
# Creating and starting thread
create_thread(threads, prefix+str(i), e)
else:
# Wait until a thread finishes
e.wait()
# Get rid of finished threads
to_del = []
for th in threads:
if not th.is_alive(): to_del.append(th)
for th in to_del: threads.remove(th)
# Cheeky clear init + create thread
create_thread(threads, prefix+str(i), e)
e.clear()
time.sleep(2*timeout/1000) # Last chance to wait for unfinished pings
print("Program ended. Number of threads active: %d." % threading.active_count())
if __name__ == "__main__":
ev = Event()
main(ev)
我遇到的问题是,虽然我为 ping 命令设置了超时(以毫秒为单位),但某些线程由于某种原因没有完成。我通过使所有线程成为守护进程并在程序完成后等待两次超时(main 中的最后几行)暂时解决了这个问题,但这并没有按预期工作,一些线程在睡眠后仍未完成。
这与命令 ping 本身有关还是我的设计有问题?
和平!
【问题讨论】:
-
你试过让它在 shell (cmd) 命令中完成吗?
-
是的,我在 shell 上运行了该命令,但它永远不会超过超时。这就是 -w 命令存在的原因,因此它等待响应的时间不会超过此时间。
-
但在代码中,有时它似乎仍然会重复,并且不会终止。
-
嗯,我明白了。我更喜欢将 Batch 或 C# 用于互联网相关功能。在某种程度上,您的脚本运行不顺畅。你应该调试它,让它写一个脚本正在做什么的TXT。当它检查你的错误时,你应该看到发生了什么
-
目标主机是通过ip地址还是名字来指定?我检查了 ping 源,它在设置截止时间计时器之前执行 DNS 查找。因此,如果 DNS 查找速度较慢,ping 命令可能会在截止日期之后运行。
标签: python linux multithreading command-line timeout