我正在尝试计算以太网接口上使用的带宽(1000 Mbit/s)。为了测试我的脚本,我使用iperf产生巨大带宽的工具。
我面临的问题是何时eth0_rx1
和eth0_rx2
获取大于最大 32 位值的值。我得到的差异为 0。
不知何故
printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"
给出了正确的值,但是当尝试使用
eth0_diff=expr $eth0_rx2 - $eth0_rx1
我得到的值为 0。
有没有办法处理是否rx_bytes
超过tx_bytes
32 位?
我不确定这是否是一种计算已用带宽的优雅方法。如果不是,请建议其他替代方法。
示例输出:
eth0_rx1 = 2134947002 \
eth0_rx2= 2159752166 \
eth0 Download rate: 24805164 B/s \
eth0_diff = 12536645 \
eth0_rx_kB = 12242 \
eth0_rx_kB_100 = 1224200 \
eth0_rx_kB_BW = 9
eth0_rx1 = 2159752166 \
eth0_rx2= 2184557522 \
eth0 Download rate: 24805356 B/s \
eth0_diff = 0 \
eth0_rx_kB = 0 \
eth0_rx_kB_100 = 0 \
eth0_rx_kB_BW = 0
使用的脚本:
#!/bin/sh
eth0_rx1=$(cat /sys/class/net/eth0/statistics/rx_bytes)
while sleep 1; do
eth0_rx2=$(cat /sys/class/net/eth0/statistics/rx_bytes)
echo "eth0_rx1 = $eth0_rx1"
echo "eth0_rx2= $eth0_rx2"
printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"
eth0_diff=`expr $eth0_rx2 - $eth0_rx1`
echo "eth0_diff = $eth0_diff"
#convert bytes to Kilo Bytes
eth0_rx_kB=`expr $eth0_diff / 1024`
echo "eth0_rx_kB = $eth0_rx_kB"
#bandwidth calculation
eth0_rx_kB=`expr $eth0_rx_kB \* 100`
echo "eth0_rx_kB_100 = $eth0_rx_kB"
#125000 = 1000 Mbit/s
eth0_rx_kB=`expr $eth0_rx_kB / 125000`
echo "eth0_rx_kB_BW = $eth0_rx_kB"
eth0_rx1=$eth0_rx2
eth2_rx1=$eth2_rx2
done
答案1
假设printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"
给出了正确的值,只要整数算术足够好,你就可以得到答案:$((eth0_rx2-eth0_rx1))
,IE 壳算术。
许多 shell,尤其是 Bash,都使用64 位整数,即使在 32 位平台上也是如此。
因此:
eth0_diff=$((eth0_rx2 - eth0_rx1))
...
eth0_rx_kB=$((eth0_diff / 1024))
...
eth0_rx_kB=$((eth0_rx_kB * 100))
...
eth0_rx_kB=$((eth0_rx_kB / 125000))
GNUexpr
能支持任意精度算术,如果它是用 GNU MP 库构建的。在其他情况下,它使用本机整数,显然在您的系统上(假设您使用的是 GNU expr
),这些整数的大小为 32 位。其他实现可能也有类似的限制。
答案2
bash
确实使用 64 位整数:
$echo $((2**63-1))
9223372036854775807
$echo $((2**63))
-9223372036854775808
答案3
标准任意精度计算器是dc
。我们可以用它来进行大整数算术:
eth0_diff=$(dc -e "$eth0_rx2 $eth0_rx1 -p")
您甚至可以使用和命令dc
进行打印:n
p
#!/bin/sh
set -eu
netstatfile=/sys/class/net/eth0/statistics/rx_bytes
test -r "$netstatfile"
eth0_rx1=$(cat "$netstatfile")
while sleep 1
do
eth0_rx2=$(cat "$netstatfile")
dc -e "$eth0_rx1[eth0_rx1 = ]np $eth0_rx2[eth0_rx2 = ]np" \
-e 'r-[eth0_diff = ]np [Download rate: ]np 1024/[eth0_rx_kB = ]np' \
-e '100/[eth0_rx_kB_100 = ]np 125000/[eth0_rx_kB_BW = ]np'
eth0_rx1=$eth0_rx2
done
您可能会发现该numfmt
工具(GNU coreutils 的一部分)对于除以十进制或二进制千位很有用。它能够处理非常大的数字(尽管不可否认这里使用的不是奇怪的混合物)。