O que faz '{{(exit 1); saída 1; }; }' significar?

30

Eu citei o próximo trecho de código de 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 snippet de código, o que { (exit 1); exit 1; }; faz? Qual é o propósito de fazer apenas exit em uma subshell?

    
por MS.Kim 15.06.2014 / 17:11

3 respostas

34

A execução de (exit 1); é a maneira mais simples de acionar uma interceptação ERR . Ele também acionará a saída imediata se set -e estiver em vigor. (Disparar a condição de erro requer um comando para falhar; exit com um valor de falha em uma subshell faz com que a subshell falhe).

exit 1; não fará nada disso.

Portanto, {(exit 1); exit 1;} pode ser usado para produzir primeiro a ERR trap, que pode fazer algo útil para propósitos de depuração, e então terminar o script com uma indicação de erro.

Mas não é isso que está acontecendo em autoconf arquivos. Os scripts autoconf confiam no EXIT trap para limpar os arquivos temporários criados durante a execução. A maioria dos shells, incluindo bash , definirá o status do valor fornecido no comando exit antes de chamar o EXIT trap. Isso pode permitir que a interceptação EXIT detecte se foi invocada por um erro ou por finalização normal, e também permite garantir 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 autoconf manual :

Some shell scripts, such as those generated by autoconf, use a trap to clean up before exiting. If the last shell command exited with nonzero status, the trap also exits with nonzero status so that the invoker can tell that an error occurred.

Unfortunately, in some shells, such as Solaris /bin/sh, an exit trap ignores the exit command's argument. In these shells, a trap cannot determine whether it was invoked by plain exit or by exit 1. Instead of calling exit directly, use the AC_MSG_ERROR macro that has a workaround for this problem.

A solução alternativa é certificar-se de que $? tenha o status de saída antes de executar o comando exit , para que ele tenha definitivamente esse valor quando a EXIT trap for executada. E, de fato, é a macro AC_MSG_ERROR que insere esse código curioso, completo com chaves redundantes.

    
por 16.06.2014 / 00:26
8

Não há nenhum propósito para isso, até onde eu posso ver, não há nada que possa ser alcançado diretamente iniciando uma sub-rede e então saindo imediatamente.

Coisas como esta provavelmente são um efeito colateral de gerar código automaticamente - em alguns casos, pode haver outros comandos executados no subshell onde ter o exit 1 faz sentido. Em última análise, há uma boa chance de que o código de geração seja de alguma forma simplificado, permitindo que ele insira algumas instruções que não têm nenhuma função em alguns casos e que gerar código limpo sempre é mais complexo. Ou isso ou o código que gerou o acima é apenas mal escrito:)

O uso liberal de {...} é outro exemplo disso, a maioria deles é redundante, 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 ) em vez de distinguir aqueles onde não são necessários e omiti-los.

    
por 15.06.2014 / 17:27
1

(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 essa não é a razão neste caso, pois o código de saída não é examinado.

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

    
por 15.06.2014 / 20:32