首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理shell脚本中的64位整数

处理shell脚本中的64位整数
EN

Unix & Linux用户
提问于 2021-06-23 12:34:17
回答 3查看 2.2K关注 0票数 7

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

我面临的问题是,当eth0_rx1eth0_rx2获得大于最大32位值的值时。我得到的差额是0。

不知何故

代码语言:javascript
复制
printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"

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

代码语言:javascript
复制
eth0_diff=expr $eth0_rx2 - $eth0_rx1

我得到的值是0。

如果rx_bytestx_bytes超过32位,是否有一种处理方法?

我不确定这是计算使用的带宽的一种优雅的方法。如果没有,请建议其他替代方式。

Sample输出:

代码语言:javascript
复制
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

使用的Script:

代码语言:javascript
复制
#!/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
EN

回答 3

Unix & Linux用户

回答已采纳

发布于 2021-06-23 12:41:10

假设printf 'eth0 Download rate: %s B/s\n' "$((eth0_rx2-eth0_rx1))"给出了正确的值,只要整数算法足够好,您就得到了答案:$((eth0_rx2-eth0_rx1)),即外壳算法

许多shell,特别是Bash,使用64位整数,即使在32位平台上也是如此。

因此:

代码语言:javascript
复制
    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))

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

票数 17
EN

Unix & Linux用户

发布于 2021-06-23 12:41:44

bash确实使用64位整数:

代码语言:javascript
复制
$echo $((2**63-1))
9223372036854775807
$echo $((2**63))
-9223372036854775808
票数 7
EN

Unix & Linux用户

发布于 2021-06-24 08:09:26

标准的任意精度计算器是dc.我们可以将它用于大整数算法:

代码语言:javascript
复制
eth0_diff=$(dc -e "$eth0_rx2 $eth0_rx1 -p")

您甚至可以让dc使用np命令进行打印:

代码语言:javascript
复制
#!/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的一部分)对于除以十进制或二进制数千很有用。它能够处理非常大的数字(尽管不可否认,这里使用的奇怪的混合物不是这样的)。

票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/655470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档