如何编写通用Shell脚本实现物理网卡带宽限速(如将10G链路限制为1G等)
如何编写通用Shell脚本实现物理网卡带宽限速(如将10G链路限制为1G等)
我太懂你不想翻出积灰老hub的心情了!用Linux的tc命令配合TBF(Token Bucket Filter)确实是最省心的软件限速方案,不用折腾硬件还能灵活调整带宽。下面我就给你写一个通用Shell脚本,同时把那些让人头疼的参数计算讲明白,保证你能直接用、看得懂。
先理清核心参数逻辑
TBF实现限速的关键是三个参数,先把它们搞透:
- rate:就是你想要模拟的目标带宽,比如10M、100M,这是核心控制项;
- burst:突发流量上限,简单说就是允许短时间内超过rate的最大流量。计算逻辑一般结合网卡MTU和目标带宽,公式可以用
(MTU * 8) * 5(5个MTU大小的包,足够应对大部分场景),或者rate * latency / 1000(latency是延迟,单位毫秒); - latency:令牌桶的等待延迟,意思是当流量超过rate时,最多等多久再处理。现在内核支持NO_HZ的情况下,不用纠结系统tick,设个100ms就很稳妥,既能保证流量平滑,又不会有明显延迟。
通用Shell脚本实现
直接上可运行的脚本,保存成link-bandwidth.sh后记得加执行权限chmod +x link-bandwidth.sh:
#!/bin/bash # 检查参数数量是否正确 if [ $# -ne 2 ]; then echo "用法: $0 <网卡名> <目标带宽,如10m|100m|1G|2.5G|10G>" exit 1 fi IFACE=$1 TARGET_BW=$2 # 检查网卡是否存在 if [ ! -d "/sys/class/net/$IFACE" ]; then echo "错误:网卡 $IFACE 不存在!" exit 1 fi # 获取网卡MTU值 MTU=$(cat "/sys/class/net/$IFACE/mtu") # 设置延迟参数(固定100ms,通用场景足够) LATENCY=100 # 把人类友好的带宽单位转换成bps(比特每秒) case $TARGET_BW in 10m) RATE=10000000 ;; 100m) RATE=100000000 ;; 1G) RATE=1000000000 ;; 2.5G) RATE=2500000000 ;; 10G) RATE=10000000000 ;; *) echo "错误:不支持的带宽单位!请使用10m|100m|1G|2.5G|10G" exit 1 ;; esac # 计算burst值:取MTU计算和带宽延迟计算的较大值,兼顾突发流量和带宽匹配 BURST_MTU=$((MTU * 8 * 5)) BURST_RATE=$((RATE * LATENCY / 1000)) BURST=$((BURST_MTU > BURST_RATE ? BURST_MTU : BURST_RATE)) # 先清除网卡上已有的tc规则(避免新旧规则冲突) echo "正在清除 $IFACE 上的旧限速规则..." tc qdisc del dev $IFACE root 2>/dev/null # 添加新的TBF限速规则 echo "正在将 $IFACE 限速为 $TARGET_BW..." tc qdisc add dev $IFACE root tbf rate $RATE burst $BURST latency $LATENCY if [ $? -eq 0 ]; then echo "限速成功!当前 $IFACE 带宽限制为 $TARGET_BW" else echo "错误:限速失败,请确保以root权限运行!" exit 1 fi
脚本使用说明
- 权限要求:必须用root或sudo运行,因为
tc命令需要管理员权限; - 使用示例:
- 把eth0限速为100M:
sudo ./link-bandwidth.sh eth0 100m - 恢复网卡原带宽(清除规则):
sudo tc qdisc del dev eth0 root
- 把eth0限速为100M:
- 灵活调整:要是需要其他带宽档位,直接在脚本的
case分支里加对应的数值就行,比如加个500m)对应RATE=500000000。
额外注意事项
- 脚本默认限制的是**出口(egress)**带宽,如果需要限制入口(ingress),得配合
tc ingress和filter规则实现,逻辑稍复杂,有需要可以再细聊; - 测试限速是否生效,推荐用
iperf3工具:在另一台机器跑iperf3 -s,你的机器跑iperf3 -c <对方IP>,就能看到实际带宽是否符合预期; - 如果限速后出现丢包,可适当调大burst值,比如把脚本里的
*5改成*10,给突发流量更多缓冲空间。
备注:内容来源于stack exchange,提问作者olh




