在 Python 中 Ping 服务器

Posted

技术标签:

【中文标题】在 Python 中 Ping 服务器【英文标题】:Pinging servers in Python 【发布时间】:2011-02-26 13:31:04 【问题描述】:

在 Python 中,有没有办法通过 ICMP ping 服务器,如果服务器响应则返回 TRUE,如果没有响应则返回 FALSE?

【问题讨论】:

相关:Ping a site in Python? 【参考方案1】:

我的 ping 函数版本:

适用于 Python 3.5 及更高版本、Windows 和 Linux。 在 Windows 上,如果 ping 命令失败并显示“目标主机无法访问”,则返回 False。 并且不显示任何输出,无论是作为弹出窗口还是在命令行中。
import platform, subprocess

def ping(host_or_ip, packets=1, timeout=1000):
    ''' Calls system "ping" command, returns True if ping succeeds.
    Required parameter: host_or_ip (str, address of host to ping)
    Optional parameters: packets (int, number of retries), timeout (int, ms to wait for response)
    Does not show any output, either as popup window or in command line.
    Python 3.5+, Windows and Linux compatible
    '''
    # The ping command is the same for Windows and Linux, except for the "number of packets" flag.
    if platform.system().lower() == 'windows':
        command = ['ping', '-n', str(packets), '-w', str(timeout), host_or_ip]
        # run parameters: capture output, discard error messages, do not show window
        result = subprocess.run(command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, creationflags=0x08000000)
        # 0x0800000 is a windows-only Popen flag to specify that a new process will not create a window.
        # On Python 3.7+, you can use a subprocess constant:
        #   result = subprocess.run(command, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
        # On windows 7+, ping returns 0 (ok) when host is not reachable; to be sure host is responding,
        # we search the text "TTL=" on the command output. If it's there, the ping really had a response.
        return result.returncode == 0 and b'TTL=' in result.stdout
    else:
        command = ['ping', '-c', str(packets), '-w', str(timeout), host_or_ip]
        # run parameters: discard output and error messages
        result = subprocess.run(command, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return result.returncode == 0

随意使用它。

【讨论】:

超时以秒为单位,而不是毫秒,因此默认值 1000 不太可能有用。请编辑为“1”。 @ratijas 超时参数必须以毫秒为单位,在 Windows 和 Linux 中。我刚刚查找了 Mac OS 命令,它使用秒数;但无论如何,我无法在 Mac 上测试它。【参考方案2】:

在 linux 上,无需 root(或 setuid 或 CAP_NET_RAW)即可创建 ICMP 数据报(非原始)套接字:https://unix.stackexchange.com/a/592914。我最终得到了

$ id
uid=1000(raylu) gid=1000(raylu) [...]
$ sudo sysctl net.ipv4.ping_group_range='1000 1000'
import socket
import struct
import time

def main():
    ping('192.168.1.10')

def ping(destination):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.getprotobyname('icmp'))
    sock.settimeout(10.0)
    start_time = time.time_ns() # python 3.7+ only

    payload = struct.pack('L', start_time)
    sock.sendto(encode(payload), (destination, 0))
    while (time.time_ns() - start_time) // 1_000_000_000 < 10:
        try:
            data, source = sock.recvfrom(256)
        except socket.timeout:
            print('timed out')
            return
        message_type, message_code, check, identifier, sequence_number = struct.unpack('bbHHh', data[:8])
        if source == (destination, 0) and message_type == ICMP.ECHO_REPLY and data[8:] == payload:
            print((time.time_ns() - start_time) // 1_000_000, 'ms')
            break
        else:
            print('got unexpected packet from %s:' % source[0], message_type, data[8:])
    else:
        print('timed out')

def encode(payload: bytes):
    # calculate checksum with check set to 0
    checksum = calc_checksum(icmp_header(ICMP.ECHO_REQUEST, 0, 0, 1, 1) + payload)
    # craft the packet again with the checksum set
    return icmp_header(ICMP.ECHO_REQUEST, 0, checksum, 1, 1) + payload

def icmp_header(message_type, message_code, check, identifier, sequence_number) -> bytes:
    return struct.pack('bbHHh', message_type, message_code, check, identifier, sequence_number)

def calc_checksum(data: bytes) -> int:
    '''RFC 1071'''
    # code stolen from https://github.com/alessandromaggio/pythonping/blob/a59ce65a/pythonping/icmp.py#L8
    '''
    MIT License

    Copyright (c) 2018 Alessandro Maggio

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
    '''
    subtotal = 0
    for i in range(0, len(data)-1, 2):
        subtotal += (data[i] << 8) + data[i+1]
    if len(data) % 2:
        subtotal += (data[len(data)-1] << 8)
    while subtotal >> 16:
        subtotal = (subtotal & 0xFFFF) + (subtotal >> 16)
    check = ~subtotal
    return ((check << 8) & 0xFF00) | ((check >> 8) & 0x00FF)

class ICMP:
    ECHO_REPLY = 0
    ECHO_REQUEST = 8

尽管其他答案在这里建议的许多软件包也可以使用

【讨论】:

【参考方案3】:

在 windows 或 linux 中 Ping 它们,返回一个排序列表。这是来自@Ahmed Essam 和@Arno 回复的混合/修复。

import asyncio
import re

import platform
isWindows = platform.system()


async def ping(host):
    cmd = 'ping   1'.format(host, '-n' if isWindows else '-c')
    ping_proc = \
        await asyncio.create_subprocess_shell(cmd, stdout=asyncio.subprocess.PIPE,
                                                      stderr=asyncio.subprocess.PIPE)
    stdout, stderr = await ping_proc.communicate()
    outstr = stdout.decode()

    if ping_proc.returncode == 0:
        delay = int(re.search(r'(?:time=)([\d]*)', outstr).group(1)) if 'time=' in outstr else -1
        if delay >= 0:
            # print(' ms'.format(host, delay))
            return [host, delay]

    return [host, None]


async def ping_all():
    tasks = []

    for i in range(1, 256):
        ip = "192.168.1.".format(i)
        task = asyncio.ensure_future(ping(ip))
        tasks.append(task)

    retList = await asyncio.gather(*tasks, return_exceptions=True)
    retList = [x for x in retList if x[1] is not None]
    retList.sort(key=lambda x: int(x[0].split('.')[-1]))

    return retList


loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
pingRet = loop.run_until_complete(ping_all())

for ip, d in pingRet:
    print(':<16s ms'.format(ip, d))

【讨论】:

【参考方案4】:

在python3中使用socket包:

import socket

def ping_server(server: str, port: int, timeout=3):
    """ping server"""
    try:
        socket.setdefaulttimeout(timeout)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((server, port))
    except OSError as error:
        return False
    else:
        s.close()
        return True

【讨论】:

不是 ICMP,而是当您不能依赖底层操作系统调用时测试连接的好方法。并且紧凑。【参考方案5】:

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

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

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

【讨论】:

因为编辑需要root权限,这里讨论解除这个问题:github.com/kyan001/ping3/issues/10 哦,安装和执行都需要root权限:ping("example.com") 这不需要 sudo 来执行。我正在运行 python 3.8.10【参考方案6】:

我需要更快的 ping 扫描并且我不想使用任何外部库,所以我决定使用内置 asyncio 来使用并发。

此代码需要 python 3.7+,并且仅在 Linux 上制作和测试。它不能在 Windows 上运行,但我相信您可以轻松地将其更改为在 Windows 上运行。

我不是asyncio 的专家,但我使用了这篇很棒的文章Speed Up Your Python Program With Concurrency 并想出了这些代码行。我试图让它尽可能简单,所以很可能你需要添加更多代码来满足你的需要。

它不返回true或false,我认为让它打印响应ping请求的IP会更方便。我认为它非常快,在近 10 秒内 ping 255 ips。

#!/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 会先打印。

【讨论】:

【参考方案7】:

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

编辑: 由 @radato os.system 替换为 subprocess.call。这可以避免在您的主机名字符串可能未验证的情况下出现shell injection 漏洞。

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,如果您收到 Destination Host Unreachable 错误,此函数仍将返回 True

说明

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

platform.system() 返回平台名称。前任。 'Darwin' 在 macOS 上。subprocess.call() 执行系统调用。前任。 subprocess.call(['ls','-l'])

【讨论】:

请注意,如果您收到来自其他主机的“目标主机无法访问”回复,这仍会返回 true(在 Windows 上)。 我发现我的调制解调器关闭时偶尔会 ping 成功???这是在 Windows 10 操作系统上测试“8.8.8.8”和“google.com”。有些地方不太对劲。 这不可能发生@Markus。请用上面代码的修改版本手动测试,然后告诉我们结果。手动:1)打开cmd 2)ping 8.8.8.8 -n 1 3)echo %ERRORLEVEL%。代码:将Python代码的最后一行修改为return system_call(command)。通过正确的连接,您将获得 0(零)。关闭调制解调器后,您必须得到一些错误代码。当然,两种方法必须在相同的条件下返回相同的错误码。 它确实发生了,我使用的是准确的代码,一个字一个字。我理解并相信您的 cmets,在没有连接的情况下,命令行 ping 无法成功,因此我认为在 python 到命令行操作中某些东西无法正常工作。我会尝试更新,看看效果如何。谢谢。 我可以确认 windows ping 命令的返回值是骗人的。我正在 ping 一个已断开网络连接的系统,另一个 IP 响应它不可用,但我得到 0% 的丢失和 0 的 ERRORLEVEL。这是结果的粘贴pastebin.pl/view/2437bb7c【参考方案8】:

