用Python ping服务器


Answers:


112

此功能可在任何操作系统(Unix,Linux,macOS和Windows)
Python 2和Python 3中使用

编辑:
@radato os.system替换为subprocess.call。这样可以避免在主机名字符串可能未经验证的情况下出现外壳注入漏洞。

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

说明

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

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


14
请注意,如果您从其他主机收到“目标主机无法访问”的答复,则该消息仍将返回true(在Windows上)。
ikrase

我发现我的调制解调器关闭时偶尔会获得ping成功???在Windows 10操作系统上测试“ 8.8.8.8”和“ google.com”。不太正确。
马库斯

这不会发生@Markus。请手动进行测试,并使用上面代码的修改版本,然后将结果告知我们。手动:1)打开cmd 2)ping 8.8.8.8 -n 13)echo %ERRORLEVEL%。代码:将Python代码的最后一行修改为return system_call(command)。有了正确的连接,您将得到0(零)。关闭调制解调器后,您必须获取一些错误代码。当然,这两种方法必须在相同条件下返回相同的错误代码。
ePi272314

它的确发生了,我在逐字地使用确切的代码。我理解并相信您的评论,当没有连接时,命令行ping无法成功,因此我认为python至命令行操作中的某些操作无法正常进行。我将尝试更新,看看它如何进行。谢谢。
马库斯

@Markus看到ikrase的评论。
鲍里斯

163

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


42
我最终得到了这个变体response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
MGP

4
@ jeckyll2hide man ping,仅发送1个数据包,最后期限为2秒,然后将所有输出重定向到/ dev / null,仅获取返回值。
MGP 2014年

@ManuelGutierrez我认为您想要“ -W 2000”(2000毫秒后超时),也许是“ -t 3”(3秒后退出,无论如何)
优柔寡断2014年

1
-w和-W以秒为单位而不是毫秒。检查man ping以确保。
艾伦·图灵

7
如果您hostname从用户那里获得字符串,他们可以通过给您一个类似的“ url”来轻松地入侵您的服务器'google.com; rm -rf /*'。使用subprocess.run(["ping", "-c", "1", hostname]).returncode代替。
鲍里斯(Boris)

38

有一个叫做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))

4
“请注意,ICMP消息只能从以root身份运行的进程发送(在Windows中,您必须以'Administrator'身份运行此脚本)。”
本·海德

1
我喜欢您可以指定发送的ICMP请求的超时和计数。我能够编写一个脚本来发现本地子网上的所有主机。使用该os.system('ping -c 1 -t 1 hostname')解决方案,它将在1秒内执行,而不是255秒。pyping与使用TCP / IP套接字库相比,该库非常易于使用。我认为我pyping是同时使用这两种方法编写ping程序的,并且据我所知,它更快捷,更容易使用,尤其是在不熟悉使用TCP / IP套接字库的情况下。
MikeyE

10
不适用于py3。ModuleNotFoundError:没有名为“核心”的模块
alireza

2
“核心”错误来自与python3不兼容。我试图为python3修复它,但它不断向我发送错误。作者和项目github页已关闭(找不到404)。我们必须将其自己移植到python3 :-)
Andre

6
对于python3,请尝试ping3:github.com/kyan001/ping3 pip install ping3
beep_check

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

6
唯一的问题是它将无法在Windows上运行。
Kudu 2010年

8
应该提到的是,诸如此类的必要原因是ICMP需要root,而/ bin / ping可以通过设置SUID来解决。
Catskul

1
注意:如果ping位于其他位置,则可能会失败。使用whereis ping以获得正确的路径。
2013年

4
此功能适用于Windows:ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
Victor Lellis 2015年

1
如何在Windows中解析结果以检查响应是否正常?
皮托2015年

15

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

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

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


2
编辑后需要root用户特权,请在此处进行讨论以进行讨论:github.com/kyan001/ping3/issues/10
Dimitrios Mistriotis

1
哦,不仅需要root特权进行安装,而且还需要执行:ping(“ example.com”)
钟钟忠

14

因为我希望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"))

