使用此代码,已在Python 2.7上测试通过并且正常工作。如果成功,它会返回ping时间(以毫秒为单位),如果失败则返回False。
import platform,subproccess,re
def Ping(hostname,timeout):
if platform.system() == "Windows":
command="ping "+hostname+" -n 1 -w "+str(timeout*1000)
else:
command="ping -i "+str(timeout)+" -c 1 " + hostname
proccess = subprocess.Popen(command, stdout=subprocess.PIPE)
matches=re.match('.*time=([0-9]+)ms.*', proccess.stdout.read(),re.DOTALL)
if matches:
return matches.group(1)
else:
return False
看起来很简单,但让我头疼不已。我一直收到“icmp open socket operation not permitted”的错误提示,或者如果服务器离线,解决方案就会卡住。然而,如果您想知道服务器是否存活,并且在该服务器上运行Web服务器,则curl可以完成任务。如果您拥有ssh和证书,则ssh和一个简单的命令就足够了。这是代码:
from easyprocess import EasyProcess # as root: pip install EasyProcess
def ping(ip):
ping="ssh %s date;exit"%(ip) # test ssh alive or
ping="curl -IL %s"%(ip) # test if http alive
response=len(EasyProcess(ping).call(timeout=2).stdout)
return response #integer 0 if no response in 2 seconds
这里有一个使用Python的subprocess
模块和底层操作系统提供的ping
命令行工具的解决方案。已在Windows和Linux上进行了测试。支持设置网络超时时间。不需要root权限(至少在Windows和Linux上)。
import platform
import subprocess
def ping(host, network_timeout=3):
"""Send a ping packet to the specified host, using the system "ping" command."""
args = [
'ping'
]
platform_os = platform.system().lower()
if platform_os == 'windows':
args.extend(['-n', '1'])
args.extend(['-w', str(network_timeout * 1000)])
elif platform_os in ('linux', 'darwin'):
args.extend(['-c', '1'])
args.extend(['-W', str(network_timeout)])
else:
raise NotImplemented('Unsupported OS: {}'.format(platform_os))
args.append(host)
try:
if platform_os == 'windows':
output = subprocess.run(args, check=True, universal_newlines=True).stdout
if output and 'TTL' not in output:
return False
else:
subprocess.run(args, check=True)
return True
except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
return False
以下是我借鉴他人答案的观点。尝试简化和最小化查询。
import platform, os
def ping(host):
result = os.popen(' '.join(("ping", ping.param, host))).read()
return 'ttl=' in result.lower()
ping.param = "-n 1" if platform.system().lower() == "windows" else "-c 1"
编辑:根据Olivier B.的评论,返回时忽略大小写。
return 'TTL=' in result or 'ttl=' in result
- Olivier B.import wmi
# new WMI object
c = wmi.WMI()
# here is where the ping actually is triggered
x = c.Win32_PingStatus(Address='google.com')
# how big is this thing? - 1 element
print 'length x: ' ,len(x)
#lets look at the object 'WMI Object:\n'
print x
#print out the whole returned object
# only x[0] element has values in it
print '\nPrint Whole Object - can directly reference the field names:\n'
for i in x:
print i
#just a single field in the object - Method 1
print 'Method 1 ( i is actually x[0] ) :'
for i in x:
print 'Response:\t', i.ResponseTime, 'ms'
print 'TTL:\t', i.TimeToLive
#or better yet directly access the field you want
print '\npinged ', x[0].ProtocolAddress, ' and got reply in ', x[0].ResponseTime, 'ms'
我最终发现了一个关于类似情况的问题。我尝试了使用pyping,但是Naveen提供的示例在Windows下的Python 2.7中并没有起作用。
对我有用的示例是:
import pyping
response = pyping.send('Your IP')
if response['ret_code'] == 0:
print("reachable")
else:
print("unreachable")
import os #to get clear screen
import subprocess as sp #to get system ping
os.system("clear") #clear screen
print('Wait or Press Ctrl+Z to Terminate\n') #notice to terminate or wait
for i in range(255): #0 to 255 loop
ip='192.168.1.'+str(i) #concatenating str and int
s,r=sp.getstatusoutput("ping -c1 -w2 " + ip) #ping and store status in s
if s==0: #if status is 0 equal to pass
print(ip+" is UP ✓ ") #output
else: #if status is not 0 equal to fail
pass #skip and try next ip from loop
我需要更快的ping扫描,而且不想使用任何外部库,所以我决定使用内置的asyncio
来实现并发。
此代码要求Python 3.7+,并且仅在Linux上制作和测试。它不能在Windows上运行,但我相信您可以轻松地更改它以在Windows上运行。
虽然我不是asyncio
的专家,但我使用了这篇很棒的文章Speed Up Your Python Program With Concurrency,并编写了以下代码。我试图使它尽可能简单,因此您很可能需要添加更多代码以适应您的需求。
它不返回true或false,我认为只将响应ping请求的IP打印出来会更方便。我认为它非常快,几乎可以在10秒内ping255个IP地址。
#!/usr/bin/python3
import asyncio
async def ping(host):
"""
Prints the hosts that respond to ping request
"""
ping_process = await asyncio.create_subprocess_shell("ping -c 1 " + host + " > /dev/null 2>&1")
await ping_process.wait()
if ping_process.returncode == 0:
print(host)
return
async def ping_all():
tasks = []
for i in range(1,255):
ip = "192.168.1.{}".format(i)
task = asyncio.ensure_future(ping(ip))
tasks.append(task)
await asyncio.gather(*tasks, return_exceptions = True)
asyncio.run(ping_all())
示例输出:
192.168.1.1
192.168.1.3
192.168.1.102
192.168.1.106
192.168.1.6
from tcppinglib import tcpping
tcpping('example.com', 443, 1, 1).is_alive
结合上面几个答案,我有自己的方法:
def ping(host, show_log=False, package_count=1):
ping.param = "-n" if platform.system().lower() == 'windows' else "-c"
result = subprocess.run(['ping', ping.param, str(package_count), host],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = result.stdout
if show_log:
print('return code: ', result.returncode)
print(output.decode("utf-8"))
return result.returncode == 0 and (b'TTL=' in output or b'ttl=' in output)
在OSX Monterey上进行了测试。