ส่ง Ping ไปยังเซิร์ฟเวอร์ใน Python


167

ใน Python มีวิธีการ ping เซิร์ฟเวอร์ผ่าน ICMP และส่งคืน TRUE หากเซิร์ฟเวอร์ตอบกลับหรือเป็น FALSE หากไม่มีการตอบกลับหรือไม่


คำตอบ:


112

ฟังก์ชั่นนี้ใช้งานได้กับระบบปฏิบัติการ (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']).


14
โปรดทราบว่าสิ่งนี้จะยังคงเป็นจริง (บน Windows) หากคุณได้รับคำตอบ "ปลายทางโฮสต์ที่ไม่สามารถเข้าถึงได้" จากโฮสต์อื่น
ikrase

ฉันพบว่าบางครั้งฉันจะประสบความสำเร็จในการ ping เมื่อโมเด็มของฉันปิด ??? นั่นคือการทดสอบ "8.8.8.8" และ "google.com" บนระบบปฏิบัติการ Windows 10 มีบางอย่างไม่ถูกต้อง
Markus

ไม่สามารถเกิดขึ้นได้ @Markus โปรดทดสอบด้วยมือและด้วยรหัสที่มีการแก้ไขด้านบนและแจ้งผลให้เราทราบ ด้วยมือ 1) เปิด cmd 2) 3)ping 8.8.8.8 -n 1 echo %ERRORLEVEL%รหัสสินค้า: return system_call(command)ปรับเปลี่ยนบรรทัดสุดท้ายของรหัสงูหลาม ด้วยการเชื่อมต่อที่เหมาะสมคุณจะได้รับ 0 (ศูนย์) เมื่อโมเด็มปิดคุณต้องได้รับรหัสข้อผิดพลาด แน่นอนทั้งสองวิธีจะต้องส่งคืนรหัสข้อผิดพลาดเดียวกันภายใต้เงื่อนไขเดียวกัน
ePi272314

มันเกิดขึ้นและฉันใช้รหัสที่แน่นอนคำต่อคำ ฉันเข้าใจและเชื่อในความคิดเห็นของคุณไม่มีวิธีใดที่ ping บรรทัดคำสั่งจะประสบความสำเร็จเมื่อไม่มีการเชื่อมต่อดังนั้นฉันจึงคิดว่าบางสิ่งบางอย่างทำงานไม่ถูกต้องใน python กับการดำเนินการของบรรทัดคำสั่ง ฉันจะลองอัปเดตและดูว่ามันจะเป็นอย่างไร ขอบคุณ
Markus

@Markus เห็นความคิดเห็นของ ikrase
บอริส

163

หากคุณไม่ต้องการรองรับ 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' หมายเหตุสิ่งนี้จะส่งข้อความไปยังคอนโซล


42
ฉันลงเอยด้วยตัวแปรนี้response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
MGP

4
@ jeckyll2hide man ping ส่งเพียง 1 แพ็คเก็ตด้วยกำหนดเวลา 2 วินาทีและเปลี่ยนเส้นทางเอาต์พุตทั้งหมดไปยัง / dev / null ดึงเฉพาะค่าที่ส่งคืน
MGP

@ManuelGutierrez ฉันคิดว่าคุณต้องการ "-W 2000" (หมดเวลาหลังจากที่ 2,000 มิลลิวินาที) และอาจจะ "t-3" (ถึงแก่กรรมหลังจาก 3 วินาทีว่าสิ่งที่ไม่ได้)
eludom

1
-w และ -W รับค่าในไม่กี่วินาทีไม่ใช่มิลลิวินาที ตรวจสอบman pingให้แน่ใจ
อลันทัวริง

7
หากคุณได้รับhostnameสตริงจากผู้ใช้พวกเขาสามารถแฮ็คเซิร์ฟเวอร์ของคุณได้อย่างง่ายดายโดยให้ "url" เช่น'google.com; rm -rf /*'คุณ ใช้subprocess.run(["ping", "-c", "1", hostname]).returncodeแทน
บอริส

38

มีโมดูลที่เรียกว่า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))

4
"โปรดทราบว่าข้อความ ICMP สามารถส่งได้จากกระบวนการที่ทำงานเป็นรูทเท่านั้น (ใน Windows คุณต้องเรียกใช้สคริปต์นี้ในฐานะ 'ผู้ดูแลระบบ')"
Ben Hyde

