Como desativar set -e para um comando individual?


36

O comando set -e faz com que um script bash falhe imediatamente quando qualquer comando retorna um código de saída diferente de zero.

  1. Existe uma maneira fácil e elegante de desativar esse comportamento para um comando individual em um script?

  2. Em que lugares essa funcionalidade está documentada no Manual de Referência do Bash ( http://www.gnu.org/software/bash/manual/bashref.html )?

Respostas:


29
  1. Algo assim:

    #!/usr/bin/env bash
    
    set -e
    echo hi
    
    # disable exitting on error temporarily
    set +e
    aoeuidhtn
    echo next line
    
    # bring it back
    set -e
    ao
    
    echo next line

    Corre:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. Está descrito na setajuda integrada:

    $ type set
    set is a shell builtin
    $ help set
    (...)
    Using + rather than - causes these flags to be turned off.

O mesmo está documentado aqui: https://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin .


Obrigado! Encontrei outra possibilidade: #! / Bin / bash set -e # Descomente a próxima linha para ver o efeito set -e: #blubb if blubb; então ecoa "O comando blubb foi bem-sucedido". else echo "O comando blubb falhou. Código de saída: $?" saída de script normal de eco de fi
Gustave

22

Uma alternativa para desabilitar a fiança por erro seria forçar um sucesso, não importa o quê. Você pode fazer algo assim:

cmd_to_run || true

Isso retornará 0 (verdadeiro), para que o set -e não seja acionado


3
faulty_cmd || :é outro idioma popular para isso. (O :comando é sinônimo de true).
ulidtko

3
@ulidtko - interessante. Me levou para baixo o coelho para encontrar este stackoverflow.com/questions/3224878/... para obter a história na verdade vs.:
Ernie

12

Se você está tentando capturar o código de retorno / erro (função ou bifurcação), isso funciona:

function xyz {
    return 2
}

xyz && RC=$? || RC=$?

8

Se a opção "sair imediatamente do shell" se aplicar ou for ignorada, depende do contexto do comando executado (consulte a seção Manual de Referência do Bash no Set Builtin - graças a Arkadiusz Drabczyk).

Especialmente, a opção é ignorada se um comando fizer parte do teste em uma instrução if. Portanto, é possível executar um comando e verificar seu sucesso ou falha em um "contexto de saída imediata" usando uma instrução if como esta:

#!/bin/bash

set -e

# Uncomment next line to see set -e effect:
#blubb

if blubb; then
  echo "Command blubb was succesful."
else 
  echo "Command blubb failed. Exit code: $?"
fi
echo "Script exited normally."

É possível omitir a instrução "then" e usar menos linhas:

if blubb; then :;
else echo "Command blubb failed. Exit code: $?"; fi

2

Outra abordagem, que considero bastante direta (e se aplica a outras setopções além de -e):

Utilize $-para restaurar as configurações.

Por exemplo:

oldopt=$-
set +e
# now '-e' is definitely disabled.
# do some stuff...

# Restore things back to how they were
set -$oldopt

Embora -e, especificamente, as opções que outros tenham mencionado ( || trueou "colocado dentro de um if") possam ser mais idiomáticas.


0

Na verdade, tive uma pergunta semelhante recentemente (embora não tenha postado, cheguei a ela) e, pelo que posso ver, parece que apenas use set + e antes do comando e set -e depois funcionem com mais elegância. Aqui está um exemplo, pegando a resposta do comando e não deixando o erro jogá-lo fora.

#!/bin/sh

args=""
for argcol in $*
do
    args="${args} ${argcol}"
done
fortunevar=""
fortfail=""
{
    set +e
    fortunevar=`fortune $args`
    fortfail=$?
    set -e
} &> /dev/null
if [ $fortfail == 0 ]
then
    echo ${fortunevar}
    say ${fortunevar}
else
    echo misfortune: an illegal option was detected!
    echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all]
fi

Isso agarra a saída da 'fortuna', verificando seu status de saída, ecoando e dizendo isso. Eu acho que é isso que você estava pedindo, ou pelo menos algo parecido? Enfim, espero que isso ajude.


Para esclarecer, o que está entre os parênteses encaracolados sendo redirecionados para / dev / null é o que você procura, acredito. Faz com que o comando não tenha saída e verifica seu status de erro sem sair do programa.
Addison Crump

0

Eu gosto de começar o subshell se quiser mudar algo temporariamente. O comando abaixo demonstra que o primeiro bad_command é ignorado e o segundo interrompe a execução.

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.