shirley
回答者
回答于 2026-10-24
使用Python的subprocess模块调用操作系统的ping命令,遍历目标网段的IP地址,根据返回码判断设备是否在线。
基础实现代码
import subprocess
import platform
def ping_host(ip):
# Windows使用-n参数,Linux/macOS使用-c参数
param = '-n' if platform.system().lower() == 'windows' else '-c'
command = ['ping', param, '1', '-w', '1000', ip]
result = subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return result.returncode == 0
def scan_network(subnet):
online_hosts = []
for i in range(1, 255):
ip = f"{subnet}.{i}"
if ping_host(ip):
online_hosts.append(ip)
print(f"[+] {ip} 在线")
else:
print(f"[-] {ip} 离线")
return online_hosts
if __name__ == "__main__":
subnet = "192.168.1" # 替换为实际局域网网段
scan_network(subnet)
多线程优化版本
逐个ping耗时较长,可使用concurrent.futures.ThreadPoolExecutor并发执行:
import subprocess
import platform
from concurrent.futures import ThreadPoolExecutor
def ping_host(ip):
param = '-n' if platform.system().lower() == 'windows' else '-c'
command = ['ping', param, '1', '-w', '1000', ip]
result = subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return (ip, result.returncode == 0)
def fast_scan(subnet):
ips = [f"{subnet}.{i}" for i in range(1, 255)]
with ThreadPoolExecutor(max_workers=50) as executor:
results = executor.map(ping_host, ips)
for ip, is_online in results:
if is_online:
print(f"[+] {ip} 在线")
if __name__ == "__main__":
fast_scan("192.168.1")
步骤说明
- 确定网段:获取本机IP与子网掩码,确认需要扫描的网段前缀(如
192.168.1)。 - 构造ping命令:通过
platform模块识别操作系统,选择对应的ping参数(Windows用-n,类Unix用-c)。 - 执行并判断:利用
subprocess.run执行命令,returncode为0表示收到响应,设备在线。 - 并发提速:使用线程池同时发起多个ping请求,大幅缩短整体扫描时间。
判断依据
ping命令成功收到ICMP回显应答时,进程退出码为0;超时或不可达时为非0值。
适用条件
- 目标设备未禁用ICMP协议(防火墙未拦截ping请求)。
- 运行脚本的主机与目标设备处于同一广播域或路由可达的子网内。
常见误区
- 忽略跨平台差异:直接硬编码
ping -c在Windows上会报错,必须区分操作系统。 - 单线程阻塞:默认ping超时常为数秒,串行扫描254个IP可能耗时数分钟,应使用多线程或多进程。
- 误判离线:部分主机防火墙配置为丢弃ICMP包,此时设备实际在线但ping不通,需结合ARP扫描(如
scapy库)作为补充手段。 - 权限问题:在某些Linux发行版中,非root用户发送原始套接字可能受限,但普通ping命令通常无需提权。