Python으로 웹 사이트 또는 IP 주소를 어떻게 ping합니까?
Python으로 웹 사이트 또는 IP 주소를 어떻게 ping합니까?
답변:
Matthew Dixon Cowles 와 Jens Diemer의 순수 Python 핑 을 참조하십시오 . 또한 Python은 Linux에서 ICMP (예 : ping) 소켓을 생성하려면 루트가 필요합니다.
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
소스 코드 자체는 읽기의 구현을 쉽게 볼 수 verbose_ping
와의를 Ping.do
영감을.
ping
time.clock
내 Linux 상자에서 유용한 정보를 얻지 못하는 사용 . timeit.default_timer
( time.time
내 컴퓨터와 동일 ) 작동합니다. time.clock
-> timeit.default_timer
gist.github.com/255009
달성하려는 항목에 따라 시스템 ping 명령을 가장 쉽게 호출 할 수 있습니다.
하위 프로세스 모듈을 사용하는 것이이 작업을 수행하는 가장 좋은 방법이지만 ping 명령은 운영 체제마다 다르다는 점을 기억해야합니다!
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
쉘 이스케이프 문자에 대해 걱정할 필요가 없습니다. 예를 들어 ..
host = "google.com; `echo test`
.. echo 명령을 실행 하지 않습니다 .
이제 실제로 ping 결과를 얻으려면 out
변수를 구문 분석 할 수 있습니다. 출력 예 :
round-trip min/avg/max/stddev = 248.139/249.474/250.530/0.896 ms
정규식 예 :
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')
다시 말하지만, 출력은 운영 체제 (및 버전 ping
) 에 따라 달라질 수 있습니다 . 이것은 이상적이지는 않지만 많은 상황에서 잘 작동합니다 (스크립트가 실행될 컴퓨터를 알고있는 경우).
out
를 방해하는 것처럼 보이는 인코딩 된 \ n 포함 으로 정규식 일치 표현식을 조정해야 함을 발견했습니다 .matcher = re.compile("\nround-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
matcher.search
하십시오 .
Noah Gift의 프레젠테이션 Creating Agile Commandline Tools With Python을 찾을 수 있습니다 . 여기에서 그는 하위 프로세스, 큐 및 스레딩을 결합하여 호스트를 동시에 ping하고 프로세스 속도를 높일 수있는 솔루션을 개발합니다. 다음은 명령 줄 구문 분석 및 기타 기능을 추가하기 전의 기본 버전입니다. 이 버전 및 기타 버전에 대한 코드는 여기 에서 찾을 수 있습니다.
#!/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()
그는 또한 다음의 저자이기도합니다 : Python for Unix and Linux System Administration
http://ecx.images-amazon.com/images/I/515qmR%2B4sjL._SL500_AA240_.jpg
질문이 무엇인지 말하기는 어렵지만 몇 가지 대안이 있습니다.
말 그대로 ICMP ping 프로토콜을 사용하여 요청을 실행하려는 경우 ICMP 라이브러리를 가져 와서 직접 ping 요청을 실행할 수 있습니다. Google "Python ICMP"는이 icmplib 같은 것을 찾습니다 . scapy 도 살펴볼 수 있습니다 .
이것은를 사용하는 것보다 훨씬 빠릅니다 os.system("ping " + ip )
.
일반적으로 상자를 "핑"하여 작동하는지 확인하려는 경우 포트 7에서 에코 프로토콜을 사용할 수 있습니다.
echo의 경우 소켓 라이브러리를 사용하여 IP 주소와 포트 7을 엽니 다. 해당 포트에 무언가를 쓰고 캐리지 리턴 ( "\r\n"
)을 보낸 다음 응답을 읽습니다.
사이트가 실행 중인지 확인하기 위해 웹 사이트를 "ping"하려면 포트 80에서 http 프로토콜을 사용해야합니다.
웹 서버를 위해 또는 적절하게 확인하려면 urllib2 를 사용하여 특정 URL을 엽니 다. ( /index.html
항상 인기가 있음) 응답을 읽으십시오.
"traceroute"및 "finger"를 포함하여 "ping"의 잠재적 인 의미가 더 많이 있습니다.
영감으로 비슷한 일을했습니다.
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
. 실제로라는 문서가있는 모든 사이트에서 index.html
바로 서버 루트에 있습니다. 대신 당신은 줄 앞에 추가 http://
또는 https://
호스트
다음은 subprocess
. 이 check_call
메서드는 성공하면 0을 반환하거나 예외를 발생시킵니다. 이렇게하면 ping 출력을 구문 분석 할 필요가 없습니다. shlex
명령 줄 인수를 분할하는 데 사용 하고 있습니다.
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
이다 -n
가, 및 반환 코드에 대한 논리가 다릅니다)
파일 이름을 읽으면 파일에는 다음과 같이 한 줄에 하나의 URL이 포함됩니다.
http://www.poolsaboveground.com/apache/hadoop/core/
http://mirrors.sonic.net/apache/hadoop/core/
사용 명령 :
python url.py urls.txt
결과를 얻으십시오 :
Round Trip Time: 253 ms - mirrors.sonic.net
Round Trip Time: 245 ms - www.globalish.com
Round Trip Time: 327 ms - www.poolsaboveground.com
소스 코드 (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)
여기에서 Windows와 Linux 모두에서 작동하는 언급 된 스크립트의 업데이트 된 버전을 찾을 수 있습니다.
나는 당신을 도울 수 있다고 생각하는 도서관을 개발합니다. icmplib (인터넷에서 찾을 수있는 동일한 이름의 다른 코드와 관련이 없음)라고하며 Python에서 ICMP 프로토콜을 순수하게 구현 한 것입니다.
완전히 객체 지향적이며 ICMP 프로토콜을 기반으로 응용 프로그램을 개발하려는 사용자를위한 저수준 클래스 및 소켓뿐만 아니라 클래식 핑, 멀티 핑 및 추적 경로와 같은 간단한 기능이 있습니다.
다른 주요 사항은 다음과 같습니다.
설치하려면 (Python 3.6 이상 필요) :
pip3 install icmplib
다음은 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')
루트 권한없이 라이브러리를 사용하려면 "privileged"매개 변수를 False로 설정하십시오.
프로젝트 페이지에서 전체 문서를 찾을 수 있습니다 : https://github.com/ValentinBELYN/icmplib
이 라이브러리가 유용하기를 바랍니다.
시스템 ping 명령을 사용하여 호스트 목록을 ping합니다.
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)
되어야합니다 p = Popen(['ping','-n','1','self.host'], stdout=PIPE)
응답이 바이너리이기 때문에 하위 프로세스 ping 명령을 사용하여 ping 디코딩합니다.
import subprocess
ping_response = subprocess.Popen(["ping", "-a", "google.com"], stdout=subprocess.PIPE).stdout.read()
result = ping_response.decode('utf-8')
print(result)
당신은 사이트의 IP를 얻기 위해 소켓을 시도하고 ip에 대한 icmp ping을 실행하기 위해 scrapy를 사용할 수 있습니다.
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])
이것을 사용하면 python 2.7에서 테스트되었으며 성공하면 핑 시간을 밀리 초 단위로 반환하고 실패하면 False를 반환합니다.
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
목록 대신 모든 인수를 포함하는 문자열이므로 command not found
Linux에서 전체 문자열을 트리거하므로 실패합니다 .