在 shell 脚本中处理 64 位整数

Che*_*ppy 7 shell-script arithmetic

我正在尝试计算以太网接口上使用的带宽(1000 Mbit/s)。为了测试我的脚本,我使用iperf工具来生成巨大的带宽。

我现在面临的问题是,当eth0_rx1eth0_rx2变得其比最大32位的值大的值。我得到的差异为 0。

不知何故

printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"
Run Code Online (Sandbox Code Playgroud)

给出了正确的值,但是当尝试使用

eth0_diff=expr $eth0_rx2 - $eth0_rx1
Run Code Online (Sandbox Code Playgroud)

我得到的值为 0。

有没有办法处理超过 32 位rx_bytestx_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
Run Code Online (Sandbox Code Playgroud)

使用的脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

Ste*_*itt 17

鉴于这printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"给了您正确的值,只要整数算术足够好,您就会得到答案:$((eth0_rx2-eth0_rx1)) shell 算术

许多 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))
Run Code Online (Sandbox Code Playgroud)

GNUexpr 可以支持任意精度算术,如果它是用 GNU MP 库构建的。在其他情况下,它使用本机整数,显然在您的系统上(假设您使用的是 GNU expr),它们的大小为 32 位。其他实现可能有类似的限制。


Fel*_*xJN 7

bash 确实使用 64 位整数:

$echo $((2**63-1))
9223372036854775807
$echo $((2**63))
-9223372036854775808
Run Code Online (Sandbox Code Playgroud)

  • @Cheppy:您使用的是 `expr` 而不是 shell 算术,而且您使用的是 `/bin/sh` 而不是 bash。 (11认同)