Abrufen der vollständigen Befehlszeile, die einen ERR verursacht hat, während Trap

Abrufen der vollständigen Befehlszeile, die einen ERR verursacht hat, während Trap

Wie erstelle ich eine Trap, um den Befehl zurückzugeben, der einen Fehler verursacht hat?

$function err_handler() { echo "$0 caused the error"; }

$ trap err_handler ERR

$ grep -ci "failed" test4 &>/dev/null
-bash caused the error

Ich wollte die Ausgabe wie

grep caused the error

und möglicherweise (gierig genug), die gesamte ersetzte Befehlszeile zu haben. Ist das möglich (ohne Hacks)?

EDIT: Ich entschuldige mich, dass ich nicht erwähnt habe, dass meine Shell KSH ist.

Antwort1

Stellen Sie sicher, dass der Befehlsverlauf aktiviert ist (standardmäßig deaktiviert für nicht interaktive Shells) und verwenden Sie ihn:

#!/bin/bash
set -o history
function trapper () {
    printf "culprit: "
    history 1
}

trap trapper ERR

# your errors go here

Antwort2

Wenn Sie Bash verwenden, können Sie den $BASH_COMMANDParameter verwenden:

BASH_COMMAND
    The command currently being executed or about to be executed, unless
    the shell is executing a command as the result of a trap, in which case
    it is the command executing at the time of the trap.

Einige Anmerkungen: Erstens $BASH_COMMANDerhalten Sie nur den Befehl, der in zusammengesetzten Befehlen fehlgeschlagen ist, nicht die gesamte Befehlszeile.

$ function err_handler { echo "error: $BASH_COMMAND" }
$ trap err_handler ERR
$ true blah blah blah && false herp derp
error: false herp derp

Zweitens schlägt eine Pipeline nur fehl, wenn der letzte Befehl fehlschlägt. Sie ist auch dann erfolgreich, wenn Zwischenbefehle fehlschlagen, der letzte Befehl jedoch erfolgreich ist:

$ echo okay | false herp derp | true lol
# err_handler not called, the last command returned true.

Drittens $BASH_COMMANDgibt Ihnen dienicht analysiertBefehlszeile, daher ist das Erste in der Befehlszeile in ungewöhnlichen Fällen nicht unbedingt der Name des Befehls:

$ false herp derp                       # This is okay.
error: false herp derp
$ {false,herp,derp}                     # An obfuscated way to write `false blah blah`
error: {false,herp,derp}
$ cmd=false
$ $cmd herp derp                        
error: $cmd herp derp

verwandte Informationen