我使用这篇文章中答案的想法进行了简化,但只使用了较新的推荐子流程模块和 python3:

import subprocess
import platform

operating_sys = platform.system()
nas = '192.168.0.10'

def ping(ip):
    # ping_command = ['ping', ip, '-n', '1'] instead of ping_command = ['ping', ip, '-n 1'] for Windows
    ping_command = ['ping', ip, '-n', '1'] if operating_sys == 'Windows' else ['ping', ip, '-c 1']
    shell_needed = True if operating_sys == 'Windows' else False

    ping_output = subprocess.run(ping_command,shell=shell_needed,stdout=subprocess.PIPE)
    success = ping_output.returncode
    return True if success == 0 else False

out = ping(nas)
print(out)

【讨论】:

您不需要使用True if condition else False 根据条件返回 True 或 False。只需使用例如shell_needed = operating_sys == 'Windows'return success == 0【参考方案9】:

有一个名为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))

【讨论】:

"请注意,ICMP 消息只能从以 root 身份运行的进程发送(在 Windows 中,您必须以“管理员”身份运行此脚本)。" 我喜欢你可以指定发送的 ICMP 请求的超时和计数。我能够编写一个脚本来发现本地子网上的所有主机。它在 1 秒内执行,而不是使用 os.system('ping -c 1 -t 1 hostname') 解决方案的 255 秒。另外,与使用 TCP/IP 套接字库相比,pyping 库非常易于使用。我使用这两种方法编写了我的 ping 程序,在我看来,pyping 使用起来更快、更容易,尤其是在不熟悉使用 TCP/IP 套接字库的情况下。 不适用于 py3。 ModuleNotFoundError:没有名为“核心”的模块 “核心”错误来自与 python3 的不兼容。我试图为 python3 修复它,但它不断向我发送错误。作者和项目 github 页面已关闭(未找到 404)。我们必须自己将它移植到 python3 :-) 对于 python3 尝试 ping3:github.com/kyan001/ping3pip install ping3【参考方案10】:

