desenv-web-rp.com

Como fazer algo condicionalmente se um comando tiver êxito ou falha

Como posso fazer algo assim no bash?

if "`command` returns any error";
then
    echo "Returned an error"
else
    echo "Proceed..."
fi
337
Shinmaru

Como fazer algo condicionalmente se um comando tiver êxito ou falha

É exatamente isso que a declaração if do bash faz:

if command ; then
    echo "Command succeeded"
else
    echo "Command failed"
fi

Adicionando informações de comentários: você não precisa usar o [ ... ] sintaxe neste caso. [ é um comando em si, quase equivalente a test. Provavelmente, é o comando mais comum a ser usado em um if, o que pode levar à suposição de que faz parte da sintaxe do Shell. Mas se você quiser testar se um comando foi bem-sucedido ou não, use o próprio comando diretamente com if, como mostrado acima.

413
Keith Thompson

Para pequenas coisas que você deseja que ocorram se um comando do Shell funcionar, você pode usar o && construir:

rm -rf somedir && trace_output "Removed the directory"

Da mesma forma, para pequenas coisas que você deseja que ocorram quando um comando do Shell falha, você pode usar ||:

rm -rf somedir || exit_on_error "Failed to remove the directory"

Ou ambos

rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory"

Provavelmente não é prudente fazer muito com essas construções, mas elas podem ocasionalmente tornar o fluxo de controle muito mais claro.

152
Bruce Ediger

Verifique o valor de $?, que contém o resultado da execução do comando/função mais recente:

#!/bin/bash

echo "this will work"
RESULT=$?
if [ $RESULT -eq 0 ]; then
  echo success
else
  echo failed
fi

if [ $RESULT == 0 ]; then
  echo success 2
else
  echo failed 2
fi
118
Ryan Stewart

Isso funcionou para mim:

command && echo "OK" || echo "NOK"

se command for bem-sucedido, então echo "OK" é executado e, como é bem-sucedido, a execução pára por aí. De outra forma, && é ignorado e echo "NOK" É executado.

52
German Rumm

Note-se que if...then...fi e &&/|| tipo de abordagem lida com o status de saída retornado pelo comando que queremos testar (0 em caso de sucesso); no entanto, alguns comandos não retornam um status de saída diferente de zero se o comando falhar ou não puder lidar com a entrada. Isso significa que os usuais if e &&/|| abordagens não funcionam para esses comandos específicos.

Por exemplo, no Linux GNU file ainda sai com 0 se recebeu um arquivo inexistente como argumento e find não conseguiu localizar o arquivo especificado pelo usuário .

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

Nesses casos, uma maneira potencial de lidar com a situação é lendo as mensagens stderr/stdin, por exemplo aqueles que retornaram pelo comando file ou analisam a saída do comando como em find. Para isso, pode ser usada a instrução case.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found
6
Sergiy Kolodyazhnyy

O mais propenso a erros que eu poderia ter foi:

  • Primeiro, obtenha o valor. Suponha que você faça algo como:

RR=$?

Agora, não apenas para esta situação, mas para outras que você possa enfrentar, considere:

variável definida:

$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi

Resposta: sim

$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi

Resposta: não

variável indefinida:

$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi

Resposta: não

$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi

Resposta: sim

$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi

Resposta: sim

Isso evita todos os tipos de erros.

Você provavelmente conhece toda a sintaxe, mas aqui estão algumas dicas:

  • Use aspas. Evite que "blank" Seja nothing.
  • A nova notação moderna para variáveis ​​é ${variable}.
  • Adicionar um zero concatenado antes do seu número também evita "nenhum número".
  • Mas espere, adicionar um zero faz com que o número se torne base-8. Você receberá um erro como:
    • value too great for base (error token is "08") para números acima de 7. É quando 10# Entra em jogo:
    • 10# Força o número a ser base-10.
4
Dr Beco

Você consegue fazer isso:

if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then
  echo "ping response succsess!!!"
fi
1
Daniel
#!/bin/bash

if command-1 ; then
   echo "command-1 succeeded and now running from this block command-2"
   command-2
else
   echo "command-1 failed and now running from this block command-3"
   command-3
fi
1
Nick Vladiceanu

Como observado em outra parte deste segmento, a pergunta original basicamente se responde. Aqui está uma ilustração mostrando que as condições if também podem ser aninhadas.

Este exemplo usa if para verificar se existe um arquivo e se é um arquivo regular. Se essas condições forem verdadeiras, verifique se o tamanho é ou não maior que 0.

#!/bin/bash

echo "Which error log are you checking today? "
read answer

if [ -f /opt/logs/$answer*.errors ]
    then
        if [ -s /opt/logs/$answer*.errors ]
            then
                echo "Content is present in the $answer error log file."
            else
                echo "No errors are present in the $answer error log file."
        fi
    else
        echo "$answer does not have an error log at this time."
fi
1
quartzinquartz