Избегайте запуска скрипта, если переменная не определена

18

У меня скрипт выглядит так:

c=0
for f in */*; do
cp -v "$f" "/myhome/CE$(printf '%0*d' 2 $BATCHNUM)-new-stuctures_extracted/test-$(printf '%0*d' 5 $c)"
c=$((c=c+1))
done

Тем не менее, пользователь должен предоставить переменную call BATCHNUM, в противном случае мне нужно заставить этот скрипт перестать работать. Было бы лучше, если бы я мог принудительно остановить скрипт, который вызывает этот скрипт (или даже скрипт # 1, который вызывает скрипт # 2, который вызывает этот скрипт).

user40780
источник

Ответы:

28

Возможно, самый быстрый способ - добавить эти две строки в начало скрипта:

set -u # or set -o nounset
: "$BATCHNUM"

Первая строка устанавливает nounsetпараметр в оболочке, выполняющей скрипт, который прерывается, если вы пытаетесь раскрыть неустановленную переменную; вторая расширяется $BATCHNUMв контексте бездействия, чтобы вызвать прерывание, прежде чем делать что-либо еще.

Если вы хотите более полезное сообщение об ошибке, вы можете написать:

if [[ -z "$BATCHNUM" ]]; then
    echo "Must provide BATCHNUM in environment" 1>&2
    exit 1
fi

Или похожие.

Том Хант
источник
18

Здесь вы хотите проверить BATCHNUM , установлен ли, а не нуль.

Оболочка POSIX обеспечивает расширение параметров для этой работы. Просто добавьте эту строку перед использованием BATCHNUM:

: "${BATCHNUM:?Variable not set or empty}"

или лучше установить значение по умолчанию, BATCHNUMесли пользователь не предоставил его:

: "${BATCHNUM:=3}"
cuonglm
источник
4
[ -n "$BATCHNUM" ] || { kill "$PPID"; exit 1; }
#Unless $BATCHNUM is defined and unempty, ask parent process to exit and exit w/ 1

Это будет работать на bash и в POSIX sh. Я предпочитаю не делать различий между пустыми переменными и неопределенными переменными (то есть мне не нравится set -u, но это только я).

PSkocik
источник
2

Линии

if [ -z "$BATCHNUM" ]; then
    exit 2;
fi

проверить на пустое $BATCHNUM. С $PPIDего помощью вы можете причинить любой вред вашему родителю ( kill $PPID). Чтобы убить вашего деда, вам нужно получить идентификатор процесса другими способами, например, просмотреть данные в /proc/$PPID.

Однако, если ваш родитель умирает, он посылает вам сигнал ( SIGHUP), так что вы должны перехватить его, прежде чем начать кого-либо убивать:

trap '' SIGHUP

Обновление: если вы думаете, что должны убить своих родителей, вы делаете это неправильно. Просто верните значимый код выхода. Родительский скрипт должен проверять код возврата вызываемого скрипта и реагировать соответствующим образом.

Томас Эркер
источник
1
немного брутально .... :)
user40780
1

Чтобы проверить, BATCHNUMопределено ли это, и выйдите, если это не так:

if [ -n "${BATCHNUM-a}" ]; then
  echo >&2 "Fatal error: BATCHNUM not set"
  exit 2
fi

Если вы также хотите отклонить случай, когда BATCHNUMпусто, используйте ${BATCHNUM:+a}вместо ${BATCHNUM+a}. Для получения информации о ${VARIABLE+TEXT_IF_NULL}конструкции расширения параметров см., Например, руководство по bash. .

Не убивайте родительский процесс. Вы не знаете, что такое родительский процесс. Если какой-либо скрипт, вызывающий этот скрипт, должен прервать работу, если этот скрипт прерывается, заставьте его проверить состояние завершения этого скрипта. Например, в сценарии № 2:

script3 || exit $?

или используйте set -eдля отмены сценария, если какая-либо команда возвращает статус ошибки (ненулевой).

Жиль "ТАК - прекрати быть злым"
источник