我从其他答案中借用。尝试简化和最小化查询。

import platform, os

def ping(host):
    result = os.popen(' '.join(("ping", ping.param, host))).read()
    return 'TTL=' in result

ping.param = "-n 1" if platform.system().lower() == "windows" else "-c 1"

【讨论】:

【参考方案11】:

这是一个使用 Python 的 subprocess 模块和底层操作系统提供的 ping CLI 工具的解决方案。在 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

【讨论】:

【参考方案12】:

使用 Multi-ping (pip install multiPing) 我制作了这个简单的代码(如果你愿意,只需复制和粘贴!):

from multiping import MultiPing

def ping(host,n = 0):
    if(n>0):
        avg = 0
        for i in range (n):
            avg += ping(host)
        avg = avg/n
    # Create a MultiPing object to test hosts / addresses
    mp = MultiPing([host])

    # Send the pings to those addresses
    mp.send()

    # With a 1 second timout, wait for responses (may return sooner if all
    # results are received).
    responses, no_responses = mp.receive(1)


    for addr, rtt in responses.items():
        RTT = rtt


    if no_responses:
        # Sending pings once more, but just to those addresses that have not
        # responded, yet.
        mp.send()
        responses, no_responses = mp.receive(1)
        RTT = -1

    return RTT

用法:

