首页 > 解决方案 > Bash变量不保存给定的新数据?

问题描述

我写了一个 Bash 函数:

                CAPACITY=0
                USED=0
                FREE=0
                df | grep /$ | while read LINE ; do
                        CAPACITY=$(echo "${CAPACITY}+$(echo ${LINE} | awk '{print $2}')" | bc )
                        USED="$[${USED}+$(echo ${LINE} | awk '{print $3}')]"

                        FREE="$[${FREE}+$(echo ${LINE} | awk '{print $4}')]"
                done

                echo -e "${CAPACITY}\t${USED}\t${FREE}"

                for i in /home /etc /var /usr; do
                        df | grep ${i}[^' ']*$ | while read LINE ; do
                                CAPACITY=$[${CAPACITY}+$(echo ${LINE} | awk '{print $2}')]
                                USED=$[${USED}+$(echo ${LINE} | awk '{print $3}')]
                                FREE=$[${FREE}+$(echo ${LINE} | awk '{print $4}')]
                        done
                done

                if [ "${1}" = "explode?" ] ; then

                        if [ $[${USED}*100/${CAPACITY}] -ge 95 ] ; then
                                return 0
                        else
                                return 1
                        fi
                elif [ "${1}" = "check" ] ; then
                        echo -e "Capacity = $(echo "scale=2; ${CAPACITY}/1024/1024" | bc)GB\nUsed = $(echo "scale=2; ${USED}/1024/1024" | bc)GB\nAvaliable = $(echo "scale=2; ${FREE}/1024/1024" | bc)GB\nUsage = $(echo "scale=2; ${USED}*100/${CAPACITY}" | bc)%"
                fi
}

请注意在第一个“while”循环中将数据存储在 CAPACITY/USED/FREE vars 中的 2 种不同方法,以及在它之后的 echo 以调试代码。

似乎在运行脚本时,输入到循环变量中的数据没有保存。这是使用“set -x”运行脚本时的输出:

+ CAPACITY=0
+ USED=0
+ FREE=0
+ df
+ grep '/$'
+ read LINE
++ bc
+++ echo /dev/vda1 52417516 8487408 43930108 17% /
+++ awk '{print $2}'
++ echo 0+52417516
+ CAPACITY=52417516
++ echo /dev/vda1 52417516 8487408 43930108 17% /
++ awk '{print $3}'
+ USED=8487408
++ echo /dev/vda1 52417516 8487408 43930108 17% /
++ awk '{print $4}'
+ FREE=43930108
+ read LINE
+ echo -e '0\t0\t0'
0       0       0

为什么即使变量清楚地显示存储了新数字,变量也不存储新数字?

标签: bashshell

解决方案


为什么......即使变量清楚地显示存储了新数字,变量也不存储新数字?

因为右边部分|是在子shell中运行的,所以更改不会传播到父shell。

$ a=1
$ echo a=$a
a=1
$ true | { a=2; echo a=$a; }
a=2
$ echo a=$a
echo a=1

有关更多信息,请阅读bashfaq 我在管道中的循环中设置变量。为什么循环终止后它们会消失?. 常见的解决方案是使用进程替换:

while IFS= read -r line; do
    blabla
done < <( blabla )

$[弃用。改为使用$((...))bash 黑客 wiki 过时和不推荐使用的语法

在 bash 中,只需使用算术扩展((来进行数字比较。if (( used * 100 / capacity >= 96 )); then.

按照惯例,大写变量用于导出变量。对脚本局部变量使用小写的变量名。

不需要grep输出df。只是df /home /etc /var /usr。或者真的只是read -r capacity used free < <(df /home /etc /var /usr | awk '{ capacity += $1; used += $3; free += $4 } END{print capacity, used, free}')


推荐阅读