在Python中,是否有一种方法可以通过ICMP来ping服务器,如果服务器响应则返回TRUE,如果没有响应则返回FALSE ?


当前回答

下面是一个使用Python的子进程模块和底层操作系统提供的ping CLI工具的解决方案。在Windows和Linux上测试。支持设置网络超时。不需要根权限(至少在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

其他回答

如果你不需要支持Windows,这里有一个非常简洁的方法:

import os
hostname = "google.com" #example
response = os.system("ping -c 1 " + hostname)

#and then check the response...
if response == 0:
  print hostname, 'is up!'
else:
  print hostname, 'is down!'

这是因为如果连接失败,ping将返回一个非零值。(实际返回值因网络错误而异。)您还可以使用'-t'选项更改ping超时(以秒为单位)。注意,这将向控制台输出文本。

#!/usr/bin/python3

import subprocess as sp

def ipcheck():
    status,result = sp.getstatusoutput("ping -c1 -w2 " + str(pop))
    if status == 0:
        print("System " + str(pop) + " is UP !")
    else:
        print("System " + str(pop) + " is DOWN !")


pop = input("Enter the ip address: ")
ipcheck()

编程ICMP ping很复杂,因为发送原始ICMP包需要更高的权限,而且调用ping二进制很难看。对于服务器监控,您可以使用TCP ping技术实现相同的结果:

# pip3 install tcping
>>> from tcping import Ping
# Ping(host, port, timeout)
>>> ping = Ping('212.69.63.54', 22, 60)
>>> ping.ping(3)
Connected to 212.69.63.54[:22]: seq=1 time=23.71 ms
Connected to 212.69.63.54[:22]: seq=2 time=24.38 ms
Connected to 212.69.63.54[:22]: seq=3 time=24.00 ms

在内部,这只是建立一个到目标服务器的TCP连接,并立即丢弃它,测量所消耗的时间。这个特殊的实现有点局限,因为它不能处理封闭的端口,但对于您自己的服务器来说,它工作得很好。

在四处寻找之后,我最终编写了自己的ping模块,该模块旨在监视大量地址,是异步的,并且不使用大量系统资源。你可以在这里找到它:https://github.com/romana/multi-ping/它是Apache授权的,所以你可以在你的项目中以任何你认为合适的方式使用它。

实施我自己的方法的主要原因是其他方法的限制:

这里提到的许多解决方案都需要将exec输出到命令行实用程序。如果您需要监控大量的IP地址,这是非常低效和资源消耗的。 其他人提到了一些较老的python ping模块。我看了这些,最后,他们都有这样或那样的问题(比如没有正确设置数据包id),不能处理大量地址的ping-ing。

对于python3,有一个非常简单方便的python模块ping3:(pip安装ping3,需要root权限)。

from ping3 import ping, verbose_ping
ping('example.com')  # Returns delay in seconds.
>>> 0.215697261510079666

这个模块还允许自定义一些参数。