Что означает `{ { (выход 1); выход 1; }; }`?

Что означает `{ { (выход 1); выход 1; }; }`?

Я процитировал следующий фрагмент кода, 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подоболочки может быть не выход из скрипта (хотя и использование выхода для генерации определенного кода выхода).

Связанный контент