Уникайте запуску сценарію, якщо змінна не визначена


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

Однак користувач повинен надати змінний дзвінок BATCHNUM, інакше мені потрібно змусити цей сценарій перестати працювати. Буде краще, якщо я можу змусити скрипт, який викликає цей скрипт, теж зупинятися (або навіть сценарій №1, який викликає сценарій №2, який викликає цей сценарій).

Відповіді:


30

Найшвидший спосіб - це, мабуть, додати ці два рядки до початку сценарію:

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}"

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, але це тільки я).


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для переривання сценарію, якщо будь-яка команда повертає статус відмови (ненульовий).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.