1
False if platform.system().lower()=="windows" else True当然,也可以使用代替您platform.system().lower() != "windows"
Frerich Raabe

os.name!="nt"还工作吗?诚然,我还没有在所有ver / platform组合上尝试过它!
Keeely

2
在我的情况下,默认网关返回“无法访问”消息,但是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

@wellspokenman如果unreachable在管道中找到,您宁愿返回0 ,不是吗?
蜜蜂

1
@beeb是的,我也这样做,但是忘了更新评论。我当前的功能如下:pastebin.com/FEYWsVjK
wellspokenman

8

环顾四周后,我最终编写了自己的ping模块,该模块旨在监视大量地址,是异步的并且不占用大量系统资源。您可以在这里找到它:https : //github.com/romana/multi-ping/它是Apache许可的,因此您可以按照自己认为合适的任何方式在项目中使用它。

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

  • 这里提到的许多解决方案都需要执行程序才能使用命令行实用程序。如果您需要监视大量的IP地址,这是非常低效的,并且会浪费资源。
  • 其他人提到了一些较旧的python ping模块。我查看了这些内容,最后,它们都遇到了其他问题(例如未正确设置数据包ID),并且无法处理大量地址的ping操作。

干得好!如果有人想看到它在行动,只是使用 github.com/romana/multi-ping/blob/master/demo.py
簇簇

7
#!/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()

这段代码可能会解决该问题,但是添加一些注释或解释代码如何解决问题将很有帮助。
skrrgwasme 2014年

5

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

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

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

1
谢谢!但是,我需要以超级用户身份运行此代码才能使其工作。
托马斯

1
自2016
。– Stevoisiak

我收到以下错误:导入pyping追溯(最近一次呼叫最近):文件<< stdin>”,<模块>中的第1行,文件“ /usr/local/lib/python3.6/dist-packages/pyping/__init__”。 py”,第3行,在<module>中,来自核心导入* ModuleNotFoundError:没有名为“ core”的模块
钟钟

5

由于发送原始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连接并立即将其断开,从而测量经过的时间。这种特定的实现方式有一点局限性,因为它不能处理封闭的端口,但是对于您自己的服务器来说,它可以很好地工作。


4
#!/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 !")

3

我用以下方法解决此问题:

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是否正确的方法。Saludos


3

我减少了使用本文中答案的想法,但仅使用推荐的更新子过程模块和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)

1
您无需True if condition else False根据条件返回True或False。只需使用eg shell_needed = operating_sys == 'Windows'return success == 0
emorris

2

该脚本可在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不需要管理员权限。
mountainclimber

两种方式都能接受True的正确
与否

是的,这绝对行不通。在Windows上无论哪种方式
都只

2

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

一个对我有用的例子是:

import pyping

response = pyping.send('Your IP')

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

1
pyping似乎不是标准模块。也许您可以提供一个链接?
Mawg说恢复Monica

2

使用Multi-pingpip 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则可以忽略第二个参数“ ”!

希望能帮助到你!


4
很棒的库,但是需要root特权。
Craynic Cai

2

我的ping函数版本:

  • 适用于Python 3.5及更高版本,适用于Windows和Linux(应适用于Mac,但无法对其进行测试)。
  • 在Windows上,如果ping命令失败并显示“ Destination Host Unreachable”,则返回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 (Mac not tested, should work)
    '''
    # 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

随时随地使用它。


1

看起来很简单,但是很适合我。我一直收到“不允许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

1

我有类似的要求,所以我如下所示实现了它。已在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%)”中提取信息来进行额外的验证。


1

这是使用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

0

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

0

许多答案遗漏的一件事是(至少在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在返回之前进行打印。


0

仅限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'

样本输出


0

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

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"

0

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

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

我不是专家,asyncio但是我使用了这篇很棒的文章“使用并发加速Python程序”,我想到了这些代码行。我试图使其尽可能地简单,因此很可能需要向其添加更多代码以满足您的需求。

它不会返回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会首先打印出来。


-3
  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 privs,下面的效果很好!高温超导

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.