Pingowanie serwerów w Pythonie

167

Czy w Pythonie istnieje sposób na wysłanie polecenia ping do serwera przez protokół ICMP i zwrócenie wartości TRUE, jeśli serwer odpowie, lub FALSE, jeśli nie ma odpowiedzi?

Kudu
źródło

Odpowiedzi:

112

Ta funkcja działa w każdym systemie operacyjnym (Unix, Linux, macOS i Windows)
Python 2 i Python 3

EDYCJE:
By @radato os.system został zastąpiony przez subprocess.call. Pozwala to uniknąć podatności na wstrzyknięcie powłoki w przypadkach, gdy ciąg znaków nazwy hosta może nie zostać zweryfikowany.

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

Zauważ, że zgodnie z @ikrase w systemie Windows ta funkcja będzie nadal zwracać, Truejeśli pojawi się Destination Host Unreachablebłąd.

Wyjaśnienie

Polecenie jest dostępne pingw systemach Windows i Unix-podobnych.
Opcja -n(Windows) lub -c(Unix) kontroluje liczbę pakietów, które w tym przykładzie były ustawione na 1.

platform.system()zwraca nazwę platformy. Dawny. 'Darwin'na macOS.
subprocess.call()wykonuje wywołanie systemowe. Dawny. subprocess.call(['ls','-l']).

ePi272314
źródło
14
Zauważ, że to nadal zwróci prawdę (w Windows), jeśli otrzymasz odpowiedź „host docelowy nieosiągalny” z innego hosta.
ikrase
Od czasu do czasu otrzymuję polecenie ping, gdy mój modem jest wyłączony ??? To testowanie „8.8.8.8” i „google.com” w systemie operacyjnym Windows 10. Coś jest nie tak.
Markus
To nie może się zdarzyć @Markus. Prosimy o przetestowanie ręczne i zmodyfikowaną wersję powyższego kodu i podanie wyniku. Ręcznie: 1) otwórz cmd 2) ping 8.8.8.8 -n 13) echo %ERRORLEVEL%. Kod: Zmodyfikuj ostatni wiersz kodu Pythona na return system_call(command). Przy odpowiedniej łączności otrzymasz 0 (zero). Przy wyłączonym modemie musisz otrzymać kod błędu. Oczywiście obie metody muszą zwracać ten sam kod błędu w tych samych warunkach.
ePi272314
Zdarzyło się i użyłem dokładnego kodu, słowo w słowo. Rozumiem i wierzę Wasze komentarze, nie ma możliwości, aby ping z wiersza poleceń mógł się powieść, gdy nie ma połączenia, stąd pomyślałem, że coś nie działa poprawnie w operacji Python do wiersza poleceń. Spróbuję aktualizacji i zobaczę, jak pójdzie. Dzięki.
Markus
@Markus zobacz komentarz ikrase.
Boris
163

Jeśli nie potrzebujesz obsługi systemu Windows, oto naprawdę zwięzły sposób, aby to zrobić:

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

Działa to, ponieważ ping zwraca wartość niezerową, jeśli połączenie nie powiedzie się. (Wartość zwracana w rzeczywistości różni się w zależności od błędu sieci.) Możesz także zmienić limit czasu ping (w sekundach), używając opcji „-t”. Uwaga, spowoduje to wyświetlenie tekstu na konsoli.

10flow
źródło
42
Skończyło się na tym wariancieresponse = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
MGP
4
@ jeckyll2hide man ping, wyślij tylko 1 pakiet z terminem ostatecznym 2 sekundy i przekieruj wszystkie dane wyjściowe do / dev / null, pobierz tylko wartość zwracaną.
MGP
@ManuelGutierrez Myślę, że chcesz "-W 2000" (limit czasu po 2000 milisekundach) i może "-t 3" (wyjście po 3 sekundach, bez względu na wszystko)
eludom
1
-w i -W przyjmują wartości w sekundach, a nie milisekundach. Sprawdź, man pingaby się upewnić.
Alan Turing
7
Jeśli otrzymasz hostnameciąg od użytkownika, może on łatwo zhakować twój serwer, podając ci „url” w rodzaju 'google.com; rm -rf /*'. Użyj subprocess.run(["ping", "-c", "1", hostname]).returncodezamiast tego.
Boris
38

Istnieje moduł o nazwie pyping, który może to zrobić. Można go zainstalować za pomocą pip

pip install pyping

Jest dość prosty w użyciu, jednak podczas korzystania z tego modułu potrzebujesz dostępu do konta roota, ponieważ tworzy on surowe pakiety pod maską.

import pyping

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

if r.ret_code == 0:
    print("Success")
