Bash переменная не сохраняет новые данные? - PullRequest
0 голосов
/ 31 марта 2020

Я написал 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
}

Обратите внимание на 2 различных метода для сохранения данных в переменных CAPACITY / USED / FREE в первом 'while' l oop и эхо сразу после этого для отладки кода.

Похоже, что при запуске скрипта данные, введенные в переменные в l oop, не сохраняются. Вот вывод при запуске сценария с '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

Почему, черт возьми, переменные не хранят новые числа, даже если он ясно показывает, что новое число было сохранено?

1 Ответ

1 голос
/ 31 марта 2020

Почему ... переменные не хранят новые числа, даже если они ясно показывают, что новое число было сохранено?

Поскольку правая часть | запускается в подоболочка, поэтому изменения не распространяются на родительскую оболочку.

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

Для получения дополнительной информации читайте bashfaq Я установил переменные в al oop, который находится в конвейере. Почему они исчезают после завершения l oop? . Распространенным решением является использование замены процесса:

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

$[ устарело. Используйте $((...)) вместо этого. bash хакеры вики устарели и устарели синтаксис .

В bash просто используйте арифметику c расширение (( для сравнения чисел. 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}').

...