【问题标题】:Python pinging local IPsPython ping 本地 IP
【发布时间】: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


【解决方案1】:

Python 3.3 为subprocess.check_call() 实现了一个timeout= 关键字参数:

https://docs.python.org/3.3/library/subprocess.html#subprocess.check_call

否则我会使用另一个线程来确保生成的命令在超时期限后被杀死 - 即看到这个 SO 答案:

https://stackoverflow.com/a/6001858/866915

【讨论】:

  • 谢谢!!我使用的是 python 2.7,但我可能可以使用第二个链接中的方法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多