#Getting the latency average (in seconds) of host '192.168.0.123' using 10 samples
ping('192.168.0.123',10)

如果要单个样本,第二个参数“10”可以忽略!

希望对你有帮助!

【讨论】:

很棒的库,但需要 root 权限。【参考方案13】:

仅限 WINDOWS - 不敢相信没有人破解过 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'

sample output

【讨论】:

【参考方案14】:

很多答案遗漏的一件事是(至少在 Windows 中)ping 命令在收到回复“目标主机无法访问”时返回 0(表示成功)。

这是我检查b'TTL=' 是否在响应中的代码,因为它仅在 ping 到达主机时出现。注意:此代码大部分基于此处的其他答案。

import platform
import subprocess

def ping(ipAddr, timeout=100):
    '''
    Send a ping packet to the specified host, using the system ping command.
    Accepts ipAddr as string for the ping destination.
    Accepts timeout in ms for the ping timeout.
    Returns True if ping succeeds otherwise Returns False.
        Ping succeeds if it returns 0 and the output includes b'TTL='
    '''
    if platform.system().lower() == 'windows':
        numFlag = '-n'
    else:
        numFlag = '-c'
    completedPing = subprocess.run(['ping', numFlag, '1', '-w', str(timeout), ipAddr],
                                   stdout=subprocess.PIPE,    # Capture standard out
                                   stderr=subprocess.STDOUT)  # Capture standard error
    # print(completedPing.stdout)
    return (completedPing.returncode == 0) and (b'TTL=' in completedPing.stdout)

print(ping('google.com'))

注意:这会捕获输出而不是打印它,因此如果您想查看ping 的输出,则需要在返回之前打印completedPing.stdout

【讨论】:

【参考方案15】:

由于发送原始 ICMP 数据包需要提升权限,因此编程 ICMP ping 很复杂,并且调用 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 连接并立即断开它,测量经过的时间。这个特定的实现有一点限制,因为它不处理关闭的端口,但对于您自己的服务器,它工作得很好。

【讨论】:

这种策略在服务器有防火墙会丢弃真正的 ICMP ping 时也很有用!另外,这里是 GitHub 页面:github.com/zhengxiaowai/tcping【参考方案16】:

我解决了这个问题:

def ping(self, host):
    res = False

    ping_param = "-n 1" if system_name().lower() == "windows" else "-c 1"

    resultado = os.popen("ping " + ping_param + " " + host).read()

    if "TTL=" in resultado:
        res = True
    return res

“TTL” 是了解 ping 是否正确的方法。 萨鲁多斯

【讨论】:

【参考方案17】:

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

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

这里提到的许多解决方案都需要执行到命令行实用程序。如果您需要监控大量 IP 地址,这将非常低效且占用大量资源。 其他人提到了一些较旧的 python ping 模块。我查看了这些,最后,它们都存在一些问题(例如未正确设置数据包 ID)并且没有处理大量地址的 ping。

