Прерывание сценария оболочки, если какая-либо команда возвращает ненулевое значение?

Возможно, я в замешательстве, но я считаю, что предварительный пример такой же, как и при замене строк. Поэтому вместо , добавляющего «Hello» в «World», строка «World» может быть добавлена ​​к «Hello»:

const char world[] = "World";
const char hello[] = "Hello";

// Prepend hello to world:
const unsigned int RESULT_SIZE = sizeof(world) + sizeof(hello) + 2 * sizeof('\0');
char * result = malloc(RESULT_SIZE);
if (result)
{
  strcpy(result, hello);
  strcat(result, world);
  puts("Result of prepending hello to world: ");
  puts(result);
  puts("\n");
}

Кроме того, основная трата времени выполнения находит конец строки. Если строки были сохранены с длиной, конец мог бы быть рассчитан быстрее.

389
задан Mat 16 September 2012 в 11:01
поделиться

6 ответов

Добавьте это в начало скрипта:

set -e

Это приведет к немедленному завершению работы оболочки, если простая команда завершится с ненулевым значением выхода. Простая команда - это любая команда, которая не является частью теста if, while или before, или частью && или || list.

Подробнее см. на странице руководства bash (1) внутренней команды «set».

Лично я запускаю почти все сценарии оболочки с помощью «set -e». Это действительно раздражает иметь сценарий упорно продолжать, когда что-то не в предположениях, средних и перерывов для остальной части скрипта.

694
ответ дан 22 November 2019 в 23:38
поделиться

Операторы if в вашем примере не нужны. Просто сделайте это следующим образом:

dosomething1 || exit 1

Если вы прислушаетесь к совету Вилле Лаурикари и используете set -e , то для некоторых команд вам может понадобиться следующее:

dosomething || true

The || true заставит конвейер команд иметь возвращаемое значение true , даже если команда не выполнена, поэтому опция -e не будет уничтожать сценарий.

79
ответ дан 22 November 2019 в 23:38
поделиться

Запустите его с -e или , установите -e вверху.

Также посмотрите на set -u .

12
ответ дан 22 November 2019 в 23:38
поделиться

Выражение типа

dosomething1 && dosomething2 && dosomething3

прекратит обработку, когда одна из команд вернётся с ненулевым значением. Например, следующая команда никогда не напечатает «done»:

cat nosuchfile && echo "done"
echo $?
1
3
ответ дан 22 November 2019 в 23:38
поделиться

If you have cleanup you need to do on exit, you can also use 'trap' with the pseudo-signal ERR. This works the same way as trapping INT or any other signal; bash throws ERR if any command exits with a nonzero value:

# Create the trap with   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah

Or, especially if you're using "set -e", you could trap EXIT; your trap will then be executed when the script exits for any reason, including a normal end, interrupts, an exit caused by the -e option, etc.

27
ответ дан 22 November 2019 в 23:38
поделиться

Переменная $? редко требуется. Команда псевдо-идиома ; если [$? -экв 0]; затем X; fi всегда следует записывать как if command; затем X; fi .

Случаи, когда требуется $? , - это когда его нужно проверить по нескольким значениям:

command
case $? in
  (0) X;;
  (1) Y;;
  (2) Z;;
esac

или когда $? необходимо повторно использовать или иначе манипулируют:

if command; then
  echo "command successful" >&2
else
  ret=$?
  echo "command failed with exit code $ret" >&2
  exit $ret
fi
11
ответ дан 22 November 2019 в 23:38
поделиться