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


当前回答

有一个名为pyping的模块可以做到这一点。可以用pip安装

pip install pyping

它使用起来非常简单,但是,当使用这个模块时,您需要root访问权限,因为它在底层制作原始数据包。

import pyping

r = pyping.ping('google.com')

if r.ret_code == 0:
    print("Success")
else:
    print("Failed with {}".format(r.ret_code))

其他回答

import subprocess
ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "192.168.0.1"], stdout=subprocess.PIPE).stdout.read()

因为我喜欢让我的Python程序在2.7和3版本上通用。在Linux, Mac OS和Windows平台上,我必须修改现有的示例。

# shebang does not work over all platforms
# ping.py  2016-02-25 Rudolf
# subprocess.call() is preferred to os.system()
# works under Python 2.7 and 3.4
# works under Linux, Mac OS, Windows

def ping(host):
    """
    Returns True if host responds to a ping request
    """
    import subprocess, platform

    # Ping parameters as function of OS
    ping_str = "-n 1" if  platform.system().lower()=="windows" else "-c 1"
    args = "ping " + " " + ping_str + " " + host
    need_sh = False if  platform.system().lower()=="windows" else True

    # Ping
    return subprocess.call(args, shell=need_sh) == 0

# test call
print(ping("192.168.17.142"))

编程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连接,并立即丢弃它,测量所消耗的时间。这个特殊的实现有点局限,因为它不能处理封闭的端口,但对于您自己的服务器来说,它工作得很好。

如果你不需要支持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超时(以秒为单位)。注意,这将向控制台输出文本。

此函数适用于任何操作系统(Unix、Linux、macOS和Windows) Python 2和Python 3

编辑: @radato os。System被subprocess.call取代。这避免了在没有验证主机名字符串的情况下shell注入漏洞。

import platform    # For getting the operating system name
import subprocess  # For executing a shell command

def ping(host):
    """
    Returns True if host (str) responds to a ping request.
    Remember that a host may not respond to a ping (ICMP) request even if the host name is valid.
    """

    # Option for the number of packets as a function of
    param = '-n' if platform.system().lower()=='windows' else '-c'

    # Building the command. Ex: "ping -c 1 google.com"
    command = ['ping', param, '1', host]

    return subprocess.call(command) == 0

注意,根据Windows上的@ikrase,如果你得到一个目标主机不可达错误,这个函数仍然会返回True。

解释

该命令在Windows和类unix系统中都是ping。 选项-n (Windows)或-c (Unix)控制包的数量,在本例中设置为1。

platform.system()返回平台名称。前女友。macOS上的“达尔文”。 Subprocess.call()执行一个系统调用。例如subprocess.call ([' ls ', ' - l '])。