【问题标题】:Trying to create a discovery script using Python Multithreadinig尝试使用 Python 多线程创建发现脚本
【发布时间】:2017-07-29 07:37:32
【问题描述】:

我正在尝试创建一个发现脚本,它将使用多线程同时 ping 多个 IP 地址。

import ipaddress
import sh
from threading import Thread
from Queue import Queue


user_input = raw_input("")
network = ipaddress.ip_network(unicode(user_input))

def pingit(x):

    for i in x.hosts():
        try:
            sh.ping(i, "-c 1")
            print i, "is active"
        except sh.ErrorReturnCode_1:
            print "no response from", i

queue_to_work = Queue(maxsize=0)
number_of_workers = 30

for i in range(number_of_workers):
    workers = Thread(target=pingit(network),args=(queue_to_work,))
    workers.getDaemon(True)
    workers.start()

当我运行这个脚本时,我得到了 ping 响应,但速度并不快。我相信多线程并没有开始。

谁能告诉我哪里出错了?

非常感谢。

【问题讨论】:

  • 看着你的问题,我想知道你为什么要使用多线程来完成这项任务。似乎分布式任务队列(如 Celery)更适合手头的任务。您能否提供更多关于您想要实现的目标的背景信息?
  • @JohanVergeer,我正在尝试发现网络上的活动和非活动 IP 地址。我在for i in x.hosts(): try: sh.ping(i, "-c 1") print i, "is active" except sh.ErrorReturnCode_1: print "no response from", i 下面的第一个脚本但是,这真的很慢。我尝试看一些教程并遇到了多线程。我想如果我使用多线程,我可以一次 ping 30 个 IP 地址。任何帮助或指导将不胜感激。

标签: python multithreading networking


【解决方案1】:

你完全错了。

import ipaddress
import sh
from threading import Thread

user_input = raw_input("")
network = ipaddress.ip_network(unicode(user_input))

def pingit(x):

    for i in x.hosts():
        try:
            sh.ping(i, "-c 1")
            print i, "is active"
        except sh.ErrorReturnCode_1:
            print "no response from", i

workers = Thread(target=pingit,args=(network,))
workers.start()

这就是您启动线程的方式。编写pingit(network) 将实际运行函数,并将其结果传递给Thread,而您想传递函数本身。您应该分别传递函数pingit 和参数network。请注意,这会创建一个实际上运行 pingit(network) 的线程。

现在,如果您想使用多个线程,可以循环执行。但是您还必须创建单独的数据集以馈入线程。考虑你有一个主机列表,例如['A', 'B', 'C', 'D'],并且您想从两个线程中对它们执行 ping 操作。您必须创建两个线程,分别调用 pingit(['A', 'B'])pingit(['C', 'D'])

附带说明,不要使用ip_network 来查找IP 地址,请使用ip_address。您可以ping 一个IP 地址,但不能ping 网络。当然如果你想ping所有网络中的ip地址,ip_network就可以了。

您可能希望以某种方式将用户输入拆分为多个 IP 地址,并将列表拆分为线程的子列表。这很容易。现在您可以编写for 来创建线程,并将每个子列表提供给线程的参数。这会创建实际使用不同参数运行的线程。

【讨论】:

  • 另外,如果您有大量线程,请考虑使用线程池。搜索这个词,有很多关于它的信息。
  • 非常感谢@vsoraki。这绰绰有余,你让我轻松了。
【解决方案2】:

我想分享我对此的看法。

因为我猜这是你想在后台运行的东西,我建议你使用队列而不是线程。

这将为您提供多种优势:

  • 您可以将多个功能添加到队列中
  • 如果出现问题,队列将继续,并为您捕获错误。如果出现问题,您甚至可以添加一些日志记录。
  • 队列作为守护进程运行,队列中的每个项目都作为自己的进程
  • 像 RabbitMQ 或 Redis 这样的系统是为这种特定类型的任务而构建的。
  • 设置相对容易

我为您创建了一个简单的脚本,您可以使用:

import subprocess

from celery import Celery

app = Celery()

@app.task
def check_host(ip, port=80, timeout=1):
    output = subprocess.Popen(["ping", "-c", "1", ip], stdout=subprocess.PIPE).communicate()[0]

    if "1 packets received" in output.decode("utf-8"):
        return "{ip} connected successfully".format_map(vars())
    else:
        return "{ip} was unable to connect".format_map(vars())


def pingit(ip="8.8.8.8"):    

    check_host.delay(ip)

它的作用如下。

  1. 您首先导入 Celery,这将使您能够连接到在后台运行的 Celery。
  2. 您创建了一个属于 Celery 类实例的应用程序
  3. 您使用此应用程序来创建任务。在这个里面你把你想要异步执行的所有动作都放在任务中。
  4. 您在任务上调用 delay() 方法

现在任务将在后台运行,所有其他任务将被放入队列中为您异步运行。 所以你可以把所有东西都放在一个循环中,队列会为你处理。

关于芹菜的信息:http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html
还有一个很棒的教程来设置我在 YouTube 上找到的所有内容:https://www.youtube.com/watch?v=68QWZU_gCDA

希望对你有所帮助

【讨论】:

  • 这很有帮助。我会对此进行更多研究。
猜你喜欢
  • 1970-01-01
  • 2013-05-04
  • 2013-11-02
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 2016-11-29
  • 1970-01-01
相关资源
最近更新 更多