使用Python ping网站?


80

如何使用Python ping网站或IP地址?


2
请定义“ ping”。您是要使用ICMP ping协议,还是要查看Web服务器是否正在运行?或者是其他东西?
S.Lott,

事实证明,这对于我正在解决的问题更有用:stackoverflow.com/questions/3764291/checking-network-connection
jedierikb 2012年

Answers:


82

看到这个纯Python平马修·考尔斯迪克森延DIEMER。另外,请记住,Python需要root才能在Linux中生成ICMP(即ping)套接字。

import ping, socket
try:
    ping.verbose_ping('www.google.com', count=3)
    delay = ping.Ping('www.wikipedia.org', timeout=2000).do()
except socket.error, e:
    print "Ping Error:", e

源代码本身易于阅读,请参阅和的实现verbose_pingPing.do获取启发。


4
ping的使用time.clock不会在我的Linux机器上产生任何有用的信息。timeit.default_timer(等于time.time在我的机器上)工作。time.clock-> timeit.default_timer gist.github.com/255009
jfs

@Vinicius-谢谢!更新了github上的新位置。好像它也在不断维护!
Orip 2011年

3
ping没有名为do_one的方法。我找不到一种简单的方法来获取ping时间。
Joseph Turian

1
“运行”已重命名为“计数”
大概

1
@ChrisWithers的“ ping”二进制文件通过“ setuid”位以root身份运行。superuser.com/a/1035983/4706
orip

42

根据您要达到的目标,您可能最容易调用system ping命令。

尽管必须记住ping命令在不同的操作系统上是不同的,但是使用subprocess模块​​是最好的方法!

import subprocess

host = "www.google.com"

ping = subprocess.Popen(
    ["ping", "-c", "4", host],
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE
)

out, error = ping.communicate()
print out

您无需担心脱壳字符。例如..

host = "google.com; `echo test`

..将执行echo命令。

现在,要实际获得ping结果,您可以解析out变量。输出示例:

round-trip min/avg/max/stddev = 248.139/249.474/250.530/0.896 ms

正则表达式示例:

