Pingen Sie eine Site in Python?


80

Wie pinge ich eine Website oder IP-Adresse mit Python?


2
Bitte definieren Sie "Ping". Möchten Sie das ICMP-Ping-Protokoll verwenden oder prüfen, ob ein Webserver ausgeführt wird? Oder etwas anderes?
S.Lott

Dies erwies sich als hilfreicher für ein Problem, das ich löste: stackoverflow.com/questions/3764291/checking-network-connection
jedierikb

1
Hier ist das Gerät von Pure Python: falatic.com/index.php/39/pinging-with-python
thinker007

Antworten:


82

Sehen Sie diesen reinen Python-Ping von Matthew Dixon Cowles und Jens Diemer . Denken Sie auch daran, dass Python Root benötigt, um ICMP-Sockets (dh Ping-Sockets) unter Linux zu erzeugen.

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

Der Quellcode selbst ist leicht zu lesen, siehe die Implementierungen von verbose_pingund von Ping.doals Inspiration.


4
pingVerwendungen time.clock, die auf meiner Linux-Box nichts Nützliches ergeben. timeit.default_timer(es ist gleich time.timeauf meinem Computer) funktioniert. time.clock-> timeit.default_timer gist.github.com/255009
jfs

@ Vinicius - danke! Aktualisiert mit dem neuen Speicherort auf Github. Scheint auch ständig gewartet zu werden!
Orip

3
ping hat keine Methode namens do_one. Ich konnte keinen einfachen Weg finden, um die Ping-Zeit zu bekommen.
Joseph Turian

1
'run' wurde in 'count' umbenannt
pferate

1
@ChrisWithers wird die 'Ping'-Binärdatei als Root über das' Setuid'-Bit ausgeführt. superuser.com/a/1035983/4706
oriP

42

Je nachdem, was Sie erreichen möchten, ist es wahrscheinlich am einfachsten, den System-Ping-Befehl aufzurufen.

Die Verwendung des Unterprozessmoduls ist der beste Weg, obwohl Sie sich daran erinnern müssen, dass der Ping-Befehl auf verschiedenen Betriebssystemen unterschiedlich ist!

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

Sie müssen sich keine Gedanken über Shell-Escape-Charaktere machen. Zum Beispiel..

host = "google.com; `echo test`

..wird den Echo-Befehl nicht ausführen.

Um die Ping-Ergebnisse tatsächlich zu erhalten, können Sie die outVariable analysieren . Beispielausgabe:

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

Beispiel Regex:

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')

Denken Sie auch hier daran, dass die Ausgabe je nach Betriebssystem (und sogar der Version von ping) unterschiedlich sein wird. Dies ist nicht ideal, funktioniert aber in vielen Situationen einwandfrei (wenn Sie die Computer kennen, auf denen das Skript ausgeführt wird).


