Переменная не распознается после «чтения» - PullRequest
0 голосов
/ 13 сентября 2018

- Редактировать: Решено.См. Ответ.

Справочная информация: я пишу оболочку, которая будет выполнять некоторые дополнительные действия, необходимые в нашей системе, когда кто-то изменяет размер базы данных.Оболочка написана на ksh (требование), ОС Solaris 5.10.Проблема в одной из проверок, которая проверяет, достаточно ли свободного места в базовой ОС.

Проблема: проверка считывает строку df -k для root, что я проверяю на этом шаге, и печатаетэто в файл.Затем я «читаю» содержимое в переменные, которые я использую в расчетах.К сожалению, когда я пытаюсь выполнить арифметическую операцию с одной из переменных, я получаю сообщение об ошибке, указывающее, что оно равно нулю.И строка выходных данных отладки, которую я поместил после этой строки, проверяет, что она является нулевой ... Она потеряла свое значение ...

Я пробовал каждый способ сделать это, я мог найти в Интернете, они работают, когдаЯ запускаю его вручную, но не внутри файла оболочки.(* Файл имеет #! / Usr / bin / ksh)

Код:

df -k | grep "rpool/ROOT" > dftest.out  
RPOOL_NAME=""; declare -i TOTAL_SIZE=0; USED_SPACE=0; AVAILABLE_SPACE=0; AVAILABLE_PERCENT=0; RSIGN=""  
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out  
\rm dftest.out  
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN  
((TOTAL_SIZE=$TOTAL_SIZE/1024))  

Это результат:
DBResize.sh [11]: TOTAL_SIZE = /1024: синтаксическая ошибка

В этот момент я дергаю за волосы, любая помощь будет признательна.

Ответы [ 3 ]

0 голосов
/ 15 сентября 2018

Странно ... когда я избавляюсь от вашей строки "объявить", ваш оригинальный код, кажется, работает отлично (по крайней мере, с ksh в Linux)

код:

#!/bin/ksh

df -k | grep "/home" > dftest.out
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out
\rm dftest.out

echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=$TOTAL_SIZE/1024))
print $TOTAL_SIZE

Результат:

32962416 5732492 25552588 19% /home
5598

Какое значение возвращает простой df -k. Переменные, похоже, сохраняются.

0 голосов
/ 15 сентября 2018

Код, который вы опубликовали, не может создать вывод, который вы опубликовалиОчевидно, что об ошибке сообщается в строке 11, но вы разместили менее 11 строк кода.Предыдущие строки могут иметь значение.Всегда отправляйте полный код , когда вы просите о помощи.

Более конкретно, команда declare не существует в ksh, это вещь bash.Вы можете достичь того же результата с помощью typeset (declare - это bash, эквивалентный typeset, но не все опции одинаковы).Либо вы выполняете этот скрипт с bash, либо есть другое сообщение об ошибке declare, либо вы определили некоторые дополнительные команды, включая declare, которые могут изменить поведение этого кода.

Ничего из этогооднако, это должно повлиять на конкретную проблему, о которой вы пишете.Переменные, созданные с помощью read, остаются назначенными до конца подоболочки, то есть до тех пор, пока код не достигнет ), конца канала (левая часть канала только в ksh) и т. Д.

Что касается использования declare или typeset, обратите внимание, что вы объявляете только TOTAL_SIZE как целое число.Для других переменных вы просто присваиваете значение, которое состоит исключительно из цифр.Это не имеет значения для кода, который вы разместили, но, вероятно, это не то, что вы имели в виду.

Одна вещь, которая может происходить, это то, что grep ничего не соответствует, и поэтому read читает пустую строку.Вы должны проверить на ошибки.Используйте set -e в скриптах для выхода при первой ошибке.(Есть случаи, когда set -e не перехватывает ошибки, но это хорошее начало.)

Еще одна вещь, которая может произойти, это то, что df разбивает свой вывод на несколько строк, потому что первый столбец, содержащийимя файловой системы слишком велико.Чтобы предотвратить это разделение, передайте опцию -P.

Использование временного файла хрупко: код может выполняться в каталоге только для чтения, другой процесс может захотеть получить доступ к тому же файлу одновременно... Здесь временный файл бесполезен.Просто направьте трубку прямо в read.В ksh (в отличие от большинства других вариантов sh, включая bash), правая часть трубы проходит в основной оболочке, поэтому назначения переменных в правой части трубы остаются доступными в следующих командах.

Это не имеет значения в этом конкретном скрипте, но вы можете использовать переменную без $ в арифметическом выражении.Использование $ заменяет строку, которая может привести к сбивающим с толку результатам, например, a='1+2'; $((a*3)) расширяется до 7.Если не использовать $, используется числовое значение (в ksh a='1+2'; $((a*3)) расширяется до 9; в некоторых реализациях sh вы получаете ошибку, поскольку значение a не является числовым).

#!/usr/bin/ksh
set -e
typeset -i TOTAL_SIZE=0 USED_SPACE=0 AVAILABLE_SPACE=0 AVAILABLE_PERCENT=0
df -Pk | grep "rpool/ROOT" | read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN  
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN  
((TOTAL_SIZE=TOTAL_SIZE/1024))
0 голосов
/ 14 сентября 2018

Для тех, кто заинтересован, я понял, что невозможно использовать «читать» так, как я это использовал.
Значения переменных, присвоенные «read», просто «not last».
Чтобы исправить это, я применил далеко не идеальное решение использования стандартного формата «пока читалось», и внутри цикла выводил выбранные переменные в файл переменных.
Как только указанный файл был создан, я просто «загрузил» его.

(псевдокод :)

LOOP START
echo "VAR_A="$VAR_A"; VAR_B="$VAR_B";" > somefile.out
LOOP END
. somefile.out
...