else:
    print("Failed with {}".format(r.ret_code))
Stephen Cochran
źródło
4
„Zauważ, że wiadomości ICMP mogą być wysyłane tylko z procesów działających jako root (w Windows musisz uruchomić ten skrypt jako 'Administrator').”
Ben Hyde
1
Podoba mi się, że możesz określić limit czasu i liczbę wysłanych żądań ICMP. Udało mi się napisać skrypt, który wykrywa wszystkie hosty w lokalnej podsieci. Wykonuje się w 1 sekundę, zamiast 255 sekund przy użyciu os.system('ping -c 1 -t 1 hostname')rozwiązania. Ponadto pypingbiblioteka jest bardzo łatwa w użyciu w porównaniu do korzystania z biblioteki gniazd TCP / IP. Napisałem swój program ping, używając obu i pypingmoim zdaniem jest znacznie szybszy i łatwiejszy w użyciu, zwłaszcza jeśli ktoś nie jest zaznajomiony z korzystaniem z biblioteki gniazd TCP / IP.
MikeyE
10
nie działa z py3. ModuleNotFoundError: Brak modułu o nazwie „core”
alireza
2
błąd „core” pochodzi z niezgodności z pythonem3. Próbowałem to naprawić dla Python3, ale ciągle wysyła mi błędy. strona github autorów i projektów jest wyłączona (404 nie znaleziono). będziemy musieli sami przenieść to na python3 :-)
Andre
6
dla python3 wypróbuj 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()
mluebke
źródło
6
Jedynym problemem jest to, że nie będzie działać w systemie Windows.
Kudu
8
Należy wspomnieć, że powodem, dla którego coś takiego jest konieczne, jest to, że ICMP wymaga roota, a / bin / ping omija ten problem, ustawiając SUID.
Catskul,
1
Uwaga: może się nie powieść, jeśli ping znajduje się w innej lokalizacji. Użyj, whereis pingaby uzyskać właściwą ścieżkę.
godzina
4
Działa to w systemie Windows:ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
Victor Lellis
1
Jak mogę przeanalizować wynik, aby sprawdzić, czy odpowiedź była poprawna lub ko w systemie Windows?
Pitto
15

Dla python3 istnieje bardzo prosty i wygodny moduł ping3 : ( pip install ping3wymaga uprawnień roota ).

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

Moduł ten pozwala również na dostosowanie niektórych parametrów.

Александр Рублев
źródło
2
Edytowane wymaga uprawnień roota, dyskusja na temat ich zniesienia tutaj: github.com/kyan001/ping3/issues/10
Dimitrios Mistriotis
1
Och, potrzebujesz roota prvilege nie tylko do instalacji, ale także do wykonania: ping ("example.com")
Zegar ZHONG
14

Ponieważ lubię, aby mój program w Pythonie był uniwersalny w wersji 2.7 i 3.x oraz na platformach Linux, Mac OS i Windows, musiałem zmodyfikować istniejące przykłady.

# 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"))
Rudolf
źródło
1
Zamiast tego False if platform.system().lower()=="windows" else Truemożesz oczywiście po prostu użyć platform.system().lower() != "windows".
Frerich Raabe
To os.name!="nt"też nie działa? Trzeba przyznać, że nie próbowałem tego na wszystkich kombinacjach ver / platform!
Keeely,
2
W moim przypadku brama domyślna zwraca komunikat „nieosiągalny”, ale polecenie ping w systemie Windows nadal ma kod powrotu 0. Więc to podejście zadziałało (przepraszam za formatowanie - jego 6 linii, w tym deklaracja funkcji): 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, wolałbyś raczej zwrócić 0, jeśli unreachablezostanie znaleziony w potoku, nie?
beeb
1
@beeb yeah Ja też to zrobiłem, ale zapomniałem zaktualizować komentarz. Moja obecna funkcja wygląda następująco: pastebin.com/FEYWsVjK
wellspokenman
8

Po rozejrzeniu się napisałem własny moduł ping, który jest przeznaczony do monitorowania dużej liczby adresów, jest asynchroniczny i nie zużywa dużo zasobów systemowych. Znajdziesz go tutaj: https://github.com/romana/multi-ping/ Jest na licencji Apache, więc możesz go używać w swoim projekcie w dowolny sposób.

Głównymi powodami wdrożenia mojego własnego są ograniczenia innych podejść:

  • Wiele z wymienionych tutaj rozwiązań wymaga wykonania polecenia exec out do narzędzia wiersza poleceń. Jest to dość nieefektywne i wymagające zasobów, jeśli musisz monitorować dużą liczbę adresów IP.
  • Inni wspominają o starszych modułach ping w Pythonie. Przyjrzałem się tym i na końcu wszystkie miały jakiś lub inny problem (na przykład nieprawidłowe ustawienie identyfikatorów pakietów) i nie obsłużyły pingowania dużej liczby adresów.