Ich stellte fest, dass ich Ihren Regex-Match-Ausdruck anpassen musste, da er outcodierte \ n enthält, die den Matching zu stören scheinen:matcher = re.compile("\nround-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
Pierz

@Pierz: Verwenden Sie matcher.searchstattdessen einfach , ohne den regulären Ausdruck zu ändern .
JFS

Unter Windows sollten Sie -nanstelle von verwenden -c. ( Siehe die Antwort von ePi272314 )
Stevoisiak

39

Möglicherweise finden Sie die Präsentation von Noah Gift. Erstellen agiler Befehlszeilentools mit Python . Darin kombiniert er Unterprozess, Warteschlange und Threading, um eine Lösung zu entwickeln, die Hosts gleichzeitig anpingen und den Prozess beschleunigen kann. Im Folgenden finden Sie eine Basisversion, bevor er die Befehlszeilenanalyse und einige andere Funktionen hinzufügt. Den Code zu dieser und anderen Versionen finden Sie hier

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

Er ist außerdem Autor von: Python für Unix und Linux System Administration

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


4
Ich weiß nicht, dass dies tatsächlich die Frage beantwortet, aber es sind sehr nützliche Informationen!
ig0774

Ich weiß, dass es von PyCon kommt ... aber es ist ziemlich schlecht. Das Ausführen von Systemaufrufen ist eine Verschwendung von Zeit und Ressourcen, ist jedoch unglaublich systemabhängig und schwer zu analysieren. Sie sollten sich lieber für eine Methode mit Python zum Senden / Empfangen von ICMP-Anforderungen entscheiden, da sich in diesem Thread andere befinden.
Cukic0d

9

Es ist schwer zu sagen, was Ihre Frage ist, aber es gibt einige Alternativen.

Wenn Sie eine Anforderung buchstäblich mit dem ICMP-Ping-Protokoll ausführen möchten, können Sie eine ICMP-Bibliothek abrufen und die Ping-Anforderung direkt ausführen. Google "Python ICMP", um Dinge wie diese icmplib zu finden . Vielleicht möchten Sie sich auch scapy ansehen .

Dies ist viel schneller als die Verwendung os.system("ping " + ip ).

Wenn Sie generisch eine Box "anpingen" möchten, um festzustellen, ob sie aktiv ist, können Sie das Echo-Protokoll an Port 7 verwenden.

Für Echo verwenden Sie die Socket- Bibliothek, um die IP-Adresse und den Port 7 zu öffnen. Sie schreiben etwas auf diesen Port, senden einen Wagenrücklauf ( "\r\n") und lesen dann die Antwort.

Wenn Sie eine Website "anpingen" möchten, um festzustellen, ob die Website ausgeführt wird, müssen Sie das http-Protokoll an Port 80 verwenden.

Um einen Webserver zu überprüfen oder ordnungsgemäß zu überprüfen, verwenden Sie urllib2 , um eine bestimmte URL zu öffnen. ( /index.htmlist immer beliebt) und lesen Sie die Antwort.

Es gibt noch mehr mögliche Bedeutungen von "Ping", einschließlich "Traceroute" und "Finger".


5
Echo war früher weit verbreitet, jetzt jedoch auf den meisten Systemen standardmäßig deaktiviert. Es ist also keine praktische Möglichkeit zu testen, ob die Maschine einwandfrei läuft.
Bortzmeyer

8

Ich habe etwas Ähnliches auf diese Weise gemacht, als Inspiration:

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
Ich bin

Was ist, wenn es keine index.html gibt?
Sbose

4
Was ist noch wichtiger, wenn es keinen Webserver gibt?
Kim Gräsman

In der Tat besteht keine Notwendigkeit, dies zu verketten /index.html; An jedem Ort, an dem tatsächlich ein Dokument aufgerufen wird index.html, befindet es sich genau dort im Server-Stammverzeichnis. Stattdessen würden Sie voranstellen http:// oder https://den Host
Antti Haapala

Dies ist zwar nicht wirklich ein ICMP-Ping, sondern ein TCP-Port 80 "Ping" + HTTP-Test. Es ist jedoch wahrscheinlich besser, eine HEAD- (oder OPTIONS-) Anforderung durchzuführen, da Sie tatsächlich keinen Inhalt erhalten, also die Bandbreite beeinflussen es weniger. Wenn Sie mehr Ersatz benötigen, können Sie einfach versuchen, einen TCP 80-Socket für den Host zu öffnen und ihn sofort zu schließen.
Nick T

6

Hier ist ein kurzer Ausschnitt mit subprocess. Die check_callMethode gibt entweder 0 für den Erfolg zurück oder löst eine Ausnahme aus. Auf diese Weise muss ich die Ausgabe von Ping nicht analysieren. Ich verwende shlex, um die Befehlszeilenargumente zu teilen.

  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
Warnung: funktioniert nicht unter Windows ( -cist -nvorhanden und die Logik bezüglich des Rückkehrcodes ist anders)
wim

3

Lesen Sie einen Dateinamen, die Datei enthält die eine URL pro Zeile, wie folgt:

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

Befehl verwenden:

python url.py urls.txt

Holen Sie sich das Ergebnis:

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

Quellcode (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
import subprocess as s
ip=raw_input("Enter the IP/Domain name:")
if(s.call(["ping",ip])==0):
    print "your IP is alive"
else:
    print "Check ur IP"

2

Wenn Sie etwas in Python wollen, mit dem Sie spielen können, schauen Sie sich Scapy an:

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

Das ist meiner Meinung nach viel besser (und vollständig plattformübergreifend) als einige funky Subprozessaufrufe. Sie können auch so viele Informationen über die Antwort (Sequenz-ID .....) haben, wie Sie möchten, wie Sie das Paket selbst haben.


2

Die einfachste Antwort lautet:

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

1

Eine aktualisierte Version des genannten Skripts, das sowohl unter Windows als auch unter Linux funktioniert, finden Sie hier


Der verknüpfte Code schlägt unter Python 3.8 fehl. "SyntaxError: ungültige Syntax"
Stevoisiak

0

Verwenden des System-Ping-Befehls zum Pingen einer Liste von Hosts:

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
Ich werde www.this_one_wont_work.com nur für Tritte und Kichern registrieren.
Matthew Scouten

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

0

Verwenden Sie dies, es wurde unter Python 2.7 getestet und funktioniert einwandfrei. Bei Erfolg wird die Ping-Zeit in Millisekunden zurückgegeben und bei Fehlschlag False zurückgegeben.

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
Schlägt unter Python 3.6 fehl. ModuleNotFoundError: Kein Modul mit dem Namen 'subproccess'
Stevoisiak

Scheitert auch, weil commandeine Zeichenfolge, die alle Argumente anstelle einer Liste enthält, unter command not foundLinux die vollständige Zeichenfolge auslöst .
Arielf

0

Verwenden des Unterprozess-Ping-Befehls zum Ping-Dekodieren, da die Antwort binär ist:

import subprocess
ping_response = subprocess.Popen(["ping", "-a", "google.com"], stdout=subprocess.PIPE).stdout.read()
result = ping_response.decode('utf-8')
print(result)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.