在Python中对服务器进行ping测试

265
在Python中,是否有一种通过ICMP对服务器进行ping并在服务器响应时返回TRUE,或者在无响应时返回FALSE的方法?

33个回答

2

使用此代码,已在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

2

看起来很简单,但让我头疼不已。我一直收到“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

2

这里有一个使用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

2

以下是我借鉴他人答案的观点。尝试简化和最小化查询。

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.的评论,返回时忽略大小写。


1
这似乎很好用,但在OSX上ping命令输出中ttl是小写的,所以为了使其正常工作,您需要使用以下代码: return 'TTL=' in result or 'ttl=' in result - Olivier B.

2
WINDOWS ONLY - 真不敢相信还没有人破解Win32_PingStatus 使用一个简单的WMI查询,我们可以免费获取一个包含非常详细信息的对象
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'

样本输出


这个非常好用,简单干净,而且返回的对象包含各种有用的信息。 - LeafTeaNeko

2

我最终发现了一个关于类似情况的问题。我尝试了使用pyping,但是Naveen提供的示例在Windows下的Python 2.7中并没有起作用。

对我有用的示例是:

import pyping

response = pyping.send('Your IP')

if response['ret_code'] == 0:
    print("reachable")
else:
    print("unreachable")

2
“pyping”似乎不是标准模块。也许您可以提供一个链接? - Mawg says reinstate Monica

2
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

2

我需要更快的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

请注意,IP地址并不是按顺序排列的,因为IP地址在回复后立即打印,所以先响应的IP地址会先被打印出来。

2
我想到的唯一勉强令人满意的解决方案是这样的:
from tcppinglib import tcpping
tcpping('example.com', 443, 1, 1).is_alive

适用于Windows和Linux操作系统,通过简单的套接字使用非特权账户运行。
显然还支持异步/多个"ping"。

https://pypi.org/project/tcppinglib/


1

结合上面几个答案,我有自己的方法:


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上进行了测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接