web-dev-qa-db-fra.com

Ping de serveurs en Python

En Python, existe-t-il un moyen d'envoyer un ping à un serveur via ICMP et de renvoyer TRUE si le serveur répond ou FALSE s'il n'y a pas de réponse?

121
Kudu

Si vous n'avez pas besoin de prendre en charge Windows, voici une manière très concise de le faire:

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

Cela fonctionne car ping renvoie une valeur non nulle si la connexion échoue. (La valeur de retour varie en fonction de l'erreur réseau.) Vous pouvez également modifier le délai d'attente du ping (en secondes) à l'aide de l'option '-t'. Notez que cela affichera du texte sur la console.

124
10flow

Cette fonction fonctionne sur Python 2 et Python 3. Elle fonctionne sur n’importe quel système d’exploitation (Unix, Linux, macOS et Windows), mais sous Windows, elle retournera quand même True si vous obtenez une erreur Destination Host Unreachable.

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.
    """

    # Ping command count option as function of OS
    param = '-n' if platform.system()=='Windows' else '-c'

    # Building the command. Ex: "ping -c 1 google.com"
    command = ['ping', param, '1', Host]

    return system.call(command) == 0

La commande est ping dans les systèmes Windows et Unix-like . L'option -n (Windows) ou -c (Unix) contrôle le nombre de paquets qui, dans cet exemple, est 1.

platform.system() renvoie le nom de la plate-forme. Ex. 'Darwin' sur macOS
subprocess.call() effectue un appel système. Ex. subprocess.call(['ls','-l']). Notez que la documentation recommande d’utiliser subprocess.run() si vous utilisez Python 3.5+.

76
ePi272314

Il existe un module appelé pyping qui peut le faire. Il peut être installé avec pip 

pip install pyping

C'est assez simple à utiliser, cependant, lorsque vous utilisez ce module, vous avez besoin d'un accès root, car il crée des paquets bruts sous le capot. 

import pyping

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

if r.ret_code == 0:
    print("Success")
else:
    print("Failed with {}".format(r.ret_code))
30
Stephen Cochran
import subprocess
ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "192.168.0.1"], stdout=subprocess.PIPE).stdout.read()
26
mluebke

Parce que j'aime avoir mon programme Python universel sur les versions 2.7 et 3.x et sur les plateformes Linux, Mac OS et Windows, j'ai dû modifier les exemples existants.

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

Assurez-vous que Pyping est installé ou installez-le pip install Pyping

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

if response.ret_code == 0:
    print("reachable")
else:
    print("unreachable")
6
Naveen

Après avoir regardé autour de moi, j'ai fini par écrire mon propre module ping, conçu pour surveiller un grand nombre d'adresses, il est asynchrone et n'utilise pas beaucoup de ressources système. Vous pouvez le trouver ici: https://github.com/romana/multi-ping/ Il est sous licence Apache, vous pouvez donc l'utiliser dans votre projet comme bon vous semble.

Les principales raisons pour mettre en œuvre la mienne sont les restrictions des autres approches:

  • La plupart des solutions mentionnées ici nécessitent un exécutable sur un utilitaire de ligne de commande. C'est assez inefficace et gourmand en ressources si vous devez surveiller un grand nombre d'adresses IP.
  • D'autres mentionnent d'anciens modules ping Python. J'ai regardé ceux-ci et à la fin, ils avaient tous un problème (comme ne pas définir correctement les ID de paquet) et ne géraient pas le ping d'un grand nombre d'adresses.
5
Juergen Brendel
#!/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()
5
Udayendu

Utilisation de Multi-ping (pip install multiPing) J'ai créé ce code simple (simplement copier et coller si vous voulez!):

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

Utilisation:

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

Si vous voulez un seul échantillon, le second paramètre "10" peut être ignoré!

J'espère que ça aide!

3
Geraldo Neto
#!/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 !")
2
Udayendu

Le ping ICMP par programmation est compliqué à cause des privilèges élevés requis pour envoyer des paquets ICMP bruts, et appeler ping binary est moche. Pour la surveillance du serveur, vous pouvez obtenir le même résultat en utilisant une technique appelée 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

En interne, cela établit simplement une connexion TCP au serveur cible et l’interrompt immédiatement, le temps de mesure étant écoulé. Cette implémentation particulière est un peu limitée car elle ne gère pas les ports fermés, mais elle fonctionne plutôt bien pour vos propres serveurs.

2
kravietz

J'ai fini par trouver cette question concernant un scénario similaire. J'ai essayé de pyper mais l'exemple donné par Naveen ne fonctionnait pas pour moi sous Windows sous Python 2.7. 

Un exemple qui a fonctionné pour moi est:

import pyping

response = pyping.send('Your IP')

if response['ret_code'] == 0:
    print("reachable")
else:
    print("unreachable")
2
Templar

Ma réduction en utilisant des idées de réponses dans ce post mais en utilisant uniquement le module de sous-processus recommandé plus récent et 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)
2
ArnoVR

Je résous ceci avec:

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" est le moyen de savoir si le ping est correct . Saludos 

2
user3620655

Ce script fonctionne sous Windows et devrait fonctionner sous d’autres systèmes d’exploitation: Il fonctionne sous Windows, Debian et macosx, et nécessite un test sur 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
1
Matthew

J'ai aimé ping3 https://github.com/kyan001/ping3 Très simple et pratique!

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

J'avais des exigences similaires, je l'ai donc implémenté comme indiqué ci-dessous. Il est testé sur Windows 64 bits et 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))

Lorsque IP n'est pas accessible, subprocess.check_output () déclenche une exception. Une vérification supplémentaire peut être effectuée en extrayant des informations de la ligne de sortie 'Paquets: envoyés = 2, reçus = 2, perdus = 0 (perte 0%)'.

1
Luminos

Voici une solution utilisant le module subprocess de Python et l'outil CLI ping fourni par le système d'exploitation sous-jacent. Testé sous Windows et Linux. Prise en charge de la configuration d'un délai d'attente du réseau. N'a pas besoin de privilèges root (au moins sur Windows et 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
1
Epoc

Utilisez ceci, il est testé sur Python 2.7 et fonctionne correctement. Il renvoie le temps de ping en millisecondes en cas de succès et renvoie False en cas d'échec.

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
0
MSS

Vous pouvez utiliser l'exception TimeoutExpired du module de sous-processus pour intercepter les délais d'attente de ping (quelque chose que les autres réponses n'ont pas exploité.) Notez que cette solution ne fonctionne que sous Linux.

def ping(Host, timeout=3):
    """
    Send a ping (ICMP) request to a remote Host.

    The command is set to ``ping -c 1 -W 1 <Host>``, which sends exactly 1 ping
    packet, and waits for 1 second before terminating.

    Args:
        Host (str): Hostname or IP address.
        timeout (int): Ping command timeout (in seconds).

    Returns:
        bool: The ping response. ``True`` if the Host responds to a ping request 
            within the specified timeout period. ``False`` otherwise.

    Note:
        A Host may not respond to a ping (ICMP) request even if the Host name is 
        valid because of firewall rules.
    """
    # Building the command. Ex: "ping -c 1 google.com"
    command = ['ping', Host, '-W', '1', '-c', '1']

    try:
        subprocess.run(command, timeout=timeout, check=True)
        return True
    except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
        #log.warning("Failed to ping Host: %s with timeout: %d", Host, timeout)
        return False
0
teraflik

Cela semble assez simple, mais m'a donné des crises. Je continuais à obtenir "opération de socket ouvert icmp non autorisée", sinon les solutions ne fonctionneraient pas si le serveur était hors ligne. Si, toutefois, vous voulez savoir que le serveur est actif et que vous utilisez un serveur Web sur ce serveur, alors curl fera le travail. Si vous avez ssh et des certificats, alors ssh et une commande simple suffiront. Voici le code:

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
0
user2099484

WINDOWS UNIQUEMENT - Vous ne pouvez pas croire que personne ne soit craqué ouvrez Win32_PingStatus En utilisant une simple requête WMI, nous renvoyons gratuitement un objet contenant des informations vraiment détaillées 

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'

exemple de sortie

0
Aimondy

Ma prise empruntant d'autres réponses. Essayez de simplifier et de minimiser les requêtes.

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"
0
misantroop

Une chose que beaucoup de réponses manquent, c'est que (du moins sous Windows) la commande ping renvoie 0 (indiquant le succès) si elle reçoit la réponse "Hôte de destination inaccessible".

Voici mon code qui vérifie si b'TTL=' est dans la réponse, puisqu'il n'est présent que lorsque le ping a atteint l'hôte. Remarque: La plupart de ce code est basé sur les autres réponses ici.

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

Remarque: Ceci capture la sortie au lieu de l’imprimer. Par conséquent, si vous souhaitez voir la sortie de ping, vous devez imprimer completedPing.stdout avant de renvoyer.

0
Brent Robertson

Ma version d'une fonction ping:

  • Fonctionne sur Python 3.5 et versions ultérieures, sur Windows et Linux (devrait fonctionner sur Mac, mais ne peut pas le tester).
  • Sous Windows, renvoie False si la commande ping échoue avec "Hôte de destination inaccessible".
  • Et ne montre aucune sortie, que ce soit sous forme de fenêtre contextuelle ou en ligne de commande.
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

N'hésitez pas à l'utiliser comme vous voulez.