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

28

Я процитировал следующий фрагмент кода от 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в подоболочке?

MS.Kim
источник

Ответы:

33

Выполнение (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макрос, который вставляет этот любопытный код, дополненный избыточными скобками.

RICi
источник
Почему бы просто не выполнить falseвместо (exit 1)?
Руслан
3
@Ruslan: две проблемы. (1) Самое важное: falseне позволяет вам установить код состояния, и нет никакой гарантии относительно того, какой ненулевой статус он возвращает. (2) falseобычно не является встроенным, поэтому требует дочернего процесса; напротив, большинство снарядов могут избежать порождения ребенка для обработки (exit 1).
Ричи
8

Насколько я понимаю, для этого нет цели, нет ничего, чего можно достичь напрямую, запустив подоболочку, а затем немедленно выйдя из нее.

Подобные вещи, скорее всего, являются побочным эффектом автоматической генерации кода - в некоторых случаях могут быть другие команды, выполняемые в подоболочке, где это exit 1имеет смысл. В конечном счете, есть хороший шанс, что код генерации каким-то образом упростится, позволяя ему вставлять некоторые операторы, которые в некоторых случаях не имеют никакой функции, и генерировать «чистый код» каждый раз сложнее. Либо тот, либо код, сгенерировавший выше, просто плохо написан :)

Либеральное использование {...}является еще одним примером этого, большинство из них являются избыточными, но легче написать код, который вставляет их в каждом случае (может быть, в некоторых вы хотите перенаправить вывод / ввод блока), а не различать те, где они не нужны, и опустите их.

Graeme
источник
У него есть цель. Смотрите ответ @ rici.
Старый Pro
1

(exit 1)это простой, возможно, самый простой способ получить определенный код выхода (в частном случае 1, конечно, есть более простые способы). Но это не причина в этом случае, поскольку код выхода не проверяется.

Цель exitдобавления подоболочки может состоять в том, чтобы не выходить из скрипта (хотя и использует exit для генерации определенного кода выхода).

Хауке Лагинг
источник