Es ist gut, den letzten falschen Kommentar zu haben, um ihn zu korrigieren, aber kurz danach wird es möglicherweise zu einem verwirrenden Müll.
Mein Ansatz besteht aus zwei Schritten: Speichern Sie fehlgeschlagene Befehle und entfernen Sie sie später.
Speichern Sie Befehle, bei denen ein Fehler auftritt:
error_handler() {
FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}
trap error_handler ERR
trap command signals
wird ausgeführt, command
wenn einer von signals
"ausgelöst" wird.
$(command)
, führt das aus command
und erfasst seine Ausgabe.
Wenn der Befehl fehlschlägt, erfasst dieses Codefragment die Verlaufsnummer des zuletzt im Verlauf gespeicherten Befehls und speichert sie in einer Variablen zum späteren Löschen.
Einfach, funktioniert aber nicht richtig mit HISTCONTROL
und HISTIGNORE
- Wenn der Befehl aufgrund einer der Variablen nicht im Verlauf gespeichert wird, ist die Verlaufsnummer des zuletzt im Verlauf gespeicherten Befehls die Nummer des vorherigen Befehls. Wenn also ein falscher Befehl nicht im Verlauf gespeichert wird, wird der vorherige Befehl gelöscht.
Etwas kompliziertere Version, die in diesem Fall korrekt funktioniert:
debug_handler() {
LAST_COMMAND=$BASH_COMMAND;
}
error_handler() {
local LAST_HISTORY_ENTRY=$(history | tail -1l)
# if last command is in history (HISTCONTROL, HISTIGNORE)...
if [ "$LAST_COMMAND" == "$(cut -d ' ' -f 2- <<< $LAST_HISTORY_ENTRY)" ]
then
# ...prepend it's history number into FAILED_COMMANDS,
# marking the command for deletion.
FAILED_COMMANDS="$(cut -d ' ' -f 1 <<< $LAST_HISTORY_ENTRY) $FAILED_COMMANDS"
fi
}
trap error_handler ERR
trap debug_handler DEBUG
Gespeicherte Befehle später entfernen:
exit_handler() {
for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
do
history -d $i
done
FAILED_COMMANDS=
}
trap exit_handler EXIT
Erläuterung:
Entfernen Sie beim Verlassen von Bash für jede eindeutige Verlaufsnummer den entsprechenden Verlaufseintrag. Deaktivieren Sie
dann das Kontrollkästchen, FAILED_COMMANDS
um keine Befehle zu entfernen, die Verlaufsnummern von bereits gelöschten Befehlen übernommen haben.
Wenn Sie sicher sind, dass FAILED_COMMANDS
keine Duplikate vorhanden sind, können Sie einfach darüber iterieren
(dh schreiben for i in $FAILED_COMMANDS
). Wenn Sie jedoch erwarten, dass es nicht vom größten zum kleinsten sortiert wird (in diesem Fall immer), ersetzen Sie es uniq
durch sort -rnu
.
Verlaufsnummern in FAILED_COMMANDS
müssen eindeutig sein und vom größten zum kleinsten sortiert werden, da beim Löschen von Einträgen die Nummern der nächsten Befehle verschoben werden - d. H. Wenn Sie ausstellen history -d 2
, wird der dritte Eintrag zum zweiten, der vierte zum dritten usw.
Aus diesem Grund können Sie bei Verwendung dieses Codes nicht manuell anrufen, history -d <n>
wo n
eine kleinere oder gleich große gespeicherte Nummer vorhanden ist,FAILED_COMMANDS
und erwarten, dass der Code ordnungsgemäß funktioniert.
Es ist wahrscheinlich eine gute Idee , Haken exit_handler
an EXIT
, aber man kann es auch früher jederzeit anrufen.