1
ฉันชอบที่คุณสามารถระบุการหมดเวลาและจำนวนคำขอ ICMP ที่ส่ง ฉันสามารถเขียนสคริปต์ที่ค้นพบโฮสต์ทั้งหมดในเครือข่ายย่อยท้องถิ่น มันรันใน 1 วินาทีแทนที่จะเป็น 255 วินาทีโดยใช้os.system('ping -c 1 -t 1 hostname')วิธีแก้ปัญหา นอกจากนี้pypinglib ยังใช้งานง่ายมากเมื่อเทียบกับการใช้ไลบรารีซ็อกเก็ต TCP / IP ฉันเขียนโปรแกรม ping โดยใช้ทั้งคู่และpypingเร็วกว่าและใช้งานง่ายกว่ามากโดยเฉพาะอย่างยิ่งหากไม่คุ้นเคยกับการใช้ไลบรารีซ็อกเก็ต TCP / IP
MikeyE

10
ไม่ทำงานกับ py3 ModuleNotFoundError: ไม่มีโมดูลชื่อ 'core'
alireza

2
ข้อผิดพลาด 'core' มาจากความไม่ลงรอยกันกับ python3 ฉันพยายามแก้ไข python3 แต่มันส่งข้อผิดพลาดมาเรื่อย ๆ ผู้แต่งและโครงการหน้า github ไม่ทำงาน (ไม่พบ 404) เราจะต้องทำการพอร์ตด้วยตัวเองกับ python3 :-)
อังเดร

6
สำหรับ python3 ลอง ping3: github.com/kyan001/ping3 pip install ping3
beep_check

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

6
ปัญหาเดียวของเรื่องนี้ก็คือมันจะไม่ทำงานบน Windows
Kudu

8
ควรกล่าวถึงเหตุผลที่สิ่งนี้เป็นสิ่งจำเป็นเนื่องจาก ICMP ต้องการรูทและ / bin / ping ได้รับสิ่งนี้โดยการตั้งค่า SUID
Catskul

1
หมายเหตุ: อาจล้มเหลวหาก ping อยู่ในตำแหน่งอื่น ใช้whereis pingเพื่อให้ได้เส้นทางที่ถูกต้อง
ตุลาคม

4
สิ่งนี้ใช้ได้กับ Windows:ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
Victor Lellis

1
ฉันจะแยกผลลัพธ์เพื่อตรวจสอบว่าการตอบสนองเป็น ok หรือ ko ใน Windows ได้อย่างไร
Pitto

15

สำหรับ python3 มีโมดูลหลามง่ายและสะดวกมากping3 : ( pip install ping3ความต้องการรากสิทธิพิเศษ)

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

โมดูลนี้ช่วยให้สามารถปรับแต่งพารามิเตอร์บางอย่างได้เช่นกัน


2
ในฐานะที่เป็นแก้ไขต้องใช้สิทธิ์รูทการสนทนาเกี่ยวกับการยกที่นี่: github.com/kyan001/ping3/issues/10
Dimitrios Mistriotis

1
โอ้ต้องการราก prvilege ไม่เพียง แต่สำหรับการติดตั้ง แต่ยังสำหรับการดำเนินการ: ping ("example.com")
นาฬิกา ZHONG

14

เนื่องจากฉันต้องการให้โปรแกรม 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"))

1
แทนการที่คุณสามารถเรียนก็เป็นเพียงแค่การใช้งานFalse if platform.system().lower()=="windows" else True platform.system().lower() != "windows"
Frerich Raabe

ไม่ได้os.name!="nt"นอกจากนี้ยังมีการทำงานอย่างไร เป็นที่ยอมรับฉันไม่ได้ลองเลยในคอมโบ ver / platform ทั้งหมด!
Keeely

2
ในกรณีของฉันเกตเวย์เริ่มต้นส่งคืนข้อความ 'ไม่สามารถเข้าถึงได้' แต่คำสั่ง windows ping ยังคงมีรหัสส่งคืนเป็น 0 ดังนั้นวิธีการนี้ใช้งานได้ (ขออภัยสำหรับการจัดรูปแบบ - 6 บรรทัดรวมถึงการประกาศ functiontion): 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
wellspokenman

@wellspokenman คุณอยากกลับ 0 ถ้าunreachableพบในท่อใช่ไหม?
beeb

1
@beeb ใช่ฉันก็ทำเช่นนั้น แต่ลืมปรับปรุงความคิดเห็น ฟังก์ชั่นปัจจุบันของฉันมีลักษณะเช่นนี้: pastebin.com/FEYWsVjK
wellspokenman

8