Juergen Brendel
źródło
Niezła robota! Jeśli ktoś chce zobaczyć to w akcji, po prostu użyj github.com/romana/multi-ping/blob/master/demo.py
Cucu.
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()
Udayendu
źródło
Ten kod może zawierać odpowiedź na pytanie, ale pomocne byłoby dodanie komentarzy lub wyjaśnień, w jaki sposób kod rozwiązuje problem.
skrrgwasme
5

Upewnij się, że pyping jest zainstalowany lub zainstaluj go pip install pyping

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

if response.ret_code == 0:
    print("reachable")
else:
    print("unreachable")
Naveen
źródło
1
Dzięki! Jednak muszę uruchomić ten kod jako root, aby działał.
Thomas
1
Strona Pyping na GitHub już nie istnieje, a pakiet PyPI nie był aktualizowany od 2016 roku.
Stevoisiak
Otrzymałem następujące błędy: Import pyping Traceback (ostatnie połączenie ostatnio): Plik „<stdin>”, wiersz 1, w <module> File ”/usr/local/lib/python3.6/dist-packages/pyping/__init__. py ”, wiersz 3, w <module> z importu core * ModuleNotFoundError: Brak modułu o nazwie 'core'
Clock ZHONG
5

Programowy ping ICMP jest skomplikowany ze względu na podwyższone uprawnienia wymagane do wysyłania surowych pakietów ICMP, a wywoływanie pingplików binarnych jest brzydkie. W przypadku monitorowania serwera ten sam wynik można osiągnąć za pomocą techniki zwanej pingiem TCP :

# 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

Wewnętrznie, to po prostu ustanawia połączenie TCP z serwerem docelowym i natychmiast je przerywa, mierząc upływający czas. Ta konkretna implementacja jest nieco ograniczona, ponieważ nie obsługuje zamkniętych portów, ale w przypadku własnych serwerów działa całkiem dobrze.

kravietz
źródło
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 !")
Udayendu
źródło
3

Rozwiązuję to za pomocą:

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” to sposób na sprawdzenie, czy ping jest prawidłowy. Saludos

user3620655
źródło
3

Moja redukcja przy użyciu pomysłów z odpowiedzi w tym poście, ale tylko przy użyciu nowszego zalecanego modułu podprocesu i 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)
Arno
źródło
1
Nie musisz używać True if condition else Falsedo zwracania wartości Prawda lub Fałsz na podstawie warunku. Po prostu użyj np. shell_needed = operating_sys == 'Windows'Ireturn success == 0
emorris
2

Ten skrypt działa w systemie Windows i powinien działać w innych systemach operacyjnych: działa w systemach Windows, Debian i macosx, wymaga testu na 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
Mateusz
źródło
Dobra odpowiedź. W przypadku systemu Windows nie są wymagane żadne uprawnienia administratora.
alpinista
Tak czy inaczej, otrzymuję True zarówno dobre, jak i złe IP
joash
Tak, to zdecydowanie nie działa. Po prostu zwraca: „true” w obu przypadkach w systemie Windows
MKANET
2

W końcu znalazłem to pytanie dotyczące podobnego scenariusza. Wypróbowałem pyping, ale przykład podany przez Naveena nie działał dla mnie w systemie Windows pod Pythonem 2.7.

Przykład, który zadziałał dla mnie to:

import pyping

response = pyping.send('Your IP')

if response['ret_code'] == 0:
    print("reachable")
else:
    print("unreachable")
templariusz
źródło
1
pypingnie wydaje się być standardowym modułem. Może mógłbyś podać link?
Mawg mówi, że przywróć Monikę
2

Używając Multi-ping ( pip install multiPing) zrobiłem ten prosty kod ( po prostu skopiuj i wklej, jeśli chcesz! ):

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

Stosowanie:

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

Jeśli potrzebujesz jednej próbki, drugi parametr „10 ” można zignorować!

Mam nadzieję, że to pomoże!

Geraldo Neto
źródło
4
niesamowita biblioteka, ale potrzebujesz uprawnień roota.
Craynic Cai
2

Moja wersja funkcji ping:

  • Działa na Pythonie 3.5 i nowszych, Windows i Linux (powinien działać na Macu, ale nie można go przetestować).
  • W systemie Windows zwraca wartość False, jeśli polecenie ping nie powiedzie się i wyświetli komunikat „Host docelowy nieosiągalny”.
  • I nie wyświetla żadnych danych wyjściowych, ani jako wyskakujące okienko, ani w wierszu poleceń.
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

