cmd && echo "$?"
nie działałby, ponieważ z konieczności drukowałby tylko zera ( echo
działałby tylko po pomyślnym zakończeniu poprzedniego polecenia).
Oto funkcja krótkiej powłoki:
tellexit () {
"$@"
local err="$?"
printf 'exit code\t%d\n' "$err" >/dev/tty
return "$err"
}
Spowoduje to wydrukowanie kodu wyjścia danego polecenia w podobny sposób jak time
polecenie.
$ tellexit echo "hello world"
hello world
exit code 0
$ tellexit false
exit code 1
Przez przekierowanie printf
do /dev/tty
w funkcji, możemy nadal korzystać tellexit
z przekierowań bez uzyskiwania śmieci w naszych standardowych strumieni wyjściowych lub błędach:
$ tellexit bash -c 'echo hello; echo world >&2' >out 2>err
exit code 0
$ cat out
hello
$ cat err
world
Zapisując kod wyjścia w zmiennej, możemy zwrócić go wywołującemu:
$ tellexit false || echo 'failed'
exit code 1
failed
Bardziej zaawansowana wersja tej samej funkcji drukuje również sygnał, który zabił polecenie, jeśli kod wyjścia jest większy niż 128 (co oznacza, że został zakończony z powodu sygnału):
tellexit () {
"$@"
local err="$?"
if [ "$err" -gt 128 ]; then
printf 'exit code\t%d (%s)\n' "$err" "$(kill -l "$err")" >/dev/tty
else
printf 'exit code\t%d\n' "$err" >/dev/tty
fi
return "$err"
}
Testowanie:
$ tellexit sh -c 'kill $$'
exit code 143 (TERM)
$ tellexit sh -c 'kill -9 $$'
Killed
exit code 137 (KILL)
( local
Rzecz wymaga ash
/ pdksh
/ bash
/ zsh
, lub możesz to zmienić, na typeset
co rozumie także kilka innych powłok).
sleep 1 && echo $?
wydrukowałby kod komórki sypialnej tylko wtedy, gdy będzie zero ...