Come disabilitare set -e per un singolo comando?


36

Il comando set -e fa fallire immediatamente uno script bash quando un comando restituisce un codice di uscita diverso da zero.

  1. Esiste un modo semplice ed elegante per disabilitare questo comportamento per un singolo comando all'interno di uno script?

  2. In quali luoghi questa funzionalità è documentata nel Manuale di riferimento di Bash ( http://www.gnu.org/software/bash/manual/bashref.html )?

Risposte:


29
  1. Qualcosa come questo:

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

    Correre:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. È descritto nella guida setintegrata:

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

Lo stesso è documentato qui: https://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin .


Grazie! Ho trovato un'altra possibilità: #! / Bin / bash set -e # Scomincia la riga successiva per vedere l'effetto set -e: #blubb se blubb; then echo "Il comando blubb ha avuto successo." else echo "Comando blubb fallito. Codice di uscita: $?" fi eco normale uscita script
Gustave

22

Un'alternativa al disimpegno della cauzione in caso di errore sarebbe quella di forzare un successo, non importa quale. Puoi fare qualcosa del genere:

cmd_to_run || true

Restituirà 0 (vero), quindi il set -e non dovrebbe essere attivato


3
faulty_cmd || :è un altro linguaggio popolare per questo. ( :È anche un comando true).
Ulidtko,

3
@ulidtko - interessante. Mi ha portato nella tana del coniglio per trovare questo stackoverflow.com/questions/3224878/… per ottenere la storia vera vs.:
ernie,

12

Se stai cercando di catturare il codice di ritorno / errore (funzione o fork), questo funziona:

function xyz {
    return 2
}

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

8

Se l'opzione "Esci immediatamente dalla shell" si applica o viene ignorata dipende dal contesto del comando eseguito (vedere la sezione Manuale di riferimento di Bash su Set Builtin - grazie ad Arkadiusz Drabczyk).

In particolare, l'opzione viene ignorata se un comando fa parte del test in un'istruzione if. Pertanto è possibile eseguire un comando e verificarne l'esito positivo o negativo all'interno di un "contesto di uscita immediata" utilizzando un'istruzione if come questa:

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

È possibile omettere l'istruzione "then" e utilizzare meno righe:

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

2

Un altro approccio, che trovo abbastanza semplice (e si applica ad altre setopzioni in aggiunta a -e):

Utilizzare $-per ripristinare le impostazioni.

Per esempio:

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

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

Sebbene in -eparticolare, le opzioni che altri hanno menzionato ( || trueo "messo dentro un if") possono essere più idiomatiche.


0

Recentemente ho avuto una domanda simile (anche se non ho postato, ci sono riuscito) e, da quello che posso vedere, sembra che usare semplicemente set + e prima del comando e set -e successivamente funzioni in modo più elegante. Ecco un esempio, afferrare la risposta del comando e non lasciare che l'errore lo butti via.

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

Questo afferra l'output di "fortuna", controllando il suo stato di uscita, fa eco e lo dice. Penso che questo sia quello che stavi chiedendo, o almeno qualcosa di simile? Spero comunque che questo aiuti.


Per chiarire, il bit tra parentesi ricci che viene reindirizzato a / dev / null è ciò che stai cercando, credo. Fa sì che il comando non abbia alcun output e controlla il suo stato di errore senza uscire dal programma.
Addison Crump,

0

Mi piace avviare subshell se si desidera modificare qualcosa temporaneamente. Il comando seguente mostra che il primo bad_command viene ignorato e il secondo interrompe l'esecuzione.

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.