Python多线程与gevent高效批量Ping检测在线IP

洛溪
洛溪
发布时间:2026-10-13 | 5人浏览过
原创

本文介绍利用Python高效检测网段内在线IP的两种方案。针对设备众多、重复维护场景,分别采用threading模块实现多线程并发ping,以及gevent资源池进行异步IO处理。通过对比两种代码实现,帮助开发者快速掌握批量网络连通性检测技巧,提升运维效率。

问题描述

在某些运维场景下,需要确认多台终端是否在线,通常会使用ping命令进行连通性测试。当待检测设备数量较少时,手动操作尚可接受;但若维护设备规模庞大,手动ping将变得极其繁琐。此时,自动化脚本的价值便凸显出来。此外,由于单线程执行效率较低,难以在短时间内完成大量统计,因此引入多线程机制是必要的优化手段。

应用背景

存在多台设备需要维护,且维护周期短、重复性高;

单台设备配置多个IP地址,需频繁确认网络是否畅通;

其他需要批量确认网络连通性的场景。

问题解决

利用Python内置的threading模块实现多线程并发操作。若系统中未安装相关依赖,请通过pip install package name命令进行安装。

threading并发ping操作代码实现

该段代码源自网络(疑似stackoverflow),具体来源已不可考,但其核心价值在于提供了实用的解决方案。代码中关键位置已添加注释,用户可根据实际需求自定义IP所属网段及线程数量。从实际效果来看,这是一段相当高效的代码。

# -*- coding: utf-8 -*-

import sys
import os
import platform
import subprocess
import Queue
import threading
import ipaddress
import re

def worker_func(pingArgs, pending, done):
 try:
  while True:
   # Get the next address to ping.
   address = pending.get_nowait()

   ping = subprocess.Popen(pingArgs + [address],
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE
   )
   out, error = ping.communicate()

   if re.match(r".*, 0% packet loss.*", out.replace("\n", "")):
    done.put(address)

   # Output the result to the 'done' queue.
 except Queue.Empty:
  # No more addresses.
  pass
 finally:
  # Tell the main thread that a worker is about to terminate.
  done.put(None)

# The number of workers.
NUM_WORKERS = 14

plat = platform.system()
scriptDir = sys.path[0]
hosts = os.path.join(scriptDir, 'hosts.txt')

# The arguments for the 'ping', excluding the address.
if plat == "Windows":
 pingArgs = ["ping", "-n", "1", "-l", "1", "-w", "100"]
elif plat == "Linux":
 pingArgs = ["ping", "-c", "1", "-l", "1", "-s", "1", "-W", "1"]
else:
 raise ValueError("Unknown platform")

# The queue of addresses to ping.
pending = Queue.Queue()

# The queue of results.
done = Queue.Queue()

# Create all the workers.
workers = []
for _ in range(NUM_WORKERS):
 workers.append(threading.Thread(target=worker_func, args=(pingArgs, pending, done)))

# Put all the addresses into the 'pending' queue.
for ip in list(ipaddress.ip_network(u"10.69.69.0/24").hosts()):
 pending.put(str(ip))

# Start all the workers.
for w in workers:
 w.daemon = True
 w.start()

# Print out the results as they arrive.

numTerminated = 0
while numTerminated < NUM_WORKERS:
 result = done.get()
 if result is None:
  # A worker is about to terminate.
  numTerminated += 1
 else:
  print result # print out the ok ip

# Wait for all the workers to terminate.
for w in workers:
 w.join()

另一种思路是利用资源池概念,直接调用gevent模块提供的异步功能。

资源池代码实现

这段代码源自公司内部Python专家的作品,本人仅为此主题做了少量调整。核心观点不变:只要代码具备实用价值且能持续运行,就是正确且值得采用的方案。

# -*- coding: utf-8 -*-

from gevent import subprocess
import itertools
from gevent.pool import Pool

pool = Pool(100) # concurrent action count

ips = itertools.product((10, ), (69, ), (69, ), range(1, 255))

def get_response_time(ip):
 try:
  out = subprocess.check_output('ping -c 1 -W 1 {}.{}.{}.{}'.format(*ip).split())
  for line in out.splitlines():
   if '0% packet loss' in line:
    return ip
 except subprocess.CalledProcessError:
  pass

 return None

resps = pool.map(get_response_time, ips)
reachable_resps = filter(lambda (ip): ip != None, resps)

for ip in reachable_resps:
 print ip

github目录:git@github.com:qcq/Code.git 下的子目录utils内部。

以上关于Python获取网段内ping通IP的方法即为全部内容,希望能对读者有所参考,也欢迎大家继续支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表