linux - tutorial - write bash
Abortando um script de shell se algum comando retorna um valor diferente de zero? (6)
Adicione isto ao começo do script:
set -e
Isso fará com que o shell saia imediatamente se um comando simples sair com um valor de saída diferente de zero. Um comando simples é qualquer comando que não faz parte de um teste if, while ou until, ou parte de um && ou || Lista.
Veja a página man do bash (1) no comando interno "set" para mais detalhes.
Eu pessoalmente começo quase todos os scripts de shell com "set -e". É realmente irritante ter um script teimosamente continuando quando algo falha no meio e quebra as suposições para o resto do script.
Eu tenho um script de shell Bash que invoca um número de comandos. Eu gostaria de ter o script de shell automaticamente sair com um valor de retorno de 1 se qualquer um dos comandos retornar um valor diferente de zero.
Isso é possível sem verificar explicitamente o resultado de cada comando?
por exemplo
dosomething1
if [[ $? -ne 0 ]]; then
exit 1
fi
dosomething2
if [[ $? -ne 0 ]]; then
exit 1
fi
As instruções if no seu exemplo são desnecessárias. Apenas faça assim:
dosomething1 || exit 1
Se você seguir o conselho de Ville Laurikari e usar set -e
então para alguns comandos você pode precisar usar isto:
dosomething || true
O || true
|| true
fará com que o pipeline de comando tenha um true
valor de retorno, mesmo se o comando falhar, então a opção -e
não matará o script.
O $?
variável raramente é necessária. O command; if [ $? -eq 0 ]; then X; fi
pseudo-idiom command; if [ $? -eq 0 ]; then X; fi
command; if [ $? -eq 0 ]; then X; fi
command; if [ $? -eq 0 ]; then X; fi
deve sempre ser escrito como if command; then X; fi
if command; then X; fi
if command; then X; fi
.
Os casos em que $?
é necessário é quando precisa ser verificado em vários valores:
command
case $? in
(0) X;;
(1) Y;;
(2) Z;;
esac
ou quando $?
precisa ser reutilizado ou manipulado:
if command; then
echo "command successful" >&2
else
ret=$?
echo "command failed with exit code $ret" >&2
exit $ret
fi
Para adicionar à resposta aceita:
Tenha em mente que set -e
às vezes não é suficiente, especialmente se você tiver tubos.
Por exemplo, suponha que você tenha esse script
#!/bin/bash
set -e
./configure > configure.log
make
... que funciona como esperado: um erro no configure
anula a execução.
Amanhã você faz uma mudança aparentemente trivial:
#!/bin/bash
set -e
./configure | tee configure.log
make
... e agora não funciona. Isso é explicado here e uma solução alternativa (somente Bash) é fornecida:
#!/bin/bash set -e set -o pipefail ./configure | tee configure.log make
Uma expressão como
dosomething1 && dosomething2 && dosomething3
irá parar o processamento quando um dos comandos retornar com um valor diferente de zero. Por exemplo, o seguinte comando nunca será impresso "concluído":
cat nosuchfile && echo "done"
echo $?
1
apenas jogando em outro para referência, uma vez que havia uma pergunta adicional para a entrada de Mark Edgars e aqui está um exemplo adicional e aborda o tópico em geral:
[[ `cmd` ]] && echo success_else_silence
que é o mesmo que cmd || exit errcode
cmd || exit errcode
como alguém mostrou.
por exemplo. Eu quero ter certeza que uma partição está desmontada se montada:
[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1