脚本如何检测网络是否丢包

wen 实用脚本 2

本文目录导读:

脚本如何检测网络是否丢包

  1. 方法一:使用 ping 命令(最基础、最通用)
  2. 方法二:使用 mtr / traceroute(检测路径丢包)
  3. 方法三:使用 TCP/UDP 协议(绕过 ICMP 限制)
  4. 方法四:编写通用检测函数(Python 示例)
  5. 方法五:实时 UDP 丢包检测(高精度)
  6. 注意事项
  7. 推荐组合方案

本地设备到外网(如访问百度)和 本地到特定服务器(如公司内网),以下是几种常用的脚本检测方法:

使用 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)  # 原样返回

注意事项

  1. 防火墙限制: 某些云服务商(如AWS、GCP)会屏蔽ICMP,建议改用TCP 80/443端口检测。
  2. 丢包原因区分:
    • 网络拥塞(间歇性丢包)
    • 线路故障(持续高丢包)
    • 设备问题(特定端口或协议丢包)
  3. 多目标检测: 建议同时检测 内网网关 + 外网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 pingblackbox_exporter 这类专业工具。

抱歉,评论功能暂时关闭!