本文目录导读:

- 方法一:使用
ping命令(最基础、最通用) - 方法二:使用
mtr/traceroute(检测路径丢包) - 方法三:使用 TCP/UDP 协议(绕过 ICMP 限制)
- 方法四:编写通用检测函数(Python 示例)
- 方法五:实时 UDP 丢包检测(高精度)
- 注意事项
- 推荐组合方案
本地设备到外网(如访问百度)和 本地到特定服务器(如公司内网),以下是几种常用的脚本检测方法:
使用 ping 命令(最基础、最通用)
这是最直接的检测方法,几乎所有操作系统都支持。
原理: 发送ICMP包,统计丢失的包数占总发送数的百分比。
Windows (Batch/PowerShell)
@echo off :: 发送10个包,检查丢包率 ping -n 10 www.baidu.com | findstr "丢失"
PowerShell 脚本:
$result = Test-Connection -ComputerName "8.8.8.8" -Count 10 -Quiet
# 或者获取详细统计
$stats = Test-Connection -ComputerName "8.8.8.8" -Count 10
$loss = ($stats | Where-Object {$_.StatusCode -ne 0}).Count
Write-Host "丢包数: $loss"
Linux/macOS (Bash)
#!/bin/bash # 发送10个包,超时2秒,提取丢包百分比 ping -c 10 -W 2 8.8.8.8 | grep -oP '\d+(?=% packet loss)'
进阶:循环检测并告警
#!/bin/bash
TARGET="8.8.8.8"
THRESHOLD=20 # 丢包率超过20%视为异常
while true; do
LOSS=$(ping -c 10 -W 2 $TARGET | grep -oP '\d+(?=% packet loss)')
if [ "$LOSS" -gt "$THRESHOLD" ]; then
echo "[ALERT] 丢包率: ${LOSS}%"
# 可以在这里发送邮件或推送通知
else
echo "[OK] 丢包率: ${LOSS}%"
fi
sleep 60 # 每分钟检测一次
done
使用 mtr / traceroute(检测路径丢包)
如果想知道哪一跳丢了包,需要用带路由追踪的工具。
Linux (mtr):
# 连续发送10个包,显示每跳的丢包率 mtr -r -c 10 8.8.8.8
输出会显示每个路由节点的 Loss% 列。
Windows (pathping):
pathping -n 8.8.8.8
等待计算完成(默认会发几百个包),会显示每一跳的丢包率。
使用 TCP/UDP 协议(绕过 ICMP 限制)
有些网络会限制 ICMP 包,导致 ping 误判,此时需要用真实应用层协议检测。
使用 curl 检测 HTTP 延迟(间接判断)
#!/bin/bash
# 下载一个1KB的小文件,记录耗时和成功率
URL="http://example.com/1kb.txt"
TOTAL=10
FAIL=0
for i in $(seq 1 $TOTAL); do
if ! curl -s -o /dev/null --connect-timeout 3 --max-time 5 "$URL"; then
((FAIL++))
fi
done
echo "TCP/TLS 连接丢包率: $((FAIL * 100 / TOTAL))%"
使用 iperf3(专业级)
需要两端都装 iperf3:
# 服务端(目标主机) iperf3 -s # 客户端(检测端) iperf3 -c <服务器IP> -u -b 10M -t 10 # UDP模式,发送10秒 # 输出中会明确显示 "Lost/Total Datagrams" 和丢包率
编写通用检测函数(Python 示例)
适合需要跨平台或集成到监控系统:
import subprocess
import re
import os
def check_packet_loss(host="8.8.8.8", count=10, timeout=3):
"""
返回丢包率(0-100浮点数),-1表示检测失败
"""
try:
# 根据操作系统选择参数
if os.name == 'nt': # Windows
cmd = f"ping -n {count} -w {timeout*1000} {host}"
else: # Linux/macOS
cmd = f"ping -c {count} -W {timeout} {host}"
output = subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT)
# 提取丢包百分比
loss_match = re.search(r'(\d+)% loss', output)
if loss_match:
return float(loss_match.group(1))
# 备用:检查收发包数
if os.name != 'nt':
sent = output.count('bytes from')
loss_rate = (1 - sent/count) * 100
return loss_rate
return 0.0
except subprocess.CalledProcessError as e:
# ping命令本身失败(如网络不可达)
return 100.0
except Exception as e:
print(f"检测异常: {e}")
return -1.0
# 使用示例
loss = check_packet_loss("8.8.8.8")
if loss >= 0:
print(f"当前丢包率: {loss:.1f}%")
else:
print("检测失败")
实时 UDP 丢包检测(高精度)
用于检测网络质量波动,例如游戏语音、视频会议场景:
import socket
import time
import threading
class UDPPingTester:
def __init__(self, target_ip, port=33445, packet_size=64):
self.target = (target_ip, port)
self.size = packet_size
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.settimeout(1)
def test(self, count=100):
"""发送count个包,返回丢包率"""
sent = 0
received = 0
seq = 0
while sent < count:
try:
# 发送带序号的数据
data = f"SEQ:{seq}".encode() + b'\x00' * (self.size - 6)
self.sock.sendto(data, self.target)
sent += 1
# 接收回显
resp, addr = self.sock.recvfrom(1024)
received += 1
except socket.timeout:
pass # 包丢失或未返回
finally:
seq += 1
time.sleep(0.01) # 10ms间隔,避免冲击
loss_rate = (1 - received / sent) * 100
return loss_rate
# 需要在目标机器上运行服务端(回显所有UDP包)
UDP 服务端示例:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', 33445))
while True:
data, addr = sock.recvfrom(1024)
sock.sendto(data, addr) # 原样返回
注意事项
- 防火墙限制: 某些云服务商(如AWS、GCP)会屏蔽ICMP,建议改用TCP 80/443端口检测。
- 丢包原因区分:
- 网络拥塞(间歇性丢包)
- 线路故障(持续高丢包)
- 设备问题(特定端口或协议丢包)
- 多目标检测: 建议同时检测 内网网关 + 外网DNS(如8.8.8.8/114.114.114.114),以定位问题范围。
推荐组合方案
对于日常运维监控,推荐使用:
# Linux 持续监控(同时检测4个目标)
for target in "192.168.1.1" "8.8.8.8" "114.114.114.114" "www.baidu.com"; do
ping -c 20 -W 2 $target | grep -E "(packet loss|statistics)" &
done
wait
如果需要集成到Prometheus/Grafana,建议使用 smoke ping 或 blackbox_exporter 这类专业工具。