O que significa `{{(saída 1); saída 1; }; } `significa?

28

Eu citei o próximo trecho de código config.statusgerado por 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

No snippet de código, o que { (exit 1); exit 1; };faz? Qual é o propósito de fazer apenas exitem um subshell?

MS.Kim
fonte

Respostas:

33

Executar (exit 1);é a maneira mais simples de acionar uma ERRarmadilha. Também acionará a saída imediata, se set -eestiver em vigor. (A ativação da condição de erro requer a falha de um comando; exitcom um valor de falha em um subshell faz com que o subshell falhe.)

exit 1; não fará nenhuma dessas coisas.

Portanto, {(exit 1); exit 1;}pode ser usado para produzir primeiro a ERRarmadilha, o que pode ser útil para fins de depuração e, em seguida, finalizar o script com uma indicação de erro.

Mas não é isso que está acontecendo nos autoconfarquivos. autoconfscripts dependem da EXITarmadilha para limpar arquivos temporários criados durante a execução. A maioria dos shells, inclusive bash, definirá o status a partir do valor fornecido no exitcomando antes de chamar a EXITarmadilha. Isso pode permitir que a EXITinterceptação detecte se foi invocada a partir de um erro ou da finalização normal e também garante que o status de saída seja definido corretamente no final da operação de interceptação.

No entanto, aparentemente algumas conchas não cooperam. Aqui está uma citação do autoconfmanual :

Alguns scripts de shell, como os gerados por autoconf, usam uma interceptação para limpar antes de sair. Se o último comando do shell sair com status diferente de zero, a interceptação também sairá com status diferente de zero, para que o invocador possa dizer que ocorreu um erro.

Infelizmente, em alguns shells, como o Solaris /bin/sh, uma armadilha de saída ignora o argumento do comando exit. Nessas shells, uma interceptação não pode determinar se foi invocada pela saída simples ou pela saída 1. Em vez de chamar exit diretamente, use a AC_MSG_ERRORmacro que possui uma solução alternativa para esse problema.

A solução alternativa é garantir que $?tenha o status de saída antes da exitexecução do comando, para que ele definitivamente tenha esse valor quando a EXITinterceptação for executada. E, de fato, é a AC_MSG_ERRORmacro que insere esse código curioso, completo com chaves redundantes.

rici
fonte
Por que não apenas executar em falsevez de (exit 1)?
Ruslan
3
@Ruslan: Dois problemas. (1) Mais importante: falsenão permite definir o código de status e não há garantia de qual status diferente de zero ele retorna. (2) falsegeralmente não é um componente interno, portanto, requer um processo filho; por outro lado, a maioria das conchas pode evitar a criação de uma criança (exit 1).
rici
8

Não há nenhum objetivo para isso, tanto quanto posso ver, não há nada que possa ser alcançado diretamente iniciando um subshell e depois saindo imediatamente.

Coisas como essa provavelmente são um efeito colateral da geração automática de código - em alguns casos, pode haver outros comandos executados no subshell, onde isso exit 1faz sentido. Por fim, existe uma boa chance de que o código de geração seja de alguma forma simplificado, permitindo a inserção de algumas instruções que, em alguns casos, não possuem nenhuma função e gerando 'código limpo' toda vez que for mais complexo. Ou isso ou o código que gerou o texto acima está mal escrito :)

O uso liberal de {...}é outro exemplo disso, a maioria deles é redundante, mas é mais fácil escrever código que os insere em todos os casos (talvez em alguns você queira redirecionar a saída / entrada do bloco) em vez de distinguir o aqueles onde eles não são necessários e os omitem.

Graeme
fonte
Ele tem um propósito. Veja a resposta de @ rici.
Old Pro
1

(exit 1)é uma maneira simples, provavelmente a maneira mais simples de obter um determinado código de saída (no caso especial de 1, existem maneiras mais fáceis, é claro). Mas esse não é o motivo neste caso, pois o código de saída não é examinado.

O objetivo de colocar exitum subshell pode ser não sair do script (embora use exit para a geração de um determinado código de saída).

Hauke ​​Laging
fonte