Salve o código de saída para mais tarde

13

Portanto, tenho um pequeno script para executar alguns testes.

javac *.java && java -ea Test
rm -f *.class

Agora, o problema é que quando executo o script ./test , ele retornará um código de saída bem-sucedido, mesmo se o teste falhar porque rm -f *.class foi bem-sucedido.

A única maneira de conseguir fazer o que eu quero é feio para mim:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
if [ "$test_exit_code" != 0 ] ; then false; fi

Mas isso parece um problema comum: executar uma tarefa, limpar e retornar o código de saída da tarefa original.

Qual é a maneira mais idiomática de fazer isso (em bash ou apenas shells em geral)?

    
por math4tots 11.01.2015 / 03:12

3 respostas

5

Você pode agrupar os comandos exit e rm em um único comando simples com eval como:

java ... && java ...
eval "rm -f *.class; exit $?"

Dessa forma, o valor de $? quando passado para exit é o que for atribuído imediatamente antes da execução de eval .

    
por 11.01.2015 / 04:35
20

Eu iria com:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
exit "$test_exit_code"

Por que pular quando exit está disponível?

Você pode usar um trap :

trap 'last_error_code=$?' ERR

Por exemplo:

$ trap 'last_error_code=$?' ERR
$ false
$ echo $?
1
$ echo $last_error_code $?
1 0
    
por 11.01.2015 / 03:20
7

Até onde sei, o mais próximo que o bash tem de um bloco try...finally de uma linguagem de programação mais semelhante ao C (que é o que você provavelmente desejaria se estivesse disponível) é a construção trap , que funciona como isso:

trap "rm -f *.class" EXIT
javac *.java && java -ea Test

Isto irá executar "rm -f * .class" quando o seu script sair. Se você tem algo mais complexo para fazer, você pode colocá-lo em uma função:

cleanup() {
    ...
}
trap cleanup EXIT
javac *.java && java -ea Test

Se você é tão inclinado, você pode transformar isso em um idioma bastante geral que funciona mais ou menos como um bloco try...catch...finally em C. Algo parecido com isto:

(
  trap "catch_block; exit" ERR
  trap finally_block EXIT
  # contents of try goes here
)

Note que os parênteses delimitam uma sub-camada; com essa construção, apenas o subshell é encerrado se um comando falhar, não o script inteiro. Lembre-se que os subshells são computacionalmente caros, então não use muitos (centenas) deles. Dependendo do seu script, você pode conseguir o mesmo efeito de forma mais eficiente com as funções do shell e trap ... RETURN , mas cabe a você investigar.

    
por 11.01.2015 / 10:55