Odpowiedzi:
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ć, True
jeśli pojawi się Destination Host Unreachable
błąd.
Wyjaśnienie
Polecenie jest dostępne ping
w 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'])
.
ping 8.8.8.8 -n 1
3) 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.
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.
response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
man ping
aby się upewnić.
hostname
cią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]).returncode
zamiast tego.
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))
os.system('ping -c 1 -t 1 hostname')
rozwiązania. Ponadto pyping
biblioteka 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 pyping
moim zdaniem jest znacznie szybszy i łatwiejszy w użyciu, zwłaszcza jeśli ktoś nie jest zaznajomiony z korzystaniem z biblioteki gniazd TCP / IP.
pip install ping3
import subprocess
ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "192.168.0.1"], stdout=subprocess.PIPE).stdout.read()
whereis ping
aby uzyskać właściwą ścieżkę.
ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
Dla python3 istnieje bardzo prosty i wygodny moduł ping3 : ( pip install ping3
wymaga 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.
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"))
False if platform.system().lower()=="windows" else True
możesz oczywiście po prostu użyć platform.system().lower() != "windows"
.
os.name!="nt"
też nie działa? Trzeba przyznać, że nie próbowałem tego na wszystkich kombinacjach ver / platform!
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
unreachable
zostanie znaleziony w potoku, nie?
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ść:
#!/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()
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")
Programowy ping ICMP jest skomplikowany ze względu na podwyższone uprawnienia wymagane do wysyłania surowych pakietów ICMP, a wywoływanie ping
plikó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.
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
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)
True if condition else False
do zwracania wartości Prawda lub Fałsz na podstawie warunku. Po prostu użyj np. shell_needed = operating_sys == 'Windows'
Ireturn success == 0
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
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")
pyping
nie wydaje się być standardowym modułem. Może mógłbyś podać link?
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!
Moja wersja funkcji ping:
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.
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
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)”.
Oto rozwiązanie wykorzystujące subprocess
moduł Pythona i ping
narzę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
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
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.stdout
przed powrotem.
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'
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"
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, asyncio
ale 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.
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