【讨论】:

不错的工作伙伴!如果有人想看到它的实际效果,只需使用github.com/romana/multi-ping/blob/master/demo.py 值得一提的是,这也需要root权限。【参考方案18】:

因为我想让我的 Python 程序在 2.7 和 3.x 版本以及 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"))

【讨论】:

您当然也可以使用platform.system().lower() != "windows",而不是False if platform.system().lower()=="windows" else True os.name!="nt" 也不起作用吗?诚然,我没有在所有版本/平台组合上都尝试过! 在我的情况下,默认网关返回“无法访问”消息,但 windows ping 命令的返回码仍然为 0。所以这种方法有效(抱歉格式化 - 它的 6 行,包括函数声明):def ping(host): process = subprocess.Popen(["ping", "-n", "1",host], stdout=subprocess.PIPE, stderr=subprocess.PIPE) streamdata = process.communicate()[0] if 'unreachable' in str(streamdata): return 1 return process.returncode @wellspokenman 如果在管道中找到unreachable,您宁愿返回 0,不是吗? @beeb 是的,我也这样做了,但忘记更新评论了。我当前的函数如下所示:pastebin.com/FEYWsVjK【参考方案19】:

我最终发现了这个关于类似情况的问题。我尝试了 pyping,但 Naveen 给出的示例在 Python 2.7 下的 Windows 中对我不起作用。

一个对我有用的例子是:

import pyping

response = pyping.send('Your IP')

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

【讨论】:

pyping 似乎不是标准模块。或许你可以提供一个链接?【参考方案20】:

确保 pyping 已安装或安装 pip install pyping

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

if response.ret_code == 0:
    print("reachable")
else:
    print("unreachable")

【讨论】:

谢谢!但是,我需要以 root 身份运行此代码才能使其工作。 Pyping 的 GitHub 页面 no longer exists 和 PyPI package 自 2016 年以来未更新。 我收到以下错误:import pyping Traceback(最近一次调用最后一次):文件“”,第 1 行,在 文件“/usr/local/lib/python3.6/ dist-packages/pyping/__init__.py",第 3 行,在 中来自核心导入 * ModuleNotFoundError: No module named 'core'【参考方案21】:

此脚本适用于 Windows,并且应该适用于其他操作系统: 它适用于 Windows、Debian 和 macosx,需要在 solaris 上测试。

import os
import platform


def isUp(hostname):

    giveFeedback = False

    if platform.system() == "Windows":
        response = os.system("ping "+hostname+" -n 1")
    else:
        response = os.system("ping -c 1 " + hostname)

    isUpBool = False
    if response == 0:
        if giveFeedback:
            print hostname, 'is up!'
        isUpBool = True
    else:
        if giveFeedback:
            print hostname, 'is down!'

    return isUpBool

print(isUp("example.com")) #Example domain
print(isUp("localhost")) #Your computer
print(isUp("invalid.example.com")) #Unresolvable hostname: https://tools.ietf.org/html/rfc6761
print(isUp("192.168.1.1")) #Pings local router
print(isUp("192.168.1.135")) #Pings a local computer - will differ for your network

【讨论】:

好答案。此处无需 Windows 管理员权限。 无论是正确的还是错误的 IP,我都接受 True 是的,这绝对行不通。只是在 Windows 上返回 :"true" 【参考方案22】:

我有类似的要求,所以我实现了它,如下所示。它在 Windows 64 位和 Linux 上进行了测试。

import subprocess
def systemCommand(Command):
    Output = ""
    Error = ""     
    try:
        Output = subprocess.check_output(Command,stderr = subprocess.STDOUT,shell='True')
    except subprocess.CalledProcessError as e:
        #Invalid command raises this exception
        Error =  e.output 

    if Output:
        Stdout = Output.split("\n")
    else:
        Stdout = []
    if Error:
        Stderr = Error.split("\n")
    else:
        Stderr = []

    return (Stdout,Stderr)

