HOWTO · Python

Python ping 伺服器

本教程演示瞭如何在 Python 中 ping 伺服器。

本頁內容

若要從 Python 檢查主機是否會回應 ICMP echo request,可以透過 subprocess.call() 或 os.system() 呼叫作業系統的 ping 命令,也可以使用 ping3.ping() 函式。收到回應可表示主機可連線,並提供往返時間,但不能證明特定應用程式或服務可用。結果也會受到作業系統、已安裝工具、防火牆規則及網路政策影響。

在 Python 中使用 subprocess.call() 對伺服器執行 ping

subprocess.call() 會執行程式並傳回該程序的結束狀態。將命令以清單形式傳入,可避免根據主機字串組合 shell 命令。封包計數選項會因平台而異:常見的 ping 實作在 Windows 使用 -n,在類 Unix 系統則使用 -c。

import platform
import shutil
import subprocess


def ping_host(host):
    ping = shutil.which("ping")
    if ping is None:
        return None  # The ping program is not installed or on PATH.

    count_option = "-n" if platform.system() == "Windows" else "-c"
    try:
        status = subprocess.call(
            [ping, count_option, "1", host],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            timeout=5,
        )
    except (OSError, subprocess.TimeoutExpired):
        return None
    return status == 0


result = ping_host("example.com")
if result is None:
    print("ping is unavailable")
else:
    print("host responded" if result else "no successful response")

以下是提供的執行環境中觀察到的輸出。下方保留的輸出區塊及其中的標籤維持原樣;若標籤是英文,顯示內容仍是英文。

ping is unavailable

如輸出所示,提供的執行環境沒有 ping 可用。在已安裝此工具的環境中,這個範例也需要網路連線。它會隱藏命令輸出;程序以狀態碼 0 結束時傳回 True,以非零狀態碼結束時傳回 False,若程式不存在或逾時則傳回 None。非零狀態碼無法指出原因是封包遺失、遭到篩選、名稱解析失敗,還是其他系統特有的狀況。請依你的環境調整主機名稱和封包計數選項。

在 Python 中使用 os.system() 對伺服器執行 ping

os.system() 會透過 shell 執行命令字串,並傳回依平台編碼的狀態值。它的彈性不如 subprocess.call();將未受信任的主機文字串接到命令中,可能造成 shell injection。對於可能來自使用者的值,建議使用 subprocess.call() 傳入引數清單。如果使用 os.system(),請只搭配固定且可信任的主機,並依目前平台選擇封包計數選項:

import os
import platform
import shutil

host = "example.com"  # Keep this fixed or validate it before use.
ping = shutil.which("ping")
if ping is None:
    print("ping is unavailable")
else:
    count_option = "-n" if platform.system() == "Windows" else "-c"
    status = os.system(f'"{ping}" {count_option} 1 {host} > "{os.devnull}" 2>&1')
    print("host responded" if status == 0 else "no successful response")

以下是提供的執行環境中觀察到的輸出。下方保留的輸出區塊及其中的標籤維持原樣;若標籤是英文,顯示內容仍是英文。

ping is unavailable

如輸出所示,提供的執行環境沒有 ping 可用。若環境中有此工具,範例結果會取決於本機 shell、ping 實作及網路狀況。為可執行檔路徑加上引號可處理路徑中含有空格的情況,但 shell 命令字串仍須謹慎處理;不要將任意使用者輸入代入 host。此狀態代表 shell 命令的結果,不能說明像網頁伺服器這類服務是否正在接受連線。

在 Python 中使用 ping3.ping() 對伺服器執行 ping

第三種方式是使用 ping3.ping() 函式。它會傳送 ICMP echo request,而不呼叫系統的 ping 命令。請在執行腳本所使用的 Python 環境中,透過 python -m pip install ping3 安裝 ping3 套件。依作業系統和使用者權限而定,傳送 ICMP 封包可能還需要額外權限。

try:
    from ping3 import ping
except ImportError:
    print("Install ping3 with: python -m pip install ping3")
else:
    host = "example.com"
    response = ping(host)
    if response is None or response is False:
        print("no response reported")
    else:
        print(f"round-trip time: {response} seconds")

以下是提供的執行環境中觀察到的輸出。下方保留的輸出區塊及其中的標籤維持原樣;若標籤是英文,顯示內容仍是英文。

Install ping3 with: python -m pip install ping3

如輸出所示,提供的執行環境沒有安裝 ping3。安裝後,此範例仍需要適當的 ICMP 權限和網路連線。數值回應代表以秒為單位的往返時間。若沒有收到回應,請依已安裝的函式庫行為和執行環境判讀;不要假設它能區分主機無法連線、封包遭到篩選或封包遺失。

若你想安全地傳入引數並使用系統現有的 ping 工具,請選擇 subprocess.call()。os.system() 是較精簡的 shell 方式,適合執行固定且可信任的命令。ping3.ping() 可直接在 Python 中呼叫並取得時間資訊,但需要額外安裝套件,也須考量權限。這三種方式都只測試 ICMP 可達性;若要確認特定服務是否正常運作,請改用應用程式層級的檢查。