Làm cách nào để ping một trang web hoặc địa chỉ IP bằng Python?
Làm cách nào để ping một trang web hoặc địa chỉ IP bằng Python?
Câu trả lời:
Xem ping Python thuần túy này của Matthew Dixon Cowles và Jens Diemer . Ngoài ra, hãy nhớ rằng Python yêu cầu root để tạo ra các socket ICMP (tức là ping) trong linux.
import ping, socket
try:
ping.verbose_ping('www.google.com', count=3)
delay = ping.Ping('www.wikipedia.org', timeout=2000).do()
except socket.error, e:
print "Ping Error:", e
Bản thân mã nguồn rất dễ đọc, xem việc triển khai verbose_ping
và Ping.do
lấy cảm hứng.
ping
sử dụng time.clock
không mang lại bất cứ điều gì hữu ích trên hộp Linux của tôi. timeit.default_timer
(nó bằng time.time
trên máy của tôi) hoạt động. time.clock
-> timeit.default_timer
gist.github.com/255009
Tùy thuộc vào những gì bạn muốn đạt được, bạn có thể dễ dàng nhất gọi lệnh ping hệ thống ..
Sử dụng mô-đun quy trình con là cách tốt nhất để làm điều này, mặc dù bạn phải nhớ lệnh ping khác nhau trên các hệ điều hành khác nhau!
import subprocess
host = "www.google.com"
ping = subprocess.Popen(
["ping", "-c", "4", host],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = ping.communicate()
print out
Bạn không cần phải lo lắng về các ký tự thoát shell. Ví dụ..
host = "google.com; `echo test`
..sẽ không thực hiện lệnh echo.
Bây giờ, để thực sự nhận được kết quả ping, bạn có thể phân tích cú pháp out
biến. Ví dụ đầu ra:
round-trip min/avg/max/stddev = 248.139/249.474/250.530/0.896 ms
Ví dụ regex:
import re
matcher = re.compile("round-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
print matcher.search(out).groups()
# ('248.139', '249.474', '250.530', '0.896')
Một lần nữa, hãy nhớ đầu ra sẽ khác nhau tùy thuộc vào hệ điều hành (và thậm chí cả phiên bản của ping
). Điều này không phải là lý tưởng, nhưng nó sẽ hoạt động tốt trong nhiều tình huống (nơi bạn biết các máy mà tập lệnh sẽ chạy)
out
hàm chứa được mã hóa \ n có vẻ như cản trở việc đối sánh:matcher = re.compile("\nround-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
matcher.search
thay thế mà không cần thay đổi regex .
Bạn có thể tìm thấy bài thuyết trình của Noah Gift Tạo các công cụ dòng lệnh nhanh nhẹn với Python . Trong đó, ông kết hợp quy trình con, hàng đợi và phân luồng để phát triển giải pháp có khả năng ping các máy chủ đồng thời và tăng tốc quá trình. Dưới đây là phiên bản cơ bản trước khi anh ấy thêm phân tích cú pháp dòng lệnh và một số tính năng khác. Có thể tìm thấy mã của phiên bản này và các phiên bản khác tại đây
#!/usr/bin/env python2.5
from threading import Thread
import subprocess
from Queue import Queue
num_threads = 4
queue = Queue()
ips = ["10.0.1.1", "10.0.1.3", "10.0.1.11", "10.0.1.51"]
#wraps system ping command
def pinger(i, q):
"""Pings subnet"""
while True:
ip = q.get()
print "Thread %s: Pinging %s" % (i, ip)
ret = subprocess.call("ping -c 1 %s" % ip,
shell=True,
stdout=open('/dev/null', 'w'),
stderr=subprocess.STDOUT)
if ret == 0:
print "%s: is alive" % ip
else:
print "%s: did not respond" % ip
q.task_done()
#Spawn thread pool
for i in range(num_threads):
worker = Thread(target=pinger, args=(i, queue))
worker.setDaemon(True)
worker.start()
#Place work in queue
for ip in ips:
queue.put(ip)
#Wait until worker threads are done to exit
queue.join()
Ông cũng là tác giả của: Python for Unix và Linux System Administration
http://ecx.images-amazon.com/images/I/515qmR%2B4sjL._SL500_AA240_.jpg
Thật khó để nói câu hỏi của bạn là gì, nhưng có một số lựa chọn thay thế.
Nếu bạn muốn thực hiện một yêu cầu theo nghĩa đen bằng giao thức ping ICMP, bạn có thể lấy thư viện ICMP và thực hiện yêu cầu ping trực tiếp. Google "Python ICMP" để tìm những thứ như icmplib này . Bạn cũng có thể muốn nhìn vào scpy .
Điều này sẽ nhanh hơn nhiều so với sử dụng os.system("ping " + ip )
.
Nếu bạn muốn "ping" một hộp nói chung để xem nó có lên hay không, bạn có thể sử dụng giao thức echo trên cổng 7.
Đối với echo, bạn sử dụng thư viện socket để mở địa chỉ IP và cổng 7. Bạn viết một cái gì đó trên cổng đó, gửi một ký tự xuống dòng ( "\r\n"
) và sau đó đọc câu trả lời.
Nếu bạn muốn "ping" một trang web để xem trang đó có đang chạy hay không, bạn phải sử dụng giao thức http trên cổng 80.
Để kiểm tra hoặc kiểm tra chính xác máy chủ web, bạn sử dụng urllib2 để mở một URL cụ thể. ( /index.html
luôn luôn phổ biến) và đọc phản hồi.
Vẫn còn nhiều ý nghĩa tiềm năng hơn của "ping" bao gồm "traceroute" và "ngón tay".
Tôi đã làm điều gì đó tương tự theo cách này, như một nguồn cảm hứng:
import urllib
import threading
import time
def pinger_urllib(host):
"""
helper function timing the retrival of index.html
TODO: should there be a 1MB bogus file?
"""
t1 = time.time()
urllib.urlopen(host + '/index.html').read()
return (time.time() - t1) * 1000.0
def task(m):
"""
the actual task
"""
delay = float(pinger_urllib(m))
print '%-30s %5.0f [ms]' % (m, delay)
# parallelization
tasks = []
URLs = ['google.com', 'wikipedia.org']
for m in URLs:
t = threading.Thread(target=task, args=(m,))
t.start()
tasks.append(t)
# synchronization point
for t in tasks:
t.join()
subprocess
/index.html
; trong bất kỳ trang web nào thực sự có một tài liệu được gọi index.html
, nó sẽ ở ngay đó, trong thư mục gốc của máy chủ. Thay vào đó bạn muốn thêm vào trước http://
hoặc https://
để lưu trữ
Đây là một đoạn ngắn sử dụng subprocess
. Các check_call
phương pháp hoặc là trả về 0 cho sự thành công, hoặc đặt ra một ngoại lệ. Bằng cách này, tôi không phải phân tích cú pháp đầu ra của ping. Tôi đang sử dụng shlex
để tách các đối số dòng lệnh.
import subprocess
import shlex
command_line = "ping -c 1 www.google.comsldjkflksj"
args = shlex.split(command_line)
try:
subprocess.check_call(args,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print "Website is there."
except subprocess.CalledProcessError:
print "Couldn't get a ping."
-c
là -n
ở đó, và logic về mã trở lại là khác nhau)
đọc tên tệp, tệp chứa một url trên mỗi dòng, như sau:
http://www.poolsaboveground.com/apache/hadoop/core/
http://mirrors.sonic.net/apache/hadoop/core/
sử dụng lệnh:
python url.py urls.txt
nhận được kết quả:
Round Trip Time: 253 ms - mirrors.sonic.net
Round Trip Time: 245 ms - www.globalish.com
Round Trip Time: 327 ms - www.poolsaboveground.com
mã nguồn (url.py):
import re
import sys
import urlparse
from subprocess import Popen, PIPE
from threading import Thread
class Pinger(object):
def __init__(self, hosts):
for host in hosts:
hostname = urlparse.urlparse(host).hostname
if hostname:
pa = PingAgent(hostname)
pa.start()
else:
continue
class PingAgent(Thread):
def __init__(self, host):
Thread.__init__(self)
self.host = host
def run(self):
p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
m = re.search('Average = (.*)ms', p.stdout.read())
if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
else: print 'Error: Invalid Response -', self.host
if __name__ == '__main__':
with open(sys.argv[1]) as f:
content = f.readlines()
Pinger(content)
import subprocess as s
ip=raw_input("Enter the IP/Domain name:")
if(s.call(["ping",ip])==0):
print "your IP is alive"
else:
print "Check ur IP"
Nếu bạn muốn một thứ gì đó thực sự bằng Python mà bạn có thể chơi, hãy xem Scapy:
from scapy.all import *
request = IP(dst="www.google.com")/ICMP()
answer = sr1(request)
Theo ý kiến của tôi, điều đó tốt hơn nhiều (và hoàn toàn đa nền tảng), so với một số lệnh gọi quy trình con sôi nổi. Ngoài ra, bạn có thể có nhiều thông tin về câu trả lời (ID trình tự .....) như bạn muốn, vì bạn có chính gói tin.
Bạn có thể tìm thấy phiên bản cập nhật của tập lệnh được đề cập hoạt động trên cả Windows và Linux tại đây
sử dụng lệnh ping hệ thống để ping danh sách các máy chủ:
import re
from subprocess import Popen, PIPE
from threading import Thread
class Pinger(object):
def __init__(self, hosts):
for host in hosts:
pa = PingAgent(host)
pa.start()
class PingAgent(Thread):
def __init__(self, host):
Thread.__init__(self)
self.host = host
def run(self):
p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
m = re.search('Average = (.*)ms', p.stdout.read())
if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
else: print 'Error: Invalid Response -', self.host
if __name__ == '__main__':
hosts = [
'www.pylot.org',
'www.goldb.org',
'www.google.com',
'www.yahoo.com',
'www.techcrunch.com',
'www.this_one_wont_work.com'
]
Pinger(hosts)
p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
Nên p = Popen(['ping','-n','1','self.host'], stdout=PIPE)
sử dụng lệnh ping của quy trình con để giải mã ping vì phản hồi là nhị phân:
import subprocess
ping_response = subprocess.Popen(["ping", "-a", "google.com"], stdout=subprocess.PIPE).stdout.read()
result = ping_response.decode('utf-8')
print(result)
bạn có thể thử socket để lấy ip của trang web và sử dụng scrapy để thực hiện ping icmp tới ip.
import gevent
from gevent import monkey
# monkey.patch_all() should be executed before any library that will
# standard library
monkey.patch_all()
import socket
from scapy.all import IP, ICMP, sr1
def ping_site(fqdn):
ip = socket.gethostbyaddr(fqdn)[-1][0]
print(fqdn, ip, '\n')
icmp = IP(dst=ip)/ICMP()
resp = sr1(icmp, timeout=10)
if resp:
return (fqdn, False)
else:
return (fqdn, True)
sites = ['www.google.com', 'www.baidu.com', 'www.bing.com']
jobs = [gevent.spawn(ping_site, fqdn) for fqdn in sites]
gevent.joinall(jobs)
print([job.value for job in jobs])
Tôi phát triển một thư viện mà tôi nghĩ có thể giúp bạn. Nó được gọi là icmplib (không liên quan đến bất kỳ mã nào khác cùng tên có thể tìm thấy trên Internet) và là một triển khai thuần túy của giao thức ICMP bằng Python.
Nó hoàn toàn hướng đối tượng và có các chức năng đơn giản như ping, multiping và traceroute cổ điển, cũng như các lớp và ổ cắm cấp thấp cho những ai muốn phát triển ứng dụng dựa trên giao thức ICMP.
Dưới đây là một số điểm nổi bật khác:
Để cài đặt nó (yêu cầu Python 3.6+):
pip3 install icmplib
Đây là một ví dụ đơn giản về hàm ping:
host = ping('1.1.1.1', count=4, interval=1, timeout=2, privileged=True)
if host.is_alive:
print(f'{host.address} is alive! avg_rtt={host.avg_rtt} ms')
else:
print(f'{host.address} is dead')
Đặt tham số "đặc quyền" thành Sai nếu bạn muốn sử dụng thư viện mà không có đặc quyền gốc.
Bạn có thể tìm thấy tài liệu đầy đủ trên trang dự án: https://github.com/ValentinBELYN/icmplib
Hy vọng bạn sẽ thấy thư viện này hữu ích.
Sử dụng điều này, nó đã được thử nghiệm trên python 2.7 và hoạt động tốt, nó trả về thời gian ping tính bằng mili giây nếu thành công và trả về False khi thất bại.
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
command
là một chuỗi bao gồm tất cả các đối số thay vì một danh sách để kích hoạt command not found
chuỗi đầy đủ trên Linux.