#in main
Host = "ip to ping"
NoOfPackets = 2
Timeout = 5000 #in milliseconds
#Command for windows
Command = 'ping -n 0 -w 1 2'.format(NoOfPackets,Timeout,Host)
#Command for linux 
#Command = 'ping -c 0 -w 1 2'.format(NoOfPackets,Timeout,Host)
Stdout,Stderr = systemCommand(Command)
if Stdout:
   print("Host [] is reachable.".format(Host))
else:
   print("Host [] is unreachable.".format(Host))

当 IP 不可访问时 subprocess.check_output() 会引发异常。可以通过从输出行“数据包:已发送 = 2,已接收 = 2,丢失 = 0(0% 丢失)”中提取信息来完成额外的验证。

【讨论】:

【参考方案23】:

使用它在 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

【讨论】:

【参考方案24】:

看起来很简单,但很适合我。我不断收到“不允许 icmp 打开套接字操作”,否则如果服务器离线,解决方案将挂起。但是,如果您想知道服务器是否处于活动状态并且您正在该服务器上运行 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

【讨论】:

【参考方案25】:
#!/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()

【讨论】:

此代码可能有问题的答案,但添加一些 cmets 或解释您的代码如何解决问题会有所帮助。【参考方案26】:
#!/usr/bin/python3

import subprocess as sp

ip = "192.168.122.60"
status,result = sp.getstatusoutput("ping -c1 -w2 " + ip)

if status == 0: 
    print("System " + ip + " is UP !")
else:
    print("System " + ip + " is DOWN !")

【讨论】:

【参考方案27】:
  1 #!/usr/bin/python
  2
  3 import os
  4 import sys
  5 import time
  6
  7 os.system("clear")
  8 home_network = "172.16.23."
  9 mine = []
 10
 11 for i in range(1, 256):
 12         z =  home_network + str(i)
 13         result = os.system("ping -c 1 "+ str(z))
 14         os.system("clear")
 15         if result == 0:
 16                 mine.append(z)
 17
 18 for j in mine:
 19         print "host ", j ," is up"

我刚在一分钟内完成的一个简单的..使用 icmplib 需要 root 权限,下面的效果很好! 高温

【讨论】:

【参考方案28】:

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

【讨论】:

我最终得到了这个变种response = os.system("ping -c 1 -w2 " + hostname + " &gt; /dev/null 2&gt;&amp;1") @jeckyll2hide man ping,仅发送 1 个截止日期为 2 秒的数据包并将所有输出重定向到 /dev/null,仅检索返回值。 -w 和 -W 以秒为单位而不是毫秒。检查man ping 以确保。 如果你从用户那里得到hostname 字符串,他们可以很容易地通过给你一个像'google.com; rm -rf /*' 这样的“url”来入侵你的服务器。请改用subprocess.run(["ping", "-c", "1", hostname]).returncode 这是我的 Python 3.6 解决方案,使用较新的 subprocess.run: command = ["ping", "-c", "1", "-w2", host] return subprocess.run(args=command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0【参考方案29】:
import subprocess
ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "192.168.0.1"], stdout=subprocess.PIPE).stdout.read()

【讨论】:

唯一的问题是它不能在 Windows 上运行。 值得一提的是,之所以需要这样做是因为ICMP需要root,而/bin/ping通过设置SUID来解决这个问题。 注意:如果 ping 位于不同的位置,可能会失败。使用whereis ping 获取正确的路径。 这适用于 Windows:ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read() 如何解析结果以检查 Windows 中的响应是 ok 还是 ko?

以上是关于在 Python 中 Ping 服务器的主要内容,如果未能解决你的问题,请参考以下文章

python 批量ping服务器

Discord Bot 在被烧瓶服务器 ping 后总是说它在线很多次 - PYTHON

Python集成网络诊断小工具(含有ping,tracert,tcping等小工具)

用 Python ping 一个站点?

Python 实现Ping命令状态检测

Python websockets keepalive ping 超时;没有收到关闭帧