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

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

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 trecho de código, o que faz { (exit 1); exit 1; };? Qual é o propósito de fazer apenas exitem um subshell?

Responder1

Executar (exit 1);é a maneira mais simples de acionar uma ERRarmadilha. Também acionará a saída imediata se set -eestiver em vigor. (Acionar a 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 primeiro produzir a ERRarmadilha, que pode fazer algo útil para fins de depuração, e então encerrar o script com uma indicação de erro.

Mas não é isso que está acontecendo nos autoconfarquivos. autoconfos scripts dependem da EXITarmadilha para limpar arquivos temporários criados durante a execução. A maioria dos shells, inclusive, bashdefinirá o status a partir do valor fornecido no exitcomando antes de chamar a EXITarmadilha. Isso poderia permitir que a EXITarmadilha detectasse se foi invocada a partir de um erro ou de um encerramento normal, e também permitiria garantir que o status de saída fosse definido corretamente no final da operação da armadilha.

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

Alguns scripts de shell, como os gerados por autoconf, usam uma armadilha para limpar antes de sair. Se o último comando shell tiver saído com status diferente de zero, o trap também sairá com status diferente de zero para que o invocador possa informar que ocorreu um erro.

Infelizmente, em alguns shells, como Solaris /bin/sh, uma interceptação de saída ignora o argumento do comando exit. Nesses shells, um trap não pode determinar se foi invocado pela saída simples ou pela saída 1. Em vez de chamar a saída 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ídaanteso exitcomando é executado, de modo que definitivamente terá esse valor quando a EXITarmadilha for executada. E, de fato, é a AC_MSG_ERRORmacro que insere aquele código curioso, completo com colchetes redundantes.

Responder2

Pelo que posso ver, não há propósito para isso, não há nada que possa ser alcançado diretamente iniciando um subshell e saindo imediatamente.

Coisas como essa são provavelmente um efeito colateral da geração automática de código - em alguns casos, pode haver outros comandos executados no subshell onde exit 1faz sentido ter o. Em última análise, há 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 não têm nenhuma função em alguns casos, e gerar 'código limpo' cada vez é mais complexo. Ou isso ou o código que gerou o acima está mal escrito :)

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

Responder3

(exit 1)é uma maneira simples, provavelmente a 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).

informação relacionada