Я процитировал следующий фрагмент кода, config.status
сгенерированный configure
.
if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
В фрагменте кода, что делает { (exit 1); exit 1; };
? Какова цель делать только exit
в подоболочке?
решение1
Выполнение (exit 1);
— самый простой способ вызвать ERR
ловушку. Оно также вызовет немедленный выход, если set -e
действует. (Вызов состояния ошибки требует, чтобы команда не была выполнена; exit
при значении сбоя в подоболочке подоболочка завершается сбоем.)
exit 1;
не будет делать ни того, ни другого.
Поэтому его {(exit 1); exit 1;}
можно использовать для того, чтобы сначала создать ERR
ловушку, которая может сделать что-то полезное для отладки, а затем завершить скрипт с указанием ошибки.
Но это не то, что происходит в autoconf
файлах. autoconf
Скрипты полагаются на EXIT
ловушку, чтобы очищать временные файлы, созданные во время выполнения. Большинство оболочек, включая , bash
устанавливают статус из значения, предоставленного в exit
команде, перед вызовом EXIT
ловушки. Это может позволить EXIT
ловушке определить, была ли она вызвана из-за ошибки или из-за нормального завершения, а также позволяет гарантировать, что статус выхода установлен правильно в конце операции ловушки.
Однако, по-видимому, некоторые снаряды не взаимодействуют. Вот цитата изautoconf
руководство:
Некоторые скрипты оболочки, например, те, что сгенерированы
autoconf
, используют ловушку для очистки перед выходом. Если последняя команда оболочки завершилась с ненулевым статусом, ловушка также завершается с ненулевым статусом, чтобы вызывающий мог определить, что произошла ошибка.К сожалению, в некоторых оболочках, таких как Solaris
/bin/sh
, ловушка выхода игнорирует аргумент команды выхода. В этих оболочках ловушка не может определить, была ли она вызвана простым выходом или выходом 1. Вместо того, чтобы вызывать выход напрямую, используйте макрос,AC_MSG_ERROR
который имеет обходной путь для этой проблемы.
Обходной путь — убедиться, что $?
имеет статус выходадокоманда exit
выполняется, так что она определенно будет иметь это значение, когда ловушка EXIT
будет выполнена. И, действительно, это макрос AC_MSG_ERROR
, который вставляет этот любопытный код, полный избыточных скобок.
решение2
Насколько я понимаю, в этом нет никакой цели, и ничего нельзя добиться напрямую, запустив подоболочку и немедленно завершив ее работу.
Такие вещи, скорее всего, являются побочным эффектом автоматической генерации кода - в некоторых случаях могут быть другие команды, выполняемые в подоболочке, где наличие имеет смысл exit 1
. В конечном счете, есть большая вероятность, что код генерации каким-то образом упрощается, позволяя ему вставлять некоторые операторы, которые в некоторых случаях не имеют никакой функции, а генерация "чистого кода" каждый раз становится более сложной. Либо это, либо код, который сгенерировал выше, просто плохо написан :)
Другим примером является свободное использование {...}
, большинство из них избыточны, но проще написать код, который вставляет их в каждом случае (возможно, в некоторых случаях вы захотите перенаправить вывод/ввод блока), чем выделять те, где они не нужны, и опускать их.
решение3
(exit 1)
это простой, вероятно, самый простой способ получить определенный код выхода (в частном случае 1 есть более простые способы, конечно). Но это не причина в данном случае, так как код выхода не проверяется.
Целью помещения exit
подоболочки может быть не выход из скрипта (хотя и использование выхода для генерации определенного кода выхода).