Respostas:
Essa função funciona em qualquer sistema operacional (Unix, Linux, macOS e Windows)
Python 2 e Python 3
EDITS:
Por @radato os.system
foi substituído por subprocess.call
. Isso evita a vulnerabilidade de injeção de shell nos casos em que a string do nome do host pode não ser validada.
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
Observe que, de acordo com o @ikrase no Windows, essa função ainda retornará True
se você receber um Destination Host Unreachable
erro.
Explicação
O comando está ping
nos sistemas Windows e Unix.
A opção -n
(Windows) ou -c
(Unix) controla o número de pacotes que neste exemplo foram definidos como 1.
platform.system()
retorna o nome da plataforma. Ex. 'Darwin'
no macOS.
subprocess.call()
realiza uma chamada do sistema. Ex. subprocess.call(['ls','-l'])
.
ping 8.8.8.8 -n 1
3) echo %ERRORLEVEL%
. Código: modifique a última linha do código Python para return system_call(command)
. Com conectividade adequada, você receberá 0 (zero). Com o modem desligado, você deve obter algum código de erro. Obviamente, os dois métodos devem retornar o mesmo código de erro nas mesmas condições.
Se você não precisa oferecer suporte ao Windows, aqui está uma maneira realmente concisa de fazê-lo:
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!'
Isso funciona porque o ping retorna um valor diferente de zero se a conexão falhar. (O valor de retorno realmente difere dependendo do erro de rede.) Você também pode alterar o tempo limite do ping (em segundos) usando a opção '-t'. Observe que isso produzirá texto para o console.
response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
man ping
para ter certeza.
hostname
string de um usuário, ele poderá facilmente invadir seu servidor, fornecendo a você um "URL" 'google.com; rm -rf /*'
. Use em subprocess.run(["ping", "-c", "1", hostname]).returncode
vez disso.
Existe um módulo chamado pyping que pode fazer isso. Pode ser instalado com pip
pip install pyping
É bastante simples de usar, no entanto, ao usar este módulo, você precisa de acesso root, pois ele está criando pacotes brutos sob o capô.
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')
solução. Além disso, a pyping
lib é muito fácil de usar em comparação com o uso da biblioteca de soquetes TCP / IP. Escrevi meu programa de ping usando os dois e pyping
, na minha opinião, é muito mais rápido e fácil de usar, especialmente se não estiver familiarizado com o uso da biblioteca de soquetes 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
para obter o caminho correto.
ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
Para python3, existe um módulo python muito simples e conveniente, ping3 : ( pip install ping3
, precisa de privilégios de root ).
from ping3 import ping, verbose_ping
ping('example.com') # Returns delay in seconds.
>>> 0.215697261510079666
Este módulo também permite a personalização de alguns parâmetros.
Como eu gosto de ter meu programa Python universal nas versões 2.7 e 3.xe na plataforma Linux, Mac OS e Windows, tive que modificar os exemplos 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"))
False if platform.system().lower()=="windows" else True
você, é claro, também pode usar platform.system().lower() != "windows"
.
os.name!="nt"
Também não funciona? É certo que eu não tentei em todos os combos ver / plataforma!
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
for encontrado no pipe, não?
Depois de olhar em volta, acabei escrevendo meu próprio módulo de ping, projetado para monitorar um grande número de endereços, é assíncrono e não usa muitos recursos do sistema. Você pode encontrá-lo aqui: https://github.com/romana/multi-ping/ É licenciado pela Apache, para que você possa usá-lo em seu projeto da maneira que achar melhor.
As principais razões para implementar o meu próprio são as restrições das outras abordagens:
#!/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()
Verifique se o pyping está instalado ou instale-o pip install pyping
#!/usr/bin/python
import pyping
response = pyping.ping('Your IP')
if response.ret_code == 0:
print("reachable")
else:
print("unreachable")
O ping programático do ICMP é complicado devido aos privilégios elevados necessários para o envio de pacotes ICMP brutos, e a chamada de ping
binário é feia. Para monitoramento do servidor, você pode obter o mesmo resultado usando uma técnica chamada 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, isso simplesmente estabelece uma conexão TCP com o servidor de destino e a elimina imediatamente, medindo o tempo decorrido. Essa implementação em particular é um pouco limitada, pois não lida com portas fechadas, mas para seus próprios servidores funciona muito bem.
Eu resolvo isso com:
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" é a maneira de saber se o ping está correto. Saludos
Minha redução usando idéias de respostas neste post, mas apenas usando o módulo de subprocesso recomendado mais recente e 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
para retornar True ou False com base em uma condição. Basta usar eg shell_needed = operating_sys == 'Windows'
ereturn success == 0
Este script funciona no Windows e deve funcionar em outros sistemas operacionais: Ele funciona no Windows, Debian e macosx, precisa de um teste no 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
Acabei encontrando essa pergunta em um cenário semelhante. Eu experimentei o pyping, mas o exemplo dado por Naveen não funcionou para mim no Windows no Python 2.7.
Um exemplo que funcionou para mim é:
import pyping
response = pyping.send('Your IP')
if response['ret_code'] == 0:
print("reachable")
else:
print("unreachable")
pyping
não parece ser um módulo padrão. Talvez você possa fornecer um link?
Usando Multi-ping ( pip install multiPing
) eu criei este código simples ( basta copiar e colar, se você quiser! ):
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
Uso:
#Getting the latency average (in seconds) of host '192.168.0.123' using 10 samples
ping('192.168.0.123',10)
Se você deseja uma única amostra, o segundo parâmetro " 10
" pode ser ignorado!
Espero que ajude!
Minha versão de uma função 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
Sinta-se livre para usá-lo como quiser.
Parece bastante simples, mas me deu ataques. Eu continuava recebendo "operação de soquete aberto icmp não permitida" ou as soluções seriam interrompidas se o servidor estivesse off-line. Se, no entanto, o que você deseja saber é que o servidor está ativo e você está executando um servidor Web nesse servidor, o curl fará o trabalho. Se você possui ssh e certificados, ssh e um comando simples serão suficientes. Aqui está o 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
Eu tinha requisitos semelhantes, então eu o implementei como mostrado abaixo. É testado no Windows 64 bits e 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))
Quando o IP não está acessível, subprocess.check_output () gera uma exceção. Uma verificação extra pode ser feita extraindo informações da linha de saída 'Pacotes: Enviados = 2, Recebidos = 2, Perdidos = 0 (0% de perda)'.
Aqui está uma solução usando o subprocess
módulo Python e a ping
ferramenta CLI fornecida pelo sistema operacional subjacente. Testado no Windows e Linux. Suporte para definir um tempo limite de rede. Não precisa de privilégios de root (pelo menos no Windows e 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
Use isso: ele é testado no python 2.7 e funciona bem; ele retorna o tempo de ping em milissegundos se for bem-sucedido e retornará False em caso de falha.
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
Uma coisa que muitas das respostas perdem é que (pelo menos no Windows) o ping
comando retorna 0 (indicando êxito) se receber a resposta "Host de destino inacessível".
Aqui está o meu código que verifica se b'TTL='
está na resposta, uma vez que está presente apenas quando o ping chegou ao host. Nota: A maior parte desse código é baseada nas outras respostas aqui.
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: Isso captura a saída em vez de imprimi-la; portanto, se você quiser ver a saída ping
, precisará imprimir completedPing.stdout
antes de retornar.
APENAS PARA WINDOWS - Não é possível acreditar que ninguém abriu Win32_PingStatus Usando uma consulta WMI simples, retornamos um objeto cheio de informações realmente detalhadas gratuitamente
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'
Minha opinião é emprestada de outras respostas. Tente simplificar e minimizar as consultas.
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"
Eu precisava de uma varredura de ping mais rápida e não queria usar nenhuma biblioteca externa, então resolvi usar a simultaneidade usando o built-in asyncio
.
Este código requer python 3.7+ e é feito e testado apenas no Linux . Não funcionará no Windows, mas tenho certeza de que você pode alterá-lo facilmente para funcionar no Windows.
Não sou especialista, asyncio
mas usei este ótimo artigo Acelere seu programa Python com simultaneidade e criei essas linhas de códigos. Tentei torná-lo o mais simples possível, portanto é mais provável que você precise adicionar mais código para atender às suas necessidades.
Não retorna verdadeiro ou falso, pensei que seria mais conveniente apenas imprimir o IP que responde a uma solicitação de ping. Eu acho que é bem rápido, pingando 255 ips em quase 10 segundos.
#!/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())
Saída de amostra:
192.168.1.1
192.168.1.3
192.168.1.102
192.168.1.106
192.168.1.6
Observe que os IPs não estão em ordem, pois o IP é impresso assim que responde, portanto, o que responder primeiro será impresso primeiro.
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"
Um simples que acabei de preparar em um minuto ... usando o icmplib precisa de raiz privs, o abaixo funciona muito bem! HTH