pyping multiping con python python-3.x ping icmp

multiping - ping con python



Pinging servidores en Python (22)

En Python, ¿hay alguna manera de hacer ping a un servidor a través de ICMP y devolver TRUE si el servidor responde, o FALSE si no hay respuesta?


Aquí hay una solución que usa el módulo de subprocess de Python y la herramienta ping CLI proporcionada por el sistema operativo subyacente. Probado en Windows y Linux. Soporte para configurar un tiempo de espera de red. No necesita privilegios de administrador (al menos en Windows y 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() 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


Asegúrese de que pyping está instalado o instálelo pip install pyping

#!/usr/bin/python import pyping response = pyping.ping(''Your IP'') if response.ret_code == 0: print("reachable") else: print("unreachable")


Como me gusta que mi programa Python sea universal en la versión 2.7 y 3.x y en la plataforma Linux, Mac OS y Windows, tuve que modificar los ejemplos existentes.

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


Después de mirar alrededor, terminé escribiendo mi propio módulo de ping, que está diseñado para monitorear un gran número de direcciones, es asíncrono y no usa muchos recursos del sistema. Puede encontrarlo aquí: https://github.com/romana/multi-ping/ Tiene licencia de Apache, por lo que puede usarlo en su proyecto de la forma que mejor le parezca.

Las razones principales para implementar las mías son las restricciones de los otros enfoques:

  • Muchas de las soluciones mencionadas aquí requieren una ejecución de una utilidad de línea de comandos. Esto es bastante ineficiente y consume muchos recursos si necesita monitorear un gran número de direcciones IP.
  • Otros mencionan algunos módulos anteriores de python ping. Los miré y al final, todos tenían algún problema o el otro (como no establecer correctamente las ID de los paquetes) y no manejaban el envío de grandes cantidades de direcciones.

El ping ICMP programático es complicado debido a los privilegios elevados requeridos para enviar paquetes ICMP sin procesar, y llamar a ping binary es feo. Para la supervisión del servidor, puede lograr el mismo resultado utilizando una técnica llamada 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

Internamente, esto simplemente establece una conexión TCP al servidor de destino y lo descarta inmediatamente, midiendo el tiempo transcurrido. Esta implementación particular es un poco limitada ya que no maneja puertos cerrados, pero para sus propios servidores funciona bastante bien.


Este script funciona en Windows y debería funcionar en otros sistemas operativos: funciona en Windows, Debian y macosx, necesita una prueba en 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


Hay un módulo llamado pyping que puede hacer esto. Se puede instalar con pip

pip install pyping

Sin embargo, es bastante simple de usar cuando se utiliza este módulo, necesita acceso a la raíz debido al hecho de que está elaborando paquetes sin procesar bajo el capó.

import pyping r = pyping.ping(''google.com'') if r.ret_code == 0: print("Viagra") else: print("Promescent")


Me gustó ping3 https://github.com/kyan001/ping3 Muy simple y conveniente!

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


Mi reducción usando ideas de respuestas en esta publicación pero solo usando el módulo de subproceso recomendado más nuevo y python3:

import subprocess import platform operating_sys = platform.system() nas = ''192.168.0.10'' def ping(ip): 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)


Parece bastante simple, pero me dio ajustes. Seguí obteniendo "la operación de socket abierto icmp no permitida" o de lo contrario las soluciones colgarían si el servidor estuviera fuera de línea. Sin embargo, si lo que desea saber es que el servidor está activo y está ejecutando un servidor web en ese servidor, entonces curl hará el trabajo. Si tiene ssh y certificados, entonces ssh y un simple comando serán suficientes. Aquí está el código:

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


Resuelvo esto con:

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" es la forma de saber si el ping es correcto. Saludos


Si no necesita soportar Windows, aquí hay una forma muy concisa de hacerlo:

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

Esto funciona porque ping devuelve un valor distinto de cero si la conexión falla. (El valor de retorno en realidad difiere según el error de red). También puede cambiar el tiempo de espera del ping (en segundos) usando la opción ''-t''. Tenga en cuenta que esto enviará texto a la consola.


Tenía un requisito similar, así que lo implementé como se muestra a continuación. Está probado en Windows 64 bit y 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))

Cuando IP no es alcanzable, subprocess.check_output () genera una excepción. La verificación adicional se puede hacer extrayendo información de la línea de salida ''Paquetes: Enviados = 2, Recibidos = 2, Perdidos = 0 (0% de pérdidas)''.


Terminé encontrando esta pregunta con respecto a un escenario similar. Probé la creación de pirámides pero el ejemplo dado por Naveen no funcionó para mí en Windows bajo Python 2.7.

Un ejemplo que funcionó para mí es:

import pyping response = pyping.send(''Your IP'') if response[''ret_code''] == 0: print("reachable") else: print("unreachable")


Una cosa que muchas de las respuestas se pierden es que (al menos en Windows) el comando ping devuelve 0 (indicando éxito) si recibe la respuesta "host de destino inalcanzable".

Aquí está mi código que verifica si b''TTL='' está en la respuesta, ya que eso solo está presente cuando el ping llegó al host. Nota: la mayoría de este código se basa en las otras respuestas aquí.

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

Nota: Esto captura el resultado en lugar de imprimirlo, por lo que si desea ver el resultado de ping , deberá imprimir completedPing.stdout antes de regresar.


Usando Multi-ping ( pip install multiPing ) hice este código simple (¡ simplemente copie y pegue si lo desea! ):

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

Uso:

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

Si quiere una sola muestra, ¡puede ignorar el segundo parámetro " 10 "!

¡Espero eso ayude!


Use esto, ha sido probado en Python 2.7 y funciona bien, devuelve el tiempo de ping en milisegundos si es exitoso y devuelve False on fail.

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


Esta función funciona en cualquier sistema operativo (Unix, Linux, OS X y Windows)
Python 2 y Python 3

EDIT 1: Agregó algunos comentarios a la respuesta original.
EDIT 2: Siguiendo una sugerencia de @radato , os.system fue reemplazado por subprocess.call .

from platform import system as system_name # Returns the system/OS name from subprocess import call as system_call # Execute 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. """ # Ping command count option as function of OS param = ''-n'' if system_name().lower()==''windows'' else ''-c'' # Building the command. Ex: "ping -c 1 google.com" command = [''ping'', param, ''1'', host] # Pinging return system_call(command) == 0

El comando es ping en sistemas Windows y Unix. La opción -n (Windows) o -c (Unix) controla el número de paquetes que en este ejemplo es 1.

platform.system() devuelve el nombre de la plataforma. Ex. ''Darwin'' en macOS
subprocess.call() realiza una llamada al sistema. Ex. subprocess.call([''ls'',''-l''])


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"

Uno simple que acabo de cocinar en un minuto ... usando icmplib necesita privs de raíz, el siguiente funciona bastante bien. HTH


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


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


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