หลังจากมองไปรอบ ๆ ฉันก็เลยเขียนโมดูล ping ของตัวเองซึ่งออกแบบมาเพื่อตรวจสอบที่อยู่จำนวนมากแบบอะซิงโครนัสและไม่ได้ใช้ทรัพยากรระบบจำนวนมาก คุณสามารถค้นหาได้ที่นี่: https://github.com/romana/multi-ping/เป็น Apache ที่ได้รับอนุญาตดังนั้นคุณสามารถใช้มันในโครงการของคุณในแบบที่คุณเห็นสมควร

เหตุผลหลักสำหรับการใช้งานของฉันคือข้อ จำกัด ของวิธีการอื่น ๆ :

  • โซลูชันจำนวนมากที่กล่าวถึงในที่นี้ต้องการการเรียกใช้งานกับยูทิลิตี้บรรทัดคำสั่ง นี่ค่อนข้างไม่มีประสิทธิภาพและทรัพยากรหิวถ้าคุณต้องการตรวจสอบที่อยู่ IP จำนวนมาก
  • คนอื่นพูดถึงโมดูลหลาม ping เก่าบางอย่าง ฉันดูที่และท้ายที่สุดพวกเขาทั้งหมดมีปัญหาหรืออื่น ๆ (เช่นการตั้งค่ารหัสแพ็คเก็ตไม่ถูกต้อง) และไม่ได้จัดการ ping-ing ของที่อยู่จำนวนมาก

เพื่อนร่วมงานที่ดี! หากใครต้องการเห็นมันในทางปฏิบัติเพียงใช้ github.com/romana/multi-ping/blob/master/demo.py
Cucu

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

รหัสนี้อาจมีคำตอบสำหรับคำถาม แต่จะเป็นประโยชน์ในการเพิ่มความคิดเห็นหรือคำอธิบายว่ารหัสของคุณแก้ปัญหาอย่างไร
skrrgwasme

5

ต้องแน่ใจว่าติดตั้ง pyping แล้วหรือติดตั้งpip ติดตั้ง pyping

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

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

1
ขอบคุณ! อย่างไรก็ตามฉันจำเป็นต้องเรียกใช้รหัสนี้ในฐานะรูทเพื่อให้ทำงานได้
โทมัส

1
ไม่มีหน้า GitHub ของ Pyping อีกต่อไปและแพคเกจ PyPIยังไม่ได้รับการอัปเดตตั้งแต่ปี 2016
Stevoisiak

ฉันพบข้อผิดพลาดต่อไปนี้: อิมพอร์ต pyping Traceback (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "<stdin>", บรรทัดที่ 1, ใน <module> ไฟล์ "/usr/local/lib/python3.6/dist-packages/pyping/__init__ py ", บรรทัดที่ 3, ใน <โมดูล> จาก core import * ModuleNotFoundError: ไม่มีโมดูลชื่อ 'core'
นาฬิกา ZHONG

5

ICMP ping แบบเป็นโปรแกรมมีความซับซ้อนเนื่องจากสิทธิพิเศษที่จำเป็นในการส่งแพ็คเก็ต 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 ไปยังเซิร์ฟเวอร์เป้าหมายและวางลงทันทีโดยการวัดเวลาที่ผ่านไป การใช้งานเฉพาะนี้มีข้อ จำกัด เล็กน้อยที่ไม่รองรับพอร์ตปิด แต่สำหรับเซิร์ฟเวอร์ของคุณเองก็ใช้งานได้ดี


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

3

ฉันแก้ไขปัญหานี้ด้วย:

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 นั้นถูกต้องหรือไม่ saludos


3

การลดลงของฉันโดยใช้แนวคิดจากคำตอบในโพสต์นี้ แต่ใช้เฉพาะโมดูลย่อยที่แนะนำใหม่และ 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)

1
คุณไม่จำเป็นต้องใช้True if condition else Falseเพื่อคืนค่าจริงหรือเท็จตามเงื่อนไข เพียงใช้เช่นshell_needed = operating_sys == 'Windows'และreturn success == 0
emorris

2

สคริปต์นี้ทำงานบน 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

คำตอบที่ดี. ไม่มีสิทธิ์ผู้ดูแลระบบสำหรับ Windows ที่นี่
เขา

Am ทางใดทางหนึ่งที่ได้รับทรูทั้งขวาและ IP ผิด
โยอาช

ใช่สิ่งนี้ไม่ทำงานแน่นอน เพียงแค่คืนค่า: "จริง" ทั้งสองวิธีบน Windows
MKANET

2

