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 




shell