Come attivare l'errore usando il comando Trap


13

Sto usando Ubuntu 12.04.2. Sto cercando di utilizzare il comando "trap" per acquisire anomalie o errori nel mio script di shell, ma sto anche cercando di attivare manualmente l'uscita "Errore".

Ho provato l'uscita 1, ma non attiverà il segnale "Errore".

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

Non sei sicuro di come attivare manualmente il segnale di uscita "Errore"?

Risposte:


20

la ERRtrap non deve eseguire il codice quando la shell stessa esce con un codice di errore diverso da zero, ma quando qualsiasi comando eseguito da quella shell che non fa parte di una condizione (come in if cmd..., o cmd || ......) termina con un valore diverso da zero stato di uscita (stesse condizioni di ciò che provoca set -el'uscita dalla shell).

Se si desidera eseguire il codice all'uscita della shell con stato di uscita diverso da zero, è necessario aggiungere una trap EXITe verificare $?lì:

trap '[ "$?" -eq 0 ] || echo hi' EXIT

Si noti tuttavia che su un segnale in trappola, verrebbero eseguite sia la trappola del segnale sia la trappola EXIT, quindi si consiglia di farlo come segue:

unset killed_by
trap 'killed_by=INT;exit' INT
trap 'killed_by=TERM;exit' TERM
trap '
  ret=$?
  if [ -n "$killed_by" ]; then
    echo >&2 "Ouch! Killed by $killed_by"
    exit 1
  elif [ "$ret" -ne 0 ]; then
    echo >&2 "Died with error code $ret"
  fi' EXIT

O per utilizzare lo stato di uscita come $((signum + 128))sui segnali:

for sig in INT TERM HUP; do
  trap "exit $((128 + $(kill -l "$sig")))" "$sig"
done
trap '
  ret=$?
  [ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"' EXIT

Si noti tuttavia che uscire normalmente da SIGINT o SIGQUIT ha potenziali effetti collaterali fastidiosi quando il processo genitore è una shell del genere bashche implementa l' attesa e la gestione cooperativa dell'uscita dell'interrupt di terminale. Quindi, potresti voler assicurarti di ucciderti con lo stesso segnale invece di riferire al tuo genitore che sei stato effettivamente interrotto e che dovrebbe prendere in considerazione di uscire anche se ha ricevuto un SIGINT / SIGQUIT.

unset killed_by
for sig in INT QUIT TERM HUP; do
  trap "exit $((128 + $(kill -l "$sig"))); killed_by=$sig" "$sig"
done
trap '
  ret=$?
  [ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"
  if [ -n "$killed_by" ]; then
    trap - "$killed_by" # reset handler
    # ulimit -c 0 # possibly disable core dumps
    kill -s "$killed_by" "$$"
  else
    exec "$ret"
  fi' EXIT

Se vuoi che la ERRtrap si attivi, esegui un comando con uno stato di uscita diverso da zero come falseo test.


6

Usa ritorno, non uscire, per impostare lo stato all'uscita da una funzione (se la funzione cade passante senza un ritorno, lo stato è quello dell'ultimo istruzione eseguita.) Se si sostituisce returnper exitnell'esempio della domanda, funzionerà come Penso che tu abbia voluto: la trappola verrà attivata sullo pseudo-segnale ERR e verrà stampato "ciao". Per ulteriori considerazioni, prova questo:

#!/bin/bash

func()
{
    echo 'in func'
    return 99
    echo 'still in func'
}

trap 'echo "done"' EXIT
trap 'status=$?; echo "error status is $status"; trap - EXIT; exit $status' ERR
func
echo 'returned from func'

È possibile provare varie modifiche, come restituire 0, commentare la trap ERR, non annullare la trap EXIT all'interno del gestore ERR, non uscire dal gestore ERR o rimuovere il ritorno e inserire falsecome ultima istruzione in func.

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.