ฉันสิ้นสุดการค้นหาคำถามนี้เกี่ยวกับสถานการณ์ที่คล้ายกัน ฉันลอง pyping แต่ตัวอย่างที่ Naveen ใช้ไม่ได้กับฉันใน Windows ภายใต้ Python 2.7

ตัวอย่างที่เหมาะกับฉันคือ:

import pyping

response = pyping.send('Your IP')

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

1
pypingไม่ปรากฏเป็นโมดูลมาตรฐาน บางทีคุณอาจให้ลิงค์หรือไม่
Mawg กล่าวว่าคืนสถานะโมนิก้า

2

ใช้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" สามารถถูกละเว้นได้!

หวังว่ามันจะช่วย!


4
ไลบรารีที่น่ากลัว แต่ต้องการสิทธิ์รูท
Craynic Cai

2

ฟังก์ชั่น ping รุ่นของฉัน:

  • ใช้งานได้กับ Python 3.5 และใหม่กว่าบน Windows และ Linux (ควรใช้กับ Mac แต่ไม่สามารถทดสอบได้)
  • บน Windows ส่งคืน False ถ้าคำสั่ง ping ล้มเหลวด้วย "Destination Host Unreachable"
  • และไม่แสดงผลลัพธ์ใด ๆ ไม่ว่าจะเป็นหน้าต่างป๊อปอัปหรือในบรรทัดคำสั่ง
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

รู้สึกอิสระที่จะใช้ตามที่คุณจะ


1

ดูเหมือนจะง่าย แต่ให้ฉันพอดี ฉันยังคงได้รับ "การดำเนินการซ็อกเก็ตเปิด icmp ไม่ได้รับอนุญาต" มิฉะนั้นการแก้ปัญหาจะวางสายหากเซิร์ฟเวอร์ไม่อยู่ในบรรทัด อย่างไรก็ตามหากสิ่งที่คุณต้องการทราบก็คือเซิร์ฟเวอร์ยังมีชีวิตอยู่และคุณกำลังเรียกใช้เว็บเซิร์ฟเวอร์บนเซิร์ฟเวอร์นั้น curl จะทำงาน หากคุณมี 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

1

ฉันมีข้อกำหนดที่คล้ายกันดังนั้นฉันจึงนำไปใช้ตามที่แสดงด้านล่าง ผ่านการทดสอบบน 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%)'


1

นี่คือวิธีการแก้ปัญหาโดยใช้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

0

ใช้สิ่งนี้มันผ่านการทดสอบใน python 2.7 และทำงานได้ดีมันส่งคืนเวลา ping เป็นมิลลิวินาทีถ้าสำเร็จและคืนเท็จเมื่อล้มเหลว

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

สิ่งหนึ่งที่คำตอบที่พลาดมากคือ (อย่างน้อยใน 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ก่อนส่งคืน


0

WINDOWS ONLY - ไม่เชื่อเลยว่าไม่มีใครถอดรหัสเปิด 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'

ตัวอย่างผลลัพธ์


0

ฉันยืมมาจากคำตอบอื่น พยายามลดความซับซ้อนและลดแบบสอบถาม

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

ผมจำเป็นต้องกวาด ping ได้เร็วขึ้นและผมไม่ต้องการที่จะใช้ห้องสมุดภายนอกใด ๆ asyncioดังนั้นผมจึงมีมติเห็นพ้องใช้ที่ใช้ในตัว

รหัสนี้ต้องการpython 3.7+และทำและทดสอบบนLinuxเท่านั้น มันใช้งานไม่ได้บน Windows แต่ฉันมั่นใจว่าคุณสามารถเปลี่ยนให้ทำงานบน Windows ได้อย่างง่ายดาย

ฉันไม่ใช่ผู้เชี่ยวชาญasyncioแต่ฉันใช้บทความที่ยอดเยี่ยมนี้เพื่อเร่งความเร็วโปรแกรม Python ของคุณพร้อม ๆ กันและฉันก็ใช้โค้ดเหล่านี้ ฉันพยายามทำให้มันง่ายที่สุดเท่าที่จะเป็นไปได้ดังนั้นส่วนใหญ่คุณจะต้องเพิ่มรหัสเพิ่มเติมเพื่อให้เหมาะกับความต้องการของคุณ

มันไม่ได้คืนจริงหรือเท็จฉันคิดว่ามันจะสะดวกกว่าเพียงแค่พิมพ์ 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 ทันทีที่ตอบกลับดังนั้นข้อมูลที่ตอบกลับจะได้รับการพิมพ์ก่อน


-3
  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 ต้องการ privs รากด้านล่างใช้งานได้ค่อนข้างดี! HTH

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.