傳統流量監控工具(iftop、nload、vnstat)依賴 libpcap 抓包分析,在 10Gbps+ 高速介面上 CPU 佔用極高甚至漏包。Linux 核心透過 /sys/class/net/<介面>/statistics/ 暴露介面級計數器(封包數、位元組數、錯誤、丟包),讀取無需複製封包內容,極適合高頻、低負擔流量統計。本文提供可直接部署的 Shell 腳本與解析邏輯。
/sys/class/net/eth0/statistics/
├── rx_bytes # 接收位元組數
├── tx_bytes # 傳送位元組數
├── rx_packets # 接收封包數
├── tx_packets # 傳送封包數
├── rx_errors # 接收錯誤
├── tx_errors # 傳送錯誤
├── rx_dropped # 接收丟包
├── tx_dropped # 傳送丟包
├── rx_fifo_errors # FIFO 錯誤
├── tx_fifo_errors
├── rx_frame_errors
├── tx_carrier_errors
├── rx_compressed
├── tx_compressed
├── rx_multicast
└── collisions
數值為累計計數器(64 位元無號整數),核心驅動程式即時更新,讀取即為當前快照。
#!/bin/bash
# pps_monitor.sh - 監控指定介面每秒封包收發數
# 用法: ./pps_monitor.sh eth0
INTERVAL=1
IFACE=${1:-eth0}
if [[ ! -d "/sys/class/net/$IFACE/statistics" ]]; then
echo "錯誤: 介面 $IFACE 不存在或無 statistics 目錄"
exit 1
fi
echo "監控介面: $IFACE (間隔 ${INTERVAL}s)"
echo "時間 RX PPS TX PPS"
while true; do
R1=$(cat /sys/class/net/$IFACE/statistics/rx_packets)
T1=$(cat /sys/class/net/$IFACE/statistics/tx_packets)
sleep $INTERVAL
R2=$(cat /sys/class/net/$IFACE/statistics/rx_packets)
T2=$(cat /sys/class/net/$IFACE/statistics/tx_packets)
RX_PPS=$((R2 - R1))
TX_PPS=$((T2 - T1))
printf "%s %'12d %'12d\n" "$(date '+%H:%M:%S')" $RX_PPS $TX_PPS
done
#!/bin/bash
# bw_monitor.sh - 監控指定介面每秒位元組/位元傳輸率
# 用法: ./bw_monitor.sh eth0
INTERVAL=1
IFACE=${1:-eth0}
if [[ ! -d "/sys/class/net/$IFACE/statistics" ]]; then
echo "錯誤: 介面 $IFACE 不存在"
exit 1
fi
echo "監控介面: $IFACE (間隔 ${INTERVAL}s)"
printf "%-10s %'15s %'15s %'15s %'15s\n" "時間" "RX Bytes/s" "TX Bytes/s" "RX bits/s" "TX bits/s"
while true; do
RX1=$(cat /sys/class/net/$IFACE/statistics/rx_bytes)
TX1=$(cat /sys/class/net/$IFACE/statistics/tx_bytes)
sleep $INTERVAL
RX2=$(cat /sys/class/net/$IFACE/statistics/rx_bytes)
TX2=$(cat /sys/class/net/$IFACE/statistics/tx_bytes)
RX_BPS=$((RX2 - RX1))
TX_BPS=$((TX2 - TX1))
RX_bps=$((RX_BPS * 8))
TX_bps=$((TX_BPS * 8))
printf "%-10s %'15d %'15d %'15d %'15d\n" \
"$(date '+%H:%M:%S')" $RX_BPS $TX_BPS $RX_bps $TX_bps
done
#!/bin/bash
# net_health.sh - 綜合介面健康度監控
IFACE=${1:-eth0}
INTERVAL=2
declare -A PREV
for f in /sys/class/net/$IFACE/statistics/*; do
PREV[$(basename $f)]=$(cat $f)
done
echo "介面 $IFACE 健康度監控 (間隔 ${INTERVAL}s)"
printf "%-8s %'12s %'12s %'10s %'10s %'8s %'8s %'8s %'8s\n" \
"時間" "RX_B" "TX_B" "RX_P" "TX_P" "RX_ERR" "TX_ERR" "RX_DRP" "TX_DRP"
while true; do
sleep $INTERVAL
declare -A CUR
for f in /sys/class/net/$IFACE/statistics/*; do
CUR[$(basename $f)]=$(cat $f)
done
RX_B=$((CUR[rx_bytes]-PREV[rx_bytes]))
TX_B=$((CUR[tx_bytes]-PREV[tx_bytes]))
RX_P=$((CUR[rx_packets]-PREV[rx_packets]))
TX_P=$((CUR[tx_packets]-PREV[tx_packets]))
RX_E=$((CUR[rx_errors]-PREV[rx_errors]))
TX_E=$((CUR[tx_errors]-PREV[tx_errors]))
RX_D=$((CUR[rx_dropped]-PREV[rx_dropped]))
TX_D=$((CUR[tx_dropped]-PREV[tx_dropped]))
printf "%-8s %'12d %'12d %'10d %'10d %'8d %'8d %'8d %'8d\n" \
"$(date '+%H:%M:%S')" $RX_B $TX_B $RX_P $TX_P $RX_E $TX_E $RX_D $TX_D
PREV=("${CUR[@]}") # 陣列複製需 Bash 4.3+
# 相容寫法: for k in "${!CUR[@]}"; do PREV[$k]=${CUR[$k]}; done
done
# /etc/systemd/system/net-monitor@.service
[Unit]
Description=Network Interface Monitor for %i
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/bw_monitor.sh %i
StandardOutput=append:/var/log/net-monitor/%i.log
Restart=on-failure
User=nobody
[Install]
WantedBy=multi-user.target
mkdir -p /var/log/net-monitor
systemctl enable --now net-monitor@eth0
Node Exporter 會自動收集 /sys/class/net/*/statistics/ 並暴露為 node_network_receive_bytes_total 等指標,生產環境建議直接使用 Node Exporter + Prometheus + Grafana,無需自寫腳本。
#!/bin/bash
# aggregate_bw.sh - 統計所有實體介面總流量
INTERVAL=1
while true; do
RX_TOT=0; TX_TOT=0
for iface in /sys/class/net/*/statistics/rx_bytes; do
[[ $iface =~ /sys/class/net/(.+)/statistics ]] && IFACE=${BASH_REMATCH[1]}
[[ $IFACE =~ ^(lo|docker|veth|br-|virbr) ]] && continue # 排除虛擬介面
RX_TOT=$((RX_TOT + $(cat $iface)))
TX_TOT=$((TX_TOT + $(cat ${iface/rx_bytes/tx_bytes})))
done
sleep $INTERVAL
# 計算差值輸出...
done
| 指標 | libpcap 抓包 | /sys 統計介面 |
|---|---|---|
| CPU 佔用 (10Gbps) | 高 (需複製封包至用戶空間) | 極低 (僅讀取計數器) |
| 記憶體壓力 | 大 (Ring Buffer) | 無 |
| 封包處理延遲 | 有 (中斷、複製) | 零 (核心原子更新計數器) |
| 可見封包內容 | 是 (深度分析) | 否 (僅統計量) |
| 適用場景 | 封包級分析、異常排查 | 高頻流量計費、頻寬監控、告警 |
rx_compressed),讀取時需容錯。--cap-add=CAP_NET_ADMIN 或掛載 /sys/class/net 才能看到容器專屬介面。基於 /sys/class/net/statistics 的 Shell 腳本,提供零負擔、高頻率、生產級可用的高速網路流量監控能力。適合嵌入式裝置、無 Node Exporter 環境、快速臨時監控。長期運行建議遷移至 Node Exporter + Prometheus 體系,獲得持久化、告警、視覺化完整能力。