Możesz go używać tak, jak chcesz.

Jose Francisco Lopez Pimentel
źródło
1

Wydaje się dość proste, ale dało mi ataki. Ciągle otrzymywałem komunikat „ICMP open socket operation niedozwolony”, w przeciwnym razie rozwiązania zawiesiłyby się, gdyby serwer był wyłączony. Jeśli jednak chcesz wiedzieć, że serwer działa i na nim działa serwer WWW, to curl wykona zadanie. Jeśli masz ssh i certyfikaty, wystarczy ssh i prosta komenda. Oto kod:

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
user2099484
źródło
1

Miałem podobny wymóg, więc zaimplementowałem go, jak pokazano poniżej. Jest testowany na 64-bitowym systemie Windows i Linuksie.

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

Gdy adres IP jest nieosiągalny, funkcja subprocess.check_output () zgłasza wyjątek. Dodatkową weryfikację można przeprowadzić, wyodrębniając informacje z wiersza wyjściowego „Pakiety: wysłane = 2, odebrane = 2, utracone = 0 (0% utraty)”.

Luminos
źródło
1

Oto rozwiązanie wykorzystujące subprocessmoduł Pythona i pingnarzędzie CLI dostarczane przez podstawowy system operacyjny. Przetestowano w systemach Windows i Linux. Obsługa ustawiania limitu czasu sieci. Nie potrzebuje uprawnień roota (przynajmniej w systemie Windows i 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
Epoc
źródło
0

Użyj tego, co zostało przetestowane w Pythonie 2.7 i działa dobrze, zwraca czas ping w milisekundach, jeśli się powiedzie, i zwróci False w przypadku niepowodzenia.

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
MSS
źródło
0

Jedną rzeczą, której brakuje w wielu odpowiedziach, jest to (przynajmniej w systemie Windows) ping polecenie zwraca 0 (wskazujące na sukces), jeśli otrzyma odpowiedź „Host docelowy nieosiągalny”.

Oto mój kod, który sprawdza, czy b'TTL='jest w odpowiedzi, ponieważ jest obecny tylko wtedy, gdy ping dotarł do hosta. Uwaga: większość tego kodu jest oparta na innych odpowiedziach tutaj.

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

Uwaga: To przechwytuje dane wyjściowe zamiast je drukować, więc jeśli chcesz zobaczyć wynik ping, musisz wydrukować completedPing.stdoutprzed powrotem.

Brent Robertson
źródło
0

TYLKO WINDOWS - Nie mogę uwierzyć, że nikt nie otworzył się Win32_PingStatus Używając prostego zapytania WMI, zwracamy obiekt pełen naprawdę szczegółowych informacji za darmo

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'

przykładowe wyjście

Aimondy
źródło
0

Moje zapożyczenie z innych odpowiedzi. Spróbuj uprościć i zminimalizować zapytania.

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"
misantroop
źródło
0

Potrzebowałem szybszego przeczesywania pingów i nie chciałem używać żadnych zewnętrznych bibliotek, więc zdecydowałem się na użycie współbieżności przy użyciu wbudowanych asyncio.

Ten kod wymaga języka Python 3.7+ i został stworzony i przetestowany tylko w systemie Linux . Nie będzie działać w systemie Windows, ale jestem pewien, że można go łatwo zmienić, aby działał w systemie Windows.

Nie jestem ekspertem, asyncioale użyłem tego świetnego artykułu Przyspiesz swój program w Pythonie dzięki współbieżności i wymyśliłem te linie kodów. Starałem się, aby było to tak proste, jak to tylko możliwe, więc najprawdopodobniej będziesz musiał dodać do niego więcej kodu, aby dopasować go do swoich potrzeb.

Nie zwraca prawdy ani fałszu, pomyślałem, że wygodniej będzie po prostu wydrukować adres IP, który odpowiada na żądanie ping. Myślę, że jest dość szybki, pinguje 255 ips w prawie 10 sekund.

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

Przykładowe dane wyjściowe:

192.168.1.1
192.168.1.3
192.168.1.102
192.168.1.106
192.168.1.6

Zauważ, że adresy IP nie są w kolejności, ponieważ adres IP jest drukowany, gdy tylko odpowie, więc ten, który odpowiada jako pierwszy, jest drukowany jako pierwszy.

Ahmed Essam
źródło
-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"

Prosty, który właśnie ugotowałem w minutę .. używanie icmplib wymaga uprawnień roota, poniższe działa całkiem nieźle! HTH

user3423128
źródło