web-dev-qa-db-ja.com

Pythonでpingサーバー

Pythonでは、ICMPを介してサーバーにpingを実行し、サーバーが応答した場合はTRUEを返し、応答がない場合はFALSEを返す方法はありますか?

135
Kudu

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はゼロ以外の値を返すのでこれは機能します。 (実際には戻り値はネットワークエラーによって異なります。) ' - t'オプションを使ってpingタイムアウト(秒単位)を変更することもできます。これはコンソールにテキストを出力することに注意してください。

138
10flow

この関数はどのOS(Unix、Linux、macOS、Windows)でも動作します
Python 2とPython 3

編集:
による @ radatoos.systemsubprocess.callに置き換えられました。
By @ Boris ドキュメントでは、Python 3.5+を使用している場合は subprocess.run() の使用を推奨しています。

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

Windowsの@ikraseによると、Destination Host Unreachableエラーが発生した場合でも、この関数はTrueを返します。

説明

コマンドは、WindowsとUnixのようなシステムの両方でpingです。
オプション-n(Windows)または-c(Unix)は、この例では1に設定されていたパケット数を制御します。

platform.system() はプラットフォーム名を返します。例macOSでは'Darwin'
subprocess.call() システムコールを実行します。例subprocess.call(['ls','-l'])

79
ePi272314

これを行うことができる pyping というモジュールがあります。それはピップと取付けることができます

pip install pyping

使い方はとても簡単ですが、このモジュールを使うときは、フードの下で生のパケットを作成しているため、rootアクセスが必要です。

import pyping

r = pyping.ping('google.com')

if r.ret_code == 0:
    print("Success")
else:
    print("Failed with {}".format(r.ret_code))
31
Stephen Cochran
import subprocess
ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "192.168.0.1"], stdout=subprocess.PIPE).stdout.read()
27
mluebke

私は自分の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"))
12
Rudolf
#!/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()
6
Udayendu

見回した後、私は自分自身のpingモジュールを書くことにしました。それは多数のアドレスを監視するように設計されていて、非同期で、多くのシステムリソースを使用しません。あなたはここでそれを見つけることができます: https://github.com/romana/multi-ping/ それはApacheのライセンスを受けているので、あなたはあなたが適当と思うあらゆる方法であなたのプロジェクトでそれを使うことができます。

自分で実装する主な理由は、他のアプローチの制限です。

  • ここで述べられている解決策の多くはコマンドラインユーティリティへのexecを必要とします。大量のIPアドレスを監視する必要がある場合、これは非常に非効率的でリソースを浪費します。
  • 他の人はいくつかの古いpythonのpingモジュールに言及しています。私はそれらを見て、結局のところ、それらはすべて何らかの問題(パケットIDを正しく設定していないなど)を持っていて、多数のアドレスのpingを処理しませんでした。
5
Juergen Brendel

必ずPypingがインストールされているかインストールしてくださいpip install pyping

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

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

Multi-pingpip 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)

単一のサンプルが必要な場合は、2番目のパラメータ "10"は無視できます。

お役に立てば幸いです!

3
Geraldo Neto

私はこれでこれを解決します。

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が正しいかどうかを知る方法です。サルドス

3
user3620655
#!/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 !")
2
Udayendu

プログラムによる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接続を確立し、それを直ちにドロップして経過時間を測定します。この特定の実装は、閉じたポートを処理しないという点で少し制限されていますが、ご自身のサーバーの場合はかなりうまく機能します。

2
kravietz

私は結局同様のシナリオに関してこの質問を見つけることになった。私は入力を試みましたが、Naveenによって与えられた例はPython 2.7の下でWindowsで私のために働きませんでした。

私のために働いた例は次のとおりです。

import pyping

response = pyping.send('Your IP')

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

この記事の回答からのアイデアを使用し、私の簡潔化は新しい推奨サブプロセスモジュールとpython3のみを使用しています。

import subprocess
import platform

operating_sys = platform.system()
nas = '192.168.0.10'

def ping(ip):

    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)
2
ArnoVR

このスクリプトは、Windows上で動作し、他のOS上で動作するはずです。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
1
Matthew

私はping3が好きでした https://github.com/kyan001/ping とてもシンプルで便利!

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

私は同様の要件を持っていたので、以下のように実装しました。 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()は例外を発生させます。追加の検証は、出力行「Packets:Sent = 2、Received = 2、Lost = 0(損失0%)」から情報を抽出することで実行できます。

1
Luminos

これはPythonのsubprocessモジュールと基盤となるOSによって提供されるping CLIツールを使った解決策です。 WindowsとLinuxでテスト済み。ネットワークタイムアウトの設定をサポートします。 root権限は必要ありません(少なくとも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
1
Epoc

私のバージョンのping機能:

  • Python 3.5以降、WindowsおよびLinux上で動作します(Mac上では動作しますが、テストすることはできません)。
  • Windowsでは、pingコマンドが「Destination Host Unreachable」で失敗した場合はFalseを返します。
  • また、ポップアップウィンドウとしてもコマンドラインでも、出力を表示しません。
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

あなたがそうするようにそれを自由に使ってください。

これはpython 2.7でテストされており、成功すればミリ秒単位でping時間を返し、失敗すれば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
0
MSS

サブプロセスモジュールのTimeoutExpired例外を使用してpingタイムアウトをキャッチすることができます(他の回答では利用されていないものです)。この解決策はLinuxでのみ機能することに注意してください。

def ping(Host, timeout=3):
    """
    Send a ping (ICMP) request to a remote Host.

    The command is set to ``ping -c 1 -W 1 <Host>``, which sends exactly 1 ping
    packet, and waits for 1 second before terminating.

    Args:
        Host (str): Hostname or IP address.
        timeout (int): Ping command timeout (in seconds).

    Returns:
        bool: The ping response. ``True`` if the Host responds to a ping request 
            within the specified timeout period. ``False`` otherwise.

    Note:
        A Host may not respond to a ping (ICMP) request even if the Host name is 
        valid because of firewall rules.
    """
    # Building the command. Ex: "ping -c 1 google.com"
    command = ['ping', Host, '-W', '1', '-c', '1']

    try:
        subprocess.run(command, timeout=timeout, check=True)
        return True
    except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
        #log.warning("Failed to ping Host: %s with timeout: %d", Host, timeout)
        return False
0
teraflik

十分にシンプルに思えますが、私にフィット感を与えました。私は「icmpオープンソケット操作は許可されていません」を受け取り続けた、さもなければ解決策はサーバーがオフラインであったならハングアップするでしょう。しかし、サーバーが稼働していて、そのサーバー上でWebサーバーを実行しているということを知りたい場合は、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
0
user2099484

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
Aimondy

私は他の答えから借りています。照会を単純化し最小化しようとします。

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
misantroop

多くの答えが見逃していることの1つは、(少なくともWindowsでは)pingコマンドが「Destination Host unreachable」という応答を受け取ると0(成功を示す)を返すことです。

これはb'TTL='が応答に含まれているかどうかをチェックする私のコードです。これはpingがホストに到達したときにのみ存在するためです。注:このコードの大部分は、ここにある他の答えに基づいています。

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
Brent Robertson