Pergunta

Eu sou um noob em scripts de shell. Quero imprimir uma mensagem e sair do meu script se um comando falhar. Eu tentei:

my_command && (echo 'my_command failed; exit)

mas não funciona. Ele continua executando as instruções seguindo esta linha no script. Estou usando o Ubuntu e o Bash.

Foi útil?

Solução

Tentar:

my_command || { echo 'my_command failed' ; exit 1; }

Quatro mudanças:

  • Mudar && para ||
  • Usar { } no lugar de ( )
  • Introduzir ; depois exit e
  • espaços depois { e antes }

Como você deseja imprimir a mensagem e sair apenas quando o comando falha (saídas com valor diferente de zero), você precisa de um || não um &&.

cmd1 && cmd2

correrá cmd2 quando cmd1 é bem -sucedido (valor de saída 0). Enquanto

cmd1 || cmd2

correrá cmd2 quando cmd1 falha (valor de saída diferente de zero).

Usando ( ) faz o comando dentro deles correr em um Sub-concha e chamando a exit A partir daí, faz com que você saia da sub-concha e não do seu shell original, portanto, a execução continua no seu shell original.

Para superar este uso { }

As duas últimas alterações são exigidas pelo Bash.

Outras dicas

As outras respostas abordaram bem a pergunta direta, mas você também pode estar interessado em usar set -e. Com isso, qualquer comando que falhe (fora de contextos específicos como if testes) fará com que o script seja abortado. Para certos scripts, é muito útil.

Se você deseja esse comportamento para todos os comandos em seu script, basta adicionar

  set -e 
  set -o pipefail

No início do script. Este par de opções informa ao intérprete Bash para sair sempre que um comando retornar com um código de saída diferente de zero.

No entanto, isso não permite imprimir uma mensagem de saída.

Observe também que o status de saída de cada comando é armazenado na variável shell $?, Que você pode verificar imediatamente após a execução do comando. Um status diferente de zero indica falha:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi

Eu invadi o seguinte idioma:

echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Done."

Preceder cada comando com um eco informativo e siga cada comando com o mesmo
if [ $? -ne 0 ];... linha. (Claro, você pode editar essa mensagem de erro, se quiser.)

Forneceu my_command é projetado canonicamente, ou seja retorna 0 quando é bem -sucedido, então && é exatamente o oposto do que você deseja. Você quer ||.

Observe também isso ( Não me parece certo em Bash, mas não posso tentar de onde estou. Diga-me.

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}

Você também pode usar, se deseja preservar o status de erro de saída e ter um arquivo legível com um comando por linha:

my_command1 || exit $?
my_command2 || exit $?

Isso, no entanto, não imprimirá nenhuma mensagem de erro adicional. Mas, em alguns casos, o erro será impresso pelo comando falhado de qualquer maneira.

o trap O Shell Builtin permite capturar sinais e outras condições úteis, incluindo a execução de comando com falha (ou seja, um status de retorno diferente de zero). Então, se você não quiser testar explicitamente o status de retorno de cada comando, você pode dizer trap "your shell code" ERR e o código do shell será executado sempre que um comando retornar um status diferente de zero. Por exemplo:

trap "echo script failed; exit 1" ERR

Observe que, como em outros casos de captura de comandos falhados, os pipelines precisam de tratamento especial; O acima não vai pegar false | true.

As funções a seguir apenas ecoam erros se um comando falhar:

silently () {
    label="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${label}: ${error}" >&2
        exit 1
    fi
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top