Citei o próximo trecho de código config.status
gerado 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 exit
em um subshell?
Responder1
Executar (exit 1);
é a maneira mais simples de acionar uma ERR
armadilha. Também acionará a saída imediata se set -e
estiver em vigor. (Acionar a condição de erro requer a falha de um comando; exit
com 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 ERR
armadilha, 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 autoconf
arquivos. autoconf
os scripts dependem da EXIT
armadilha 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 exit
comando antes de chamar a EXIT
armadilha. Isso poderia permitir que a EXIT
armadilha 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 doautoconf
manual:
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 aAC_MSG_ERROR
macro que possui uma solução alternativa para esse problema.
A solução alternativa é garantir que $?
tenha o status de saídaanteso exit
comando é executado, de modo que definitivamente terá esse valor quando a EXIT
armadilha for executada. E, de fato, é a AC_MSG_ERROR
macro 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 1
faz 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 exit
um subshell pode ser não sair do script (embora use exit para a geração de um determinado código de saída).