
Sping은 Linux·macOS·Windows에서 여러 네트워크 대상의 연결 상태를 실시간으로 살피는 Rust 기반 진단 도구다. 1.8.0에서는 목적지에 도달할 수 없다는 응답을 시간 초과와 구분하고, --ip로 호스트의 주소와 경로를 확인하는 기능 등을 추가했다.
최신 릴리스 · crates.io · 전체 릴리스 · CI · 라이선스
Sping은 패킷 수치뿐 아니라 네트워크 맥락도 보여주는 터미널용 연결 모니터다. 프로젝트는 현재 기능이 작동하고 실제 사용 중이며 JSON 계약은 고정됐다고 설명한다. Linux·macOS·Windows와 x86_64·aarch64·armv7(라즈베리 파이)을 지원한다. 화면 예시
한 화면에서 확인할 수 있는 정보는 세 가지다. 대상이 응답하는지(RTT, TTL, 지터, 손실률, 품질 점수, 추세), 선택한 인터페이스로 네트워크에 연결되는지(게이트웨이와 WAN 도달 여부), 문제가 어떤 유형인지(연관 진단)다.
단일 대상 화면에는 대상 주소와 인터페이스, 지연 시간의 현재값·평균·최솟값·최댓값, 지터와 DNS 시간, 손실률, TTL과 추정 홉 수, 네트워크 맥락, 품질 점수가 표시된다. 여러 대상을 지정하면 실시간 표에 대상별 RTT·평균·손실률·품질·추세·TTL·홉 수가 나온다.
1.8.0 변경 사항
라우터나 호스트가 목적지 도달 불가 응답을 보내면 이제 시간 초과와 구분한다. 클래식 화면은 From 192.0.2.1: seq=3 Destination Host Unreachable, 이벤트 화면은 192.0.2.1 reports host unreachable, JSON은 icmp_unreachable로 표시한다. Linux와 Windows, macOS의 IPv4에서 지원한다.
sping --ip는 모든 인터페이스의 IPv4·IPv6 주소와 접두사, 주소 유형, IPv6 상태, 각 주소 계열에서 사용하는 출발지 주소, 기본 게이트웨이를 보여준다. 패킷을 보내지 않으며, --external을 추가하면 STUN 서버가 관측하는 주소도 조회한다. 자세한 내용은 호스트 주소 안내를 참고하면 된다.
대상이 계속 응답하지 않는 동안 --diagnose는 진단을 마친 뒤 5분이 지나면 같은 검사를 다시 한다. --icmp는 현재 동작을 바꾸지 않지만, 2.0에서 sping target의 동작이 바뀌더라도 스크립트가 기존 ICMP 검사를 계속 사용하도록 지정하는 옵션이다. 자세한 내용은 로드맵에 있다.
진단 기능도 수정했다. Windows에서는 다른 주소 계열의 주소가 도달 불가 응답을 받으면 Linux와 마찬가지로 해당 계열도 실패로 처리한다. Linux에서는 traceroute 중 리디렉션이 발생해도 해당 라운드가 recv failed로 끝나지 않는다. 버전별 변경 사항은 CHANGELOG.md에서 확인할 수 있다.
설치와 기본 사용
설치 방법과 지원 플랫폼은 다음과 같다.
| 방법 | 명령 또는 제공 파일 | 지원 조건 | 매뉴얼·셸 자동완성 |
|---|---|---|---|
| Homebrew | brew install LambdaBytes/tap/sping | macOS | 제공 |
| Scoop | 버킷을 추가한 뒤 scoop install lambdabytes/sping | Windows x86_64 | 미제공 |
| crates.io | cargo install sping | Linux·macOS·Windows, Rust 1.88 이상 | 미제공 |
| 사전 빌드 바이너리 | 릴리스 페이지에서 다운로드 | Linux·macOS·Windows | 미제공 |
| Debian·Ubuntu 패키지 | 릴리스 페이지의 .deb | Debian 12, Ubuntu 22.04, Raspberry Pi OS (Bookworm) 이상 | 제공 |
| 소스 빌드 | cargo build --release | Linux·macOS·Windows, Rust 1.88 이상 | 미제공 |
Homebrew는 v1.6.0부터 소스에서 빌드해 바이너리와 매뉴얼 페이지, 셸 자동완성 파일을 설치한다.
Scoop은 v1.6.0부터 릴리스의 Windows 바이너리를 설치한다. 설치되는 파일은 해당 릴리스의 SHA256SUMS에 기재된 바이너리다.
scoop bucket add lambdabytes https://github.com/LambdaBytes/scoop-bucket
scoop install lambdabytes/sping
sudo 없이 scoop update sping을 실행하면 새 릴리스로 업데이트한다.
crates.io 설치에는 Rust 1.88 이상이 필요하며 바이너리만 설치한다. 매뉴얼 페이지와 셸 자동완성은 포함되지 않는다.
cargo install sping
사전 빌드 파일은 릴리스 페이지에서 제공한다. Linux 바이너리와 패키지는 glibc 2.34 이상이 필요하다. 즉 Debian 12, Ubuntu 22.04, Raspberry Pi OS (Bookworm) 이상에서 사용할 수 있다. -musl 바이너리는 정적 바이너리여서 같은 아키텍처의 모든 Linux에서 실행되며 Alpine과 이전 시스템도 포함한다.
| 플랫폼 | 릴리스 파일 |
|---|---|
| Linux x86_64 | sping-vX.Y.Z-linux-x86_64 |
| Linux aarch64 | sping-vX.Y.Z-linux-aarch64 |
| Linux x86_64, 정적 | sping-vX.Y.Z-linux-x86_64-musl |
| Linux aarch64, 정적 | sping-vX.Y.Z-linux-aarch64-musl |
| Windows x86_64 | sping-vX.Y.Z-windows-x86_64.exe |
| macOS Apple Silicon | sping-vX.Y.Z-macos-arm64 |
| Debian·Ubuntu amd64 | sping_X.Y.Z-1_amd64.deb |
| Debian·Ubuntu arm64 | sping_X.Y.Z-1_arm64.deb |
같은 릴리스의 SHA256SUMS로 파일을 확인할 수 있다. v1.5.5부터 GitHub 릴리스의 모든 파일에 빌드 출처 증명(attestation)이 포함된다. 이 증명은 파일을 만든 커밋과 워크플로 실행을 알려준다.
gh attestation verify sping-vX.Y.Z-linux-x86_64 --repo LambdaBytes/sping
Debian·Ubuntu에서는 다음처럼 설치한다. aarch64에서는 _amd64.deb 대신 _arm64.deb를 사용한다.
sudo dpkg -i sping_1.8.0-1_amd64.deb # or _arm64.deb on aarch64
패키지는 /usr/bin/sping의 바이너리, man sping 매뉴얼, bash·zsh·fish 셸 자동완성, /usr/share/doc/sping/ 아래 문서를 설치한다.
v1.5.5 이후 릴리스의 macOS 바이너리는 Developer ID 서명을 받고 Apple 공증을 거쳤다. 실행 권한을 주면 사용할 수 있다.
chmod +x sping-vX.Y.Z-macos-arm64
./sping-vX.Y.Z-macos-arm64 8.8.8.8
이전의 서명되지 않은 바이너리는 macOS가 실행을 거부할 수 있다. 이 경우 격리 속성을 제거한다.
xattr -d com.apple.quarantine sping-vX.Y.Z-macos-arm64
소스 빌드에는 Rust 1.88 이상이 필요하다(edition 2024와 let-chains 사용).
git clone https://github.com/LambdaBytes/sping.git
cd sping
cargo build --release
# Binary at ./target/release/sping
명령어와 출력 방식
기본 사용 예시는 다음과 같다.
# Single target — compact view (default)
sping 8.8.8.8
# Multiple targets — dashboard table
sping 192.168.1.1 1.1.1.1 api.example.com
# Hostname
sping google.com
# Fast probing (200ms interval)
sping 8.8.8.8 -i 200
# Bind to an interface (Linux) / a source IP (Linux, macOS)
sping 8.8.8.8 -I eth0
sping 8.8.8.8 -S 192.168.1.100
# Another WAN reference for the gateway/WAN check (default 1.1.1.1)
sping 8.8.8.8 --wan-probe 9.9.9.9
# Ping-style flags: count, timeout, payload size, TTL, quiet, family
sping 8.8.8.8 -c 5 # stop after 5 probes (any view)
sping 8.8.8.8 -W 1 # 1s per-probe timeout
sping 8.8.8.8 -s 120 # 120-byte payload
sping 8.8.8.8 -t 10 # outgoing TTL / hop limit
sping 8.8.8.8 -c 10 -q --view classic # quiet: summary only
sping example.com -4 # force IPv4 (-6 for IPv6)
sping fe80::1%eth0 # IPv6 link-local: the zone is required
# TCP connect instead of ICMP (see "TCP connect" below)
sping example.com --tcp 443
sping 192.168.1.1 10.0.0.5 --tcp 22 # every target, the same port
# The ICMP probe, what sping runs without an option until 2.0 (see Roadmap)
sping example.com --icmp
# When the target stops answering, find out why (experimental; one target)
sping example.com --diagnose
# ASCII-only output: automatic on non-UTF-8 locales and on the legacy
# Windows console (SPING_ASCII=0 forces Unicode); NO_COLOR honored
sping 8.8.8.8 --ascii
# This host's addresses: every interface, IPv4 and IPv6, the source each
# family uses and the gateway; sends nothing (see "Host addresses" below)
sping --ip
sping --ip --view json
# ... and the address a STUN server sees (asks stun.cloudflare.com)
sping --ip --external
sping --ip --external stun.example.net:3478
sping --list-interfaces # the IPv4 list it has always printed
# Debug mode
sping --debug 8.8.8.8
종료 코드는 ping과 호환된다. 응답을 받으면 0, 응답이 없으면 1, 오류가 나면 2를 반환한다.
여러 대상을 파일에서 읽는 배치 모드는 대상마다 병렬로 검사한다. 파일에는 한 줄에 대상 하나를 적고 #으로 시작하는 주석을 넣을 수 있다. 결과는 일반 요약이나 JSON으로 표준 출력에 표시하거나 파일에 저장한다.
# Create a hosts file (one target per line, # comments allowed)
cat > hosts.txt << EOF
8.8.8.8
1.1.1.1
google.com
192.168.1.20
EOF
# Summary to stdout (10 probes per host)
sping --batch hosts.txt -c 10
# JSON output
sping --batch hosts.txt -c 20 --view json
# Save to file
sping --batch hosts.txt -c 10 -o results.txt
# JSON to file
sping --batch hosts.txt -c 10 -o results.json --view json
# Fast interval
sping --batch hosts.txt -c 50 -i 200
배치 요약에는 대상별 응답 수와 손실률, 평균·최솟값·최댓값 지연, 지터, TTL, 홉 수, 품질 및 추세가 나온다. 모든 대상을 병렬 검사하며 품질·추세·스파이크 진단도 포함한다.
Sping은 다음 출력을 제공한다. 기본 간결 화면은 고정형 TUI이며, 확장 화면은 RTT 분포와 에코 경로를 더한다. 클래식 화면은 기존 ping처럼 결과를 계속 출력한다. JSON은 스크립트용 NDJSON이며, 다중 대상 표는 터미널이 필요하다.
sping 8.8.8.8 # compact (default) — fixed TUI
sping 8.8.8.8 --view extended # compact + RTT dist + echo path
sping 8.8.8.8 --view classic # traditional ping scrolling
sping 8.8.8.8 --view json # NDJSON for scripting
sping 8.8.8.8 --view json | jq '{rtt: .rtt_last, ttl: .ttl, quality: .quality}'
다중 대상 표는 터미널에서 실시간 갱신된다. 표준 출력이 파일이나 파이프라면 실행이 끝날 때 대상별 요약만 출력하며, -c N으로 멈출 수 있다. --batch 모드는 호스트별 결과나 JSON을 출력한다. 간결·확장 화면은 터미널이 아닌 출력 환경에서 클래식 화면으로 전환된다.
TCP 검사
--tcp PORT는 ICMP 에코 대신 해당 포트로 TCP 연결을 시도하고 핸드셰이크 시간을 잰다. ICMP 권한이 필요하지 않으며 ICMP를 차단하는 네트워크에서도 동작한다. 단일 대상, 다중 대상, 배치 모드와 모든 화면에서 사용할 수 있다.
열린 포트의 Connected to와 거부된 포트의 Refused by는 모두 응답으로 본다. 거부 응답은 대상이나 경로상의 장치에서 올 수 있고, 방화벽이 대상 대신 거부할 수도 있다. 따라서 경로가 작동한다는 뜻이지 서비스가 실행 중이라는 뜻은 아니다. 요약에는 예를 들어 10 connects, 10 answered (3 refused), 0.0% loss라고 표시한다. -W 안에 응답이 없으면 손실, 경로 없음 같은 로컬 실패는 ICMP 전송 실패와 마찬가지로 오류다.
Windows에서는 각 검사가 재전송하지 않는 SYN 하나를 보낸다. Windows가 거부 응답 뒤 재시도하면 약 2초 뒤에야 거부를 보고하기 때문이다. Windows의 응답 대기 시간은 최대 약 3초여서 -W가 3초를 넘더라도 여기서 끝난다. -W는 연결 시간 제한, -t는 TTL·홉 제한, -4와 -6은 주소 계열을 지정한다. -S는 Windows를 포함한 모든 플랫폼에서 출발지 주소를 지정하며, -I는 ICMP 때와 같이 동작한다. -s는 TCP에 적용되지 않아 사용하면 거부된다. 지정한 출발지 주소에 바인딩할 수 없으면 종료 코드 2의 오류가 난다.
TCP에는 읽을 TTL이 없으므로 TTL·운영체제 추정·홉 추정값을 제공하지 않는다. 화면에는 포트(예: tcp/443)와 마지막 연결 결과가 표시된다. 간결·확장 화면은 이벤트에 TCP 443 connected · 21 ms, TCP 443 refused · host or firewall answered, TCP 443 timeout · no answer처럼 나타낸다. 표와 배치 출력은 open, refused, timeout, error를 사용한다. JSON에는 probe, port, refused, tcp_state가 추가된다(JSON 계약). 간결·확장 화면의 게이트웨이·WAN 검사는 계속 ICMP를 사용한다.
검사마다 새 연결을 만들고 정상적으로 닫는다(리셋을 보내지 않는다). 연결이 성립할 때마다 이 호스트에 TIME_WAIT 항목이 남는다. 이는 짧은 연결에서 일반적으로 생기는 동작이다.
실험 기능: 장애 진단
--diagnose는 대상이 응답하지 않을 때 경로 중 어디까지 응답하는지 확인하고 관측한 내용만 보고한다. 대상 하나에만 사용할 수 있으며 실험 기능이다.
sping example.com --diagnose
sping 203.0.113.7 --diagnose -c 30 --view json
대상에 연속 세 번 검사 손실이 발생하면 진단을 시작한다. 실행 전체에서 응답을 한 번도 받지 못한 경우에는 종료 시 진단하며 -c 1 --diagnose도 이에 해당한다. 진단용 소켓을 별도로 사용하므로 추가 검사는 대상 통계에 포함되지 않는다. 확인 항목은 시스템이 대상에 사용할 출발지 주소, 같은 이름의 다른 주소 계열(에코 3회 또는 --tcp PORT를 지정했으면 해당 포트 연결 1회), 대상의 TCP 443·80 포트(단, --tcp 사용 시에는 이미 검사하는 포트를 제외), 그리고 최대 30홉·홉마다 3회·최대 20초·응답 없는 홉 3개 뒤 중단하는 제한형 traceroute다.
대상이 계속 중단된 상태라면 진단이 끝날 때마다 5분 후 다시 확인한다. 새 결과가 나올 때까지 기존 결론을 표시한다. 이벤트에는 diagnosing…, silent after hop 3 (203.0.113.1), hop 5 (198.51.100.9) reports host unreachable, target answers the trace at hop 7, TCP 443 answers, IPv6 works 같은 관측 결과가 나온다. 확장 화면은 검사하지 못한 항목과 이유도 Untested로 보여준다. 예를 들어 other family not tried (address given), trace unavailable: needs privileges처럼 표시한다. 클래식 화면은 새 검사마다 --- 행을 출력하며 JSON 줄에는 active_diagnosis가 들어간다(JSON 계약).
추가 트래픽은 어느 60초 구간에서든 최대 100회로 제한하며, traceroute만 포함해 동시에 진행하는 작업은 최대 3개다. 주소를 직접 지정하거나 -4·-6·-S를 쓰면 다른 주소 계열은 검사하지 않는다. -W, -s, -I, -S는 추가 검사에도 적용되지만 -t는 적용되지 않는다. -c N을 지정하면 마지막 출력은 진단이 끝날 때까지 기다리되 남은 예산을 넘지 않는다. 그 전에 끝나지 않으면 incomplete라고 표시한다. Ctrl+C는 진단을 즉시 중단하며 종료 코드는 바뀌지 않는다.
traceroute는 Linux에서 검사와 같은 소켓·권한으로 실행한다(ICMP 권한 안내). macOS에서는 IPv4 대상에 한해 권한 없이 실행하고, Windows에서도 지원한다. macOS의 IPv6 대상은 아직 traceroute를 하지 않아 trace unavailable on this system이 나온다. 진단 문구와 JSON 코드는 실험 기능이므로 바뀔 수 있다.
호스트 주소와 외부 주소
v1.8부터 sping --ip는 시스템이 파악한 호스트 주소를 보여주고 종료한다. 모든 인터페이스의 주소와 접두사, 주소 종류(loopback, link-local, private, shared (CGNAT), global)를 표시한다. IPv6 주소에는 temporary, deprecated, tentative, duplicate 상태도 표시한다. Windows는 아직 임시 주소를 보고하지 않아 JSON에서는 null이다.
각 주소 계열이 전역 참조 주소로 연결할 때 사용할 출발지 주소도 나온다. 이는 해당 경로의 출발지이므로 자체 경로를 가진 VPN에서는 기본 경로의 출발지와 다를 수 있다. IPv4 기본 게이트웨이도 표시한다. --external이 없으면 패킷을 보내지 않고 권한도 필요하지 않다. 출발지 주소는 패킷을 보내지 않는 UDP 연결로 알아낸다. 시스템이 알려주지 않는 값은 추측하지 않고 알 수 없음으로 표시한다. --view json은 JSON 객체 하나를 출력하며, --list-interfaces는 기존처럼 IPv4 목록을 출력한다.
sping --ip
sping --ip --view json
sping --ip --external
sping --ip --external stun.example.net:3478
sping --list-interfaces # the IPv4 list it has always printed
--external을 지정하면 UDP를 이용하는 STUN 서버(RFC 8489)에 각 주소 계열의 요청이 어떤 주소와 포트에서 왔는지 묻는다. 기본 서버는 stun.cloudflare.com:3478이며 --external SERVER[:PORT]로 바꿀 수 있다. IPv6 주소에 포트를 지정하려면 [address]:port 형식을 쓴다. 시스템 리졸버가 서버 이름을 한 번 조회한다.
주소 계열마다 0초·0.5초·1.5초에 최대 세 번 요청하며, 두 계열을 함께 처리해 전체 제한 시간은 3초다. 요청 트랜잭션 ID가 일치하는 응답만 인정한다. from은 요청이 출발한 이 호스트의 소켓 주소다. 서버가 본 주소와 함께 보면 나가는 경로의 변환(NAT, CGNAT, VPN 또는 변환 없음)을 알 수 있지만, Sping은 이를 특정 유형으로 단정하지 않는다. 서버가 응답하지 않거나 오류·경로 없음이 발생해 확인할 수 없는 값은 이유와 함께 알 수 없음으로 나타내며 종료 코드는 0이다.
권한과 주요 기능
Sping은 macOS와 Windows에서 관리자·sudo 권한 없이 작동한다. Linux에서는 권한 없는 DGRAM ICMP 소켓(net.ipv4.ping_group_range sysctl)을 쓰고, DGRAM이 거부된 경우에만 RAW 소켓으로 대체한다. 대부분의 배포판은 기본적으로 모든 사용자에게 DGRAM ICMP를 허용한다. Debian은 systemd가 권장하는 linux-sysctl-defaults 패키지를 통해 Debian 13부터 허용하지만 Debian 12에서는 허용하지 않는다. Debian 13으로 업그레이드한 시스템에도 해당 패키지가 없을 수 있다.
DGRAM ICMP가 제한돼 있으면 허용 그룹 범위를 넓힐 수 있다.
sudo sysctl -w net.ipv4.ping_group_range='0 2147483647'
RAW 소켓 대체 경로와 인터페이스 바인딩 -I·--interface에는 CAP_NET_RAW가 필요하다. root로 실행하는 대신 바이너리에 권한을 부여할 수 있다.
sudo setcap cap_net_raw+ep /usr/bin/sping
Sping은 IPv4·IPv6 ICMP 에코를 플랫폼별 자체 구현으로 처리하며, ICMP가 필터링된 곳에서는 TCP 연결 검사를 사용할 수 있다. Linux에서는 권한 없는 ICMP가 허용된 경우 관리자 권한 없이 쓸 수 있다. 최근 20회 검사를 기준으로 A–D(매우 좋음·좋음·보통·나쁨), 0–100점 품질 점수와 손실 검사도 반영하는 안정·개선·저하 추세를 계산한다. 적응형 임계값과 쿨다운을 이용해 스파이크를 탐지하고, 중단 시간과 복구 이벤트도 표시한다.
기본 측정값은 RTT, 지터, 손실률, mdev다. 확장 화면에는 RTT의 p50·p95·p99 분포, 범위와 스파이크가 나오며 Linux에서는 커널 수신 타임스탬프를 쓴다. TTL과 홉 수는 ttl 116 · hops ~12처럼 표시한다. TTL이 초기값일 때만 운영체제 힌트를 제공한다(ttl 64 (Unix-like), 128 (Windows), 255 (network)). 라우터를 지나면 TTL만으로 응답 주체를 알 수 없다. 검사에 대한 목적지 도달 불가 응답은 시간 초과와 분리해 누가 무엇을 응답했는지 보여준다.
대상별 네트워크 맥락에는 인터페이스, 출발지 주소와 접두사, 기본 게이트웨이, 대상 분류(같은 LAN, 내부 라우팅, 공용, 기본 게이트웨이, 링크 로컬, 루프백)가 포함된다. 게이트웨이·WAN 보조 검사는 히스테리시스를 사용한다. 세 번 실패하면 오프라인, 두 번 성공하면 온라인으로 판정하며 WAN 기준은 1.1.1.1 또는 --wan-probe IP다. 진단 연관 정보는 target unreachable · internet still OK, gateway unreachable · local network issue likely처럼 표시하며 JSON에는 근거와 함께 안정된 코드로 담는다.
모니터링 중 호스트 이름은 60초마다 다시 확인한다. DNS 응답에서 기존 주소가 사라지면 같은 주소 계열의 다른 주소로 이동한다. WAN 기준 주소에는 도달하지만 이름 조회가 실패하거나 검사하는 주소 계열에 주소가 없으면 그 사실을 표시한다. 단일 대상 모드에서는 네트워크 맥락을 15초마다 다시 감지한다. 인터페이스·출발지·접두사·기본 게이트웨이·대상 분류가 바뀌면 30초 동안 알린다. 실험 기능인 --diagnose는 대상이 중단되면 다른 주소 계열, TCP 443·80, 제한형 traceroute를 확인하고 대상이 계속 중단된 동안 결론을 5분마다 갱신한다. sping --ip는 모든 인터페이스 주소와 유형·IPv6 상태, 주소 계열별 출발지, 게이트웨이를 보여주며 --external을 더하면 STUN 서버가 본 주소도 확인한다. IPv6 링크 로컬 대상은 fe80::1%eth0처럼 영역을 지정할 수 있다.
화면은 간결(기본), 확장, 클래식, JSON, 다중 대상 표로 나뉜다. 간결·확장 화면은 최근 검사 RTT 범위에 맞춘 펄스 막대를 보여주며 손실은 표시하고 스파이크는 색으로 구분한다. 파일을 이용하는 배치 모드에서는 요약이나 JSON을 표준 출력 또는 파일로 보낼 수 있다. JSON은 안정된 NDJSON 형식이며 진단 코드를 게이트웨이·WAN 상태와 그 근거와 함께 담는다(JSON 계약). ping 스타일 옵션(-c, -W, -s, -t, -q, -4·-6, -i, -I, -S)과 ping 호환 종료 코드를 지원한다.
ASCII 출력은 --ascii로 지정할 수 있고, UTF-8이 아닌 로캘과 구형 Windows 콘솔에서는 자동으로 사용한다. SPING_ASCII=0은 유니코드 출력을 강제하며 NO_COLOR도 따른다. Ctrl+C와 Unix의 SIGTERM을 받으면 모니터링을 정상 종료하고 최종 요약을 출력한다(JSON 화면 제외). 클래식·JSON·배치 출력은 sping … | head처럼 파이프가 닫히는 경우도 처리한다. 디버그 모드는 --debug 또는 SPING_LOG=debug로 켠다.
플랫폼 차이와 구현
플랫폼별 기능 차이는 다음과 같다.
| 기능 | Linux | macOS | Windows |
|---|---|---|---|
| IPv4 ICMP | DGRAM 소켓 | DGRAM 소켓 | IcmpSendEcho |
| IPv6 | ICMPv6 DGRAM | ICMPv6 DGRAM | Icmp6SendEcho2 |
| TTL·홉 제한 | recvmsg | IPv4는 IP 헤더, IPv6는 recvmsg | IPv4 API만 지원 |
| 게이트웨이 감지 | /proc/net/route | /sbin/route | route print |
| 인터페이스 감지 | /proc/net/route, if_inet6 | /sbin/ifconfig | GetAdaptersAddresses |
호스트 주소(--ip) | getifaddrs, if_inet6 | /sbin/ifconfig | GetAdaptersAddresses |
| 목적지 도달 불가 | ICMP 오류(IP_RECVERR) | DGRAM 소켓, IPv4만 | 응답 상태 |
-I 인터페이스 지정 | SO_BINDTODEVICE | 허용되지만 효과 없음 | 경고 후 바인딩하지 않음 |
-S 출발지 지정 | bind() | bind() | OS 경로(TCP는 bind()) |
| TCP 연결 | socket2 | socket2 | socket2 (Winsock) |
| 진단 traceroute | ICMP 오류(IP_RECVERR) | DGRAM 소켓, IPv4만 | TTL을 지정한 IcmpSendEcho |
| 관리자 권한 | 권한 없는 ICMP 허용 시 불필요 | 불필요 | 불필요 |
| 전체 화면 | 모두 지원 | 모두 지원 | 모두 지원 |
각 플랫폼은 자체 ICMP 구현을 사용하며 제3자 ping 라이브러리는 쓰지 않는다. Linux는 DGRAM 소켓에 socket2를, TTL·홉 제한 수신에는 libc의 recvmsg를 사용하고 DGRAM이 막히면 RAW 소켓으로 대체한다. macOS는 DGRAM 소켓과 IPv4 TTL용 IP 헤더 분석, IPv6 홉 제한용 recvmsg를 쓴다. Windows는 iphlpapi.dll의 IcmpSendEcho·Icmp6SendEcho2 FFI를 쓴다. TCP 연결 검사는 모든 플랫폼에서 socket2로 검사마다 연결 하나를 만든다.
진단 traceroute는 별도 ICMP 소켓에서 TTL을 늘려 에코를 보낸다. Linux는 소켓 오류 큐(IP_RECVERR)에서 라우터 오류를 읽고, macOS IPv4는 호스트의 다른 ICMP 메시지와 함께 수신한 뒤 traceroute 메시지를 따로 보관한다. Windows는 TTL을 지정한 IcmpSendEcho·Icmp6SendEcho2를 이용한다. 비동기 Tokio 런타임, watch 채널, 초당 10프레임으로 동작하는 단일 작성자 렌더러를 사용한다.
x86_64·aarch64·armv7(armhf)은 컴파일 검사를 거친다. aarch64와 armv7은 64비트·32비트 Raspberry Pi OS를 포함한다. 릴리스 파일은 Linux x86_64·aarch64(glibc 및 정적 musl), macOS arm64, Windows x86_64용으로 제공된다.
알려진 제한
-I·--interface는 Linux에서만 실제로 인터페이스에 바인딩한다. macOS는 옵션을 받아들이지만 효과가 없고, Windows는 경고를 출력한 뒤 바인딩하지 않고 검사한다. Windows에서 ICMP는 -S·--source를 무시하고 OS가 경로를 선택하지만, --tcp는 출발지 주소에 바인딩한다.
각 검사는 응답을 받을 때까지, 최대 -W 시간 동안 기다린 뒤 다음 검사를 보낸다. 이는 Windows ping과 같은 방식이다. Linux·macOS ping은 -i 간격대로 계속 보낸다. 따라서 -W가 -i보다 길고 대상이 응답하지 않으면 기본값인 2초마다가 아니라 -W마다 검사한다. -c N 실행은 최대 N × -W까지 걸릴 수 있다.
RAW 소켓 대체 경로와 -I에는 CAP_NET_RAW가 필요하다(SECURITY.md). 일반적인 사용은 권한 없는 DGRAM 경로로 가능하다. 이름 조회는 시스템 리졸버를 통해 이뤄지고 시간 제한은 5초다. 모니터링 중에는 60초마다 다시 조회하며 역방향 DNS나 자체 DNS 캐시는 사용하지 않는다.
정적 -musl 바이너리는 musl 자체 리졸버를 사용한다. /etc/hosts와 /etc/resolv.conf의 서버를 이용하며 시스템 NSS 모듈을 쓰지 않는다. 따라서 mDNS .local 이름 등은 조회되지 않는다. IPv6 응답의 홉 제한(ttl)은 Linux·macOS에서 표시되며 Windows에서는 표시하지 않는다(JSON에서는 0). 게이트웨이 감지는 IPv4만 지원하고, --list-interfaces도 IPv4 주소만 나열한다. 전체 주소는 --ip로 볼 수 있다.
--tcp를 사용해도 게이트웨이·WAN 보조 검사는 ICMP를 쓴다. ICMP 권한이 없으면 이 검사는 경고와 함께 비활성화되고 ?로 표시된다. IPv6 링크 로컬 대상은 fe80::1%eth0 또는 인터페이스 인덱스 fe80::1%2처럼 영역이 필요하다. Windows에서는 인터페이스 인덱스 형식만 지원한다. --diagnose는 실험 기능이며 대상 하나만 지원하고, macOS traceroute는 IPv4만 지원한다.
목적지 도달 불가와 시간 초과의 구분은 Linux·Windows, 그리고 macOS의 IPv4 대상에서 가능하다. macOS의 IPv6 대상은 여전히 시간 초과로 표시된다. 시스템이 -W가 끝난 뒤에야 응답하는 경우도 시간 초과가 된다. Linux·Windows에서는 호스트가 없는 LAN 주소가 ARP 포기 시점에 보고되며, 시작 후 약 3초가 걸린다. 따라서 기본 -W 2에서는 일부 검사가 시간 초과로 나오고 -W 4에서는 모두 도달 불가로 표시된다.
로드맵과 배포
2.0에서는 sping target의 동작을 바꿔 대상이 응답하지 않는 이유를 현재 --diagnose처럼 자체적으로 확인할 계획이다. v1.8부터 제공하는 --icmp는 스크립트가 기존 검사를 계속 사용하도록 한다. -4, -6, --tcp의 동작은 유지된다.
배포 패키징은 진행 중이다. AUR과 Fedora/COPR 레시피는 packaging/에 있고 Debian 패키지는 Debian Rust 팀을 통해 준비 중이다. WinGet(LambdaBytes.Sping)과 nixpkgs 패키지는 검토 중이다.
GitHub 릴리스에는 서명·공증된 macOS 바이너리와 파일마다 빌드 출처 증명이 포함된다. 배포 대상은 Linux x86_64·aarch64(glibc 2.34 이상 및 정적 musl), macOS arm64, Windows x86_64이며, 매뉴얼과 셸 자동완성을 포함하는 .deb, Homebrew, Scoop, crates.io도 제공한다.
성능 정보
프로젝트가 공개한 수치는 바이너리 크기 1.9 MiB(스트립 및 LTO 적용), 상주 메모리 약 4 MB, 초당 두 번 검사할 때 CPU 사용률 1% 미만이다. Rust 코드는 약 23,400줄이며 테스트는 375개(단위 테스트 330개, E2E 45개)다.
관련 자료: LinuxLinks 리뷰, Terminal Trove 소개, Awesome Rust 시스템 도구 목록, DEV Community 글
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요