Назад | Перейти на главную страницу

Если оператор Redhat Shell Script завершается неудачно с нечетной синтаксической ошибкой

Redhat 5.3 Enterprise

Следующий сценарий оболочки используется для проверки, имеет ли каталог резервного копирования имя «ll_backup», а затем изменяет его, чтобы он соответствовал содержимому файла RESULT.VAR. Файл result.var копируется для целей журнала в другой каталог. У меня это работало в тестовой среде, но в процессе производства это привело к странной ошибке, которую я не могу понять!

СЦЕНАРИЙ:

#!/bin/bash
#!/bin/cat
# Restores original directory name for next LogLogic Update
#TCJ 6/1/09
declare RESULT
declare FILE
FILE=result.var
cd /home/nb-backup/backups/nb-st3000/ll_bkup_65.99.220.172/
if [ -d ll_bkup ]
 then
        cat result.var | while IFS=: read RESULT
        mv  "ll_bkup" "$RESULT"
        mv result.var /home/storegrid/scripts/results/result-`date +%y%m%d%s`.var
else
         exit 0
fi
exit 0

РЕЗУЛЬТАТ:

nb-script-restorellbackup.sh: строка 14: синтаксическая ошибка около неожиданного токена else' nb-script-restorellbackup.sh: line 14:еще '

Есть ряд проблем, от незначительных до фатальных (все фатальные связаны со строкой «кот ... пока ... читал»). Разрешите мне пройти их по порядку:

  • Как заметил Деннис Уильямсон, строки «#! / Bin / cat» и «declare ...» ничего не делают.
  • Вы устанавливаете FILE в result.var вверху, но никогда не используете эту переменную. Предполагая, что он предназначен для того, чтобы вы могли изменить имя файла только в одном месте, вам следует заменить все остальные ссылки на result.var на «$ FILE»
  • Оператору while требуется «do ... done» - или, скорее, это было бы, если бы вам вообще-то понадобился оператор while. Поскольку вы читаете только один РЕЗУЛЬТАТ из файла, вам не нужен цикл.
  • Поскольку «read RESULT» является частью конвейера, он выполняется в подоболочке, и значение RESULT, которое он устанавливает, теряется при выходе из этой подоболочки. Вы можете исправить это, используя что-то вроде 'read RESULT <"$ FILE"'.
  • Для чего там бит "IFS =:"? Он устанавливает внутренний разделитель полей на ":" на время выполнения команды чтения, но, поскольку вы читаете только одно поле (РЕЗУЛЬТАТ), единственное, что он делает, - это обрезать начальные или конечные двоеточия из того, что читается из result.var . Если вы хотели игнорировать все, что находится после двоеточия (т.е. использовать только первое поле, разделенное двоеточиями из result.var), вы должны вместо этого использовать «IFS =: read RESULT IGNOREDJUNK».
  • Если вы на самом деле не пытаетесь обрезать / анализировать содержимое result.var или вам не нужно использовать его несколько раз, вам вообще не нужно читать его в переменной; просто используйте 'mv "ll_bkup" "$ (cat" $ FILE ")"'. Но я утверждаю, что вы хотите использовать его снова (см. Ниже).
  • Сценарий довольно хрупок в том смысле, что он не проверяет, существует ли result.var (и поскольку сценарий перемещает этот файл, при запуске дважды подряд он гарантированно завершится неудачно во второй раз); аналогично, он не проверяет, существует ли уже «$ RESULT» перед попыткой переименовать его в ll_bkup, что приводит к потенциально непредсказуемым результатам.
  • Говоря об этом, в вашем описании говорится, что result.var копируется, но фактический код перемещает его. Какое предполагаемое поведение?
  • Наконец, секция «else ... exit 0» не делает ничего такого, что не делает «exit 0» в конце.

Gripe, gripe, gripe ... в общем, вот моя предлагаемая переписать:

#!/bin/bash
# Restores original directory name for next LogLogic Update
#TCJ 6/1/09
FILE=result.var
cd /home/nb-backup/backups/nb-st3000/ll_bkup_65.99.220.172/
if [ -d ll_bkup -a -f "$FILE" ]; then
    read RESULT <"$FILE"
    if [ ! -e "$RESULT" ]; then
        mv  "ll_bkup" "$RESULT"
        mv "$FILE" /home/storegrid/scripts/results/result-`date +%y%m%d%s`.var
    fi
fi
exit 0

Вам нужно изменить строку, чтобы она выглядела так:

cat result.var | while IFS=:; do read RESULT; done

это cat и read мне кажется, что он устанавливает $ RESULT равным первому слову последней строки содержимого файла "result.var"

и удалите эту строку:

#!/bin/cat

поскольку он ничего не делает.

Вам действительно не нужно использовать declare в этой ситуации.

Использовать $() вокруг вашей команды даты. Он более читабелен и при необходимости может быть более легко вложен.

Что происходит с циклом while? Это нужно do ... done где-то.

Вот вам несколько справочных материалов: