HOWTO · Python

파이썬 핑

이 튜토리얼은 Python에서 서버를 ping하는 방법을 보여줍니다.

이 페이지의 내용

Python에서 호스트가 ICMP 에코 요청에 응답하는지 확인하려면 운영 체제의 ping 명령을 subprocess.call() 또는 os.system()으로 실행하거나 ping3.ping() 함수를 사용할 수 있습니다. 응답이 있으면 호스트에 연결할 수 있는지와 왕복 시간을 확인할 수 있지만, 특정 애플리케이션이나 서비스가 사용 가능한지는 증명하지 못합니다. 결과는 운영 체제, 설치된 도구, 방화벽 규칙, 네트워크 정책에도 영향을 받습니다.

Python에서 subprocess.call()로 서버에 핑 보내기

subprocess.call()은 프로그램을 실행하고 프로세스의 종료 상태를 반환합니다. 명령을 리스트로 전달하면 호스트 문자열로 셸 명령을 만들 필요가 없습니다. 패킷 수 옵션은 플랫폼마다 다릅니다. 일반적인 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이 없습니다. ping이 설치된 환경에서 이 예제를 실행하려면 네트워크에도 접근할 수 있어야 합니다. 이 예제는 명령 출력을 숨기며, 프로세스 종료 상태가 0이면 True, 0이 아니면 False를 반환하고, 프로그램을 사용할 수 없거나 시간이 초과되면 None을 반환합니다. 종료 상태가 0이 아닌 것만으로는 원인이 패킷 손실, 필터링, 이름 확인 실패 또는 시스템별 다른 조건 중 무엇인지 알 수 없습니다. 환경에 맞게 호스트와 패킷 수 옵션을 바꾸세요.

Python에서 os.system()으로 서버에 핑 보내기

os.system()은 셸을 통해 명령 문자열을 실행하고 플랫폼별로 인코딩된 상태를 반환합니다. subprocess.call()보다 유연성이 떨어지며, 신뢰할 수 없는 호스트 문자열을 명령에 이어 붙이면 셸 인젝션이 발생할 수 있습니다. 사용자 입력이 들어갈 수 있는 값에는 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이 없습니다. ping을 사용할 수 있는 경우에도 이 예제는 로컬 셸, ping 구현, 네트워크에 따라 달라집니다. 실행 파일 경로를 따옴표로 감싸면 경로에 공백이 있어도 처리할 수 있지만, 셸 명령 문자열은 여전히 신중하게 다뤄야 합니다. host에 임의의 사용자 입력을 넣지 마세요. 반환된 상태는 셸 명령의 결과를 나타낼 뿐, 웹 서버 같은 서비스가 연결을 받고 있는지를 알려 주지는 않습니다.

Python에서 ping3.ping()으로 서버에 핑 보내기

세 번째 방법은 시스템의 ping 명령을 실행하지 않고 ICMP 에코 요청을 보내는 ping3.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()은 고정된 신뢰할 수 있는 명령에 사용할 수 있는 더 짧은 셸 기반 방법입니다. ping3.ping()은 Python 안에서 호출하고 시간 정보를 받을 수 있지만, 패키지 설치와 권한을 고려해야 합니다. 세 방법 모두 ICMP 연결 가능성만 확인합니다. 특정 서비스가 작동하는지 알아보려면 애플리케이션 수준의 검사를 사용하세요.