Відповіді:
Ця функція працює в будь-яких ОС (Unix, Linux, macOS та Windows)
Python 2 та Python 3
РЕДАКТИ:
Автор @radato os.system
був замінений на subprocess.call
. Це дозволяє уникнути вразливості введення оболонки у випадках, коли рядок імені хоста може бути не підтверджений.
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
Зауважте, що згідно @ikrase в Windows, ця функція все одно повернеться, True
якщо ви отримаєте Destination Host Unreachable
помилку.
Пояснення
Команда є ping
як в Windows, так і в Unix-подібних системах.
Параметр -n
(Windows) або -c
(Unix) контролює кількість пакетів, для яких у цьому прикладі було встановлено 1.
platform.system()
повертає назву платформи. Вих. 'Darwin'
на macOS.
subprocess.call()
виконує системний виклик. Вих. subprocess.call(['ls','-l'])
.
ping 8.8.8.8 -n 1
3) echo %ERRORLEVEL%
. Код: Змініть останній рядок коду Python на return system_call(command)
. При правильному підключенні ви отримаєте 0 (нуль). Якщо модем вимкнено, ви повинні отримати код помилки. Звичайно, обидва способи повинні повернути один і той же код помилки за однакових умов.
Якщо вам не потрібно підтримувати Windows, ось дійсно стислий спосіб зробити це:
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!'
Це працює, тому що ping повертає ненульове значення, якщо з'єднання не працює. (Повернене значення насправді відрізняється залежно від помилки мережі.) Ви також можете змінити час очікування ping (у секундах), використовуючи опцію '-t'. Зверніть увагу, це виведе текст на консоль.
response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
man ping
щоб переконатися.
hostname
рядок від користувача, він може легко зламати ваш сервер, надаючи вам такий "URL" 'google.com; rm -rf /*'
. Використовуйте subprocess.run(["ping", "-c", "1", hostname]).returncode
замість цього.
Існує модуль під назвою pyping, який може це зробити. Його можна встановити за допомогою pip
pip install pyping
Користуватися досить просто, проте при використанні цього модуля вам потрібен кореневий доступ через те, що він обробляє необроблені пакети під кришкою.
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')
розчин. Плюс pyping
lib дуже простий у використанні порівняно з використанням бібліотеки сокетів TCP / IP. Я написав свою програму ping, використовуючи обидві, і pyping
це набагато швидше та простіше у використанні, на мій погляд, особливо, якщо хтось не знайомий з використанням бібліотеки сокетів 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
для отримання правильного шляху.
ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
Для python3 є дуже простий і зручний модуль python ping3 : (( pip install ping3
, потребує root права).
from ping3 import ping, verbose_ping
ping('example.com') # Returns delay in seconds.
>>> 0.215697261510079666
Цей модуль також дозволяє налаштувати деякі параметри.
Оскільки мені подобається мати свою програму Python універсальною для версій 2.7 та 3.x та для платформ Linux, Mac OS та Windows, мені довелося змінити існуючі приклади.
# 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
можна, звичайно, також просто використовувати platform.system().lower() != "windows"
.
os.name!="nt"
працює також? Правда, я не пробував це на всіх версіях версій / платформ!
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
його знайдете в трубі, ні?
Оглянувшись, я закінчив написання власного модуля ping, який призначений для моніторингу великої кількості адрес, асинхронний і не використовує багато системних ресурсів. Ви можете знайти його тут: https://github.com/romana/multi-ping/ Це ліцензія на Apache, тому ви можете використовувати його у своєму проекті будь-яким способом, який вважаєте за потрібне.
Основними причинами реалізації мого власного є обмеження інших підходів:
#!/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()
Переконайтеся в правильності установки pyping або встановити його пункт встановити pyping
#!/usr/bin/python
import pyping
response = pyping.ping('Your IP')
if response.ret_code == 0:
print("reachable")
else:
print("unreachable")
Programmatic ICMP пінг ускладнено - за підвищених привілеїв , необхідних для відправки сирих пакетів ICMP, і виклик ping
бінарного некрасиво. Для серверного моніторингу ви можете досягти того ж результату, використовуючи техніку під назвою 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
Всередині цього просто встановлюється TCP-з'єднання з цільовим сервером і одразу перестає його, вимірюючи минулий час. Ця реалізація дещо обмежена тим, що вона не обробляє закриті порти, але для власних серверів вона працює досить добре.
Я вирішую це за допомогою:
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" - це спосіб дізнатися, чи правильно ping. Салудос
Моє скорочення, використовуючи ідеї відповідей у цій публікації, але лише використовуючи новіший рекомендований модуль підпроцесу та 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
для повернення True або False на основі умови. Просто використовуйте напр. shell_needed = operating_sys == 'Windows'
Іreturn success == 0
Цей скрипт працює в Windows і повинен працювати на інших ОС: Він працює в Windows, Debian і macosx, потрібен тест на 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
Я нарешті знайшов це питання щодо аналогічного сценарію. Я спробував піпінг, але приклад, приведений Naveen, не працював для мене в Windows під Python 2.7.
Приклад, який працював для мене:
import pyping
response = pyping.send('Your IP')
if response['ret_code'] == 0:
print("reachable")
else:
print("unreachable")
pyping
не представляється стандартним модулем. Можливо, ви могли б надати посилання?
Використовуючи Multi-ping ( pip install multiPing
), я зробив цей простий код ( просто скопіюйте та вставте, якщо хочете! ):
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
Використання:
#Getting the latency average (in seconds) of host '192.168.0.123' using 10 samples
ping('192.168.0.123',10)
Якщо ви хочете одного зразка, другий параметр " 10
" можна ігнорувати!
Сподіваюся, це допомагає!
Моя версія функції 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
Не соромтеся використовувати його як завгодно.
Здається, досить просто, але мені підходило. Я продовжував отримувати "операцію з відкритим сокетом icmp заборонено", інакше рішення б зависло, якби сервер був відключений. Якщо, однак, ви хочете знати, що сервер живий і на цьому сервері ви працюєте з веб-сервером, то згортання зробить цю роботу. Якщо у вас є ssh та сертифікати, то ssh та простої команди буде достатньо. Ось код:
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
У мене була схожа вимога, тому я реалізував її, як показано нижче. Він тестується на Windows 64 біт та 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))
Коли IP недоступний, subprocess.check_output () створює виняток. Додаткову перевірку можна здійснити, витягуючи інформацію з вихідного рядка "Пакети: відправлено = 2, отримано = 2, втрачено = 0 (0% втрати)".
Ось рішення з використанням subprocess
модуля Python та ping
інструмента CLI, що надається базовою ОС. Тестується в Windows та Linux. Підтримка налаштування мережевого тайм-ауту. Не потрібні кореневі привілеї (принаймні для Windows та 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
Використовуйте це тестоване на python 2.7 і працює чудово, він повертає час пінгу в мілісекундах, якщо успіх і повернення 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
Одне, у чому багато пропущених відповідей, - це те, що (принаймні в Windows) ping
команда повертає 0 (що свідчить про успіх), якщо вона отримає відповідь "Місце призначення не досяжне".
Ось мій код, який перевіряє, чи b'TTL='
є у відповіді, оскільки він присутній лише тоді, коли пінг дійшов до хоста. Примітка: Більшість цього коду заснована на інших відповідях тут.
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'))
Примітка. Це захоплює вихід, а не друкує його, тому якщо ви хочете побачити вихід ping
, вам потрібно буде надрукувати completedPing.stdout
перед поверненням.
ВІННІ ТОЛЬКО - Не можу повірити, що ніхто не зламався Win32_PingStatus За допомогою простого запиту WMI ми повертаємо об'єкт, повний справді детальної інформації безкоштовно
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'
Мені потрібна була швидша перевірка пінгу, і я не хотів використовувати жодних зовнішніх бібліотек, тому вирішив використовувати паралельність за допомогою вбудованої asyncio
.
Цей код вимагає python 3.7+ і виробляється та тестується лише на Linux . Він не працює в Windows, але я впевнений, що ви можете легко змінити його на роботу в Windows.
Я не експерт, asyncio
але я використав цю чудову статтю « Швидкість роботи програми Python With Concurrency», і я придумав ці рядки кодів. Я намагався зробити це максимально простим, тому, швидше за все, вам потрібно буде додати до нього більше коду, щоб відповідати вашим потребам.
Він не повертає істину чи хибність, я вважав, що було б зручніше просто надрукувати IP-адресу, яка відповідає на запит ping. Я думаю, що це досить швидко, пінгвінг 255 ips за майже 10 секунд.
#!/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())
Вибірка зразка:
192.168.1.1
192.168.1.3
192.168.1.102
192.168.1.106
192.168.1.6
Зауважте, що IP-адреси не в порядку, оскільки IP-адреса друкується, як тільки вона відповідає, тож перша, що реагує на неї, надрукується першою.
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"
Простий, який я щойно приготував за хвилину. Використання icmplib потребує кореневих привітів нижче, працює досить добре! HTH