Como desabilitar set -e para um comando individual?

25

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

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

  2. Em quais locais essa funcionalidade está documentada no Manual de referência da Bash ( link )?

por Gustave 14.07.2015 / 17:12

6 respostas

6

Se a opção "sair imediatamente shell" se aplicar ou for ignorada depende do contexto do comando executado (veja Seção do 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 imediatamente" 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
    
por 14.07.2015 / 18:32
26
  1. Algo parecido com isto:

    #!/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
    

    Executar:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
    
  2. Está descrito em set builtin help:

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

O mesmo está documentado aqui: link .

    
por 14.07.2015 / 17:25
16

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

cmd_to_run || true

Isso retornará 0 (verdadeiro), então o set -e não deve ser acionado

    
por 14.07.2015 / 17:36
2

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

function xyz {
    return 2
}

xyz && RC=$? || RC=$?
    
por 09.06.2017 / 23:00
0

Na verdade, eu tive uma pergunta semelhante recentemente (embora eu não tenha postado, cheguei perto disso), e, pelo que eu vejo, parece que apenas usando set + e antes do comando e set -e depois funciona mais elegantemente. 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 pega a saída da 'fortuna', verificando seu status de saída, ecoa e diz. Eu acho que isso é o que você estava pedindo, ou pelo menos algo parecido? De qualquer forma, espero que isso ajude.

    
por 14.07.2015 / 17:30
0

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

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
    
por 09.11.2017 / 13:11

Tags