import re
matcher = re.compile("round-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
print matcher.search(out).groups()

# ('248.139', '249.474', '250.530', '0.896')

再次提醒您,输出会因操作系统(甚至的版本ping)而异。这不是理想的方法,但是在许多情况下(您知道脚本将在其上运行的计算机)可以正常工作


我发现我不得不调整您的正则表达式匹配表达式,因为out包含的\ n似乎干扰了匹配:matcher = re.compile("\nround-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
Pierz 2014年


在Windows上,您应该使用-n而不是-c。(请参阅ePi272314的答案
Stevoisiak

39

您可能会发现Noah Gift的演示文稿 使用Python创建敏捷命令行工具。在其中,他结合了子进程,队列和线程,以开发能够同时ping通主机并加快进程的解决方案。以下是他添加命令行解析和其他一些功能之前的基本版本。此版本和其他版本的代码可在此处找到

#!/usr/bin/env python2.5
from threading import Thread
import subprocess
from Queue import Queue

num_threads = 4
queue = Queue()
ips = ["10.0.1.1", "10.0.1.3", "10.0.1.11", "10.0.1.51"]
#wraps system ping command
def pinger(i, q):
    """Pings subnet"""
    while True:
        ip = q.get()
        print "Thread %s: Pinging %s" % (i, ip)
        ret = subprocess.call("ping -c 1 %s" % ip,
            shell=True,
            stdout=open('/dev/null', 'w'),
            stderr=subprocess.STDOUT)
        if ret == 0:
            print "%s: is alive" % ip
        else:
            print "%s: did not respond" % ip
        q.task_done()
#Spawn thread pool
for i in range(num_threads):

    worker = Thread(target=pinger, args=(i, queue))
    worker.setDaemon(True)
    worker.start()
#Place work in queue
for ip in ips:
    queue.put(ip)
#Wait until worker threads are done to exit    
queue.join()

他还是《 Unix和Linux系统管理的Python》的作者。

http://ecx.images-amazon.com/images/I/515qmR%2B4sjL._SL500_AA240_.jpg


4
不知道这实际上可以回答问题,但这是非常有用的信息!
ig0774'5

我知道它来自PyCon ...但这很糟糕。执行系统调用既浪费时间和资源,又难以置信地依赖于系统,并且难以解析。您应该选择使用Python来发送/接收ICMP请求的方法,因为此线程上还有其他方法。
Cukic0d

9

很难说您的问题是什么,但是还有其他选择。

如果您打算使用ICMP ping协议从字面上执行请求,则可以获取ICMP库并直接执行ping请求。谷歌“ Python ICMP”找到类似icmplib的东西。您可能还想看看scapy

这将比使用快得多os.system("ping " + ip )

如果您打算一般地“ ping”一个框以查看它是否启动,则可以在端口7上使用echo协议。

要进行回显,请使用套接字库打开IP地址和端口7。在该端口上写一些东西,发送回车符("\r\n"),然后阅读回复。

如果要“ ping”网站以查看该网站是否正在运行,则必须在端口80上使用http协议。

对于或正确检查Web服务器,您可以使用urllib2打开特定的URL。(/index.html一直很受欢迎)并阅读回复。

“ ping”还有更多潜在的含义,包括“ traceroute”和“ finger”。


5
回声曾经很普遍,但现在在大多数系统上默认为禁用。因此,这不是测试机器运行状况的实用方法。
bortzmeyer

8

我通过这种方式做了类似的事情,以作为启发:

import urllib
import threading
import time

def pinger_urllib(host):
  """
  helper function timing the retrival of index.html 
  TODO: should there be a 1MB bogus file?
  """
  t1 = time.time()
  urllib.urlopen(host + '/index.html').read()
  return (time.time() - t1) * 1000.0


def task(m):
  """
  the actual task
  """
  delay = float(pinger_urllib(m))
  print '%-30s %5.0f [ms]' % (m, delay)

# parallelization
tasks = []
URLs = ['google.com', 'wikipedia.org']
for m in URLs:
  t = threading.Thread(target=task, args=(m,))
  t.start()
  tasks.append(t)

# synchronization point
for t in tasks:
  t.join()

1
很高兴您远离外部图书馆,而且subprocess
tshepang 2012年

如果没有index.html怎么办?
sbose 2013年

4
更重要的是,如果没有Web服务器怎么办?
金·格拉斯曼(KimGräsman)2015年

确实,没有必要将其串联起来/index.html。在任何实际上有一个名为的文档的站点中index.html,它将位于服务器根目录中。相反,你会在前面加上 http://https://到主机
安蒂哈帕拉

尽管这实际上不是ICMP ping,而是TCP端口80“ ping” + HTTP测试,但最好执行HEAD(或OPTIONS)请求,因为您实际上不会收到任何内容,因此带宽会减少影响。如果您想要更多备用的设备,可以尝试打开主机的TCP 80套接字,然后立即将其关闭。
尼克T

6

这是使用的一小段代码subprocess。该check_call方法返回0表示成功,或者引发异常。这样,我不必解析ping的输出。我shlex用来分割命令行参数。

  import subprocess
  import shlex

  command_line = "ping -c 1 www.google.comsldjkflksj"
  args = shlex.split(command_line)
  try:
      subprocess.check_call(args,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
      print "Website is there."
  except subprocess.CalledProcessError:
      print "Couldn't get a ping."

3
警告:在Windows上不起作用(-c-n那里,返回码的逻辑不同)
wim 2012年

3

读取一个文件名,该文件每行包含一个URL,如下所示:

http://www.poolsaboveground.com/apache/hadoop/core/
http://mirrors.sonic.net/apache/hadoop/core/

使用命令:

python url.py urls.txt

得到结果:

Round Trip Time: 253 ms - mirrors.sonic.net
Round Trip Time: 245 ms - www.globalish.com
Round Trip Time: 327 ms - www.poolsaboveground.com

源代码(url.py):

import re
import sys
import urlparse
from subprocess import Popen, PIPE
from threading import Thread


class Pinger(object):
    def __init__(self, hosts):
        for host in hosts:
            hostname = urlparse.urlparse(host).hostname
            if hostname:
                pa = PingAgent(hostname)
                pa.start()
            else:
                continue

class PingAgent(Thread):
    def __init__(self, host):
        Thread.__init__(self)        
        self.host = host

    def run(self):
        p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
        m = re.search('Average = (.*)ms', p.stdout.read())
        if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
        else: print 'Error: Invalid Response -', self.host


if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        content = f.readlines() 
    Pinger(content)


2

如果您想真正使用Python玩一些东西,可以看看Scapy:

from scapy.all import *
request = IP(dst="www.google.com")/ICMP()
answer = sr1(request)

在我看来,这比某些时髦的子流程调用要好得多(并且完全跨平台)。您也可以根据需要获得尽可能多的关于答案的信息(序列ID .....),因为数据包本身也是如此。


2

最简单的答案是:

import os
os.system("ping google.com") 


0

使用system ping命令ping主机列表:

import re
from subprocess import Popen, PIPE
from threading import Thread


class Pinger(object):
    def __init__(self, hosts):
        for host in hosts:
            pa = PingAgent(host)
            pa.start()

class PingAgent(Thread):
    def __init__(self, host):
        Thread.__init__(self)        
        self.host = host

    def run(self):
        p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
        m = re.search('Average = (.*)ms', p.stdout.read())
        if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
        else: print 'Error: Invalid Response -', self.host


if __name__ == '__main__':
    hosts = [
        'www.pylot.org',
        'www.goldb.org',
        'www.google.com',
        'www.yahoo.com',
        'www.techcrunch.com',
        'www.this_one_wont_work.com'
       ]
    Pinger(hosts)

6
我要注册www.this_one_wont_work.com只是为了踢和咯咯地笑。
马修·史考登

p = Popen('ping -n 1 ' + self.host, stdout=PIPE)应该是 p = Popen(['ping','-n','1','self.host'], stdout=PIPE)
toc777

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

1
在Python 3.6上失败。ModuleNotFoundError:没有名为“ subproccess”的模块
Stevoisiak19年

由于command包含所有参数的字符串而不是列表,因此也会失败,因此会command not found在Linux上触发完整字符串。
arielf

0

使用subprocess ping命令对它进行ping操作,因为响应是二进制的:

import subprocess
ping_response = subprocess.Popen(["ping", "-a", "google.com"], stdout=subprocess.PIPE).stdout.read()
result = ping_response.decode('utf-8')
print(result)
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.