Manchmal verstehe ich die Syntax eines Befehls falsch:
# mysql -d test
mysql: unknown option '-d'
# echo $?
2
Ich versuche es noch einmal und mache es richtig:
# mysql --database test
Welcome to the MySQL monitor.
mysql >
...
Wie verhindere ich, dass der erste Befehl mit einem Fehlercode ungleich 0 in den Verlauf aufgenommen wird?
Antwort1
Ich glaube nicht, dass Sie das wirklich wollen. Mein üblicher Arbeitsablauf sieht folgendermaßen aus:
- Geben Sie einen Befehl ein
- Starte es
- Beachten Sie, dass es fehlschlägt
- Drücken Sie die Taste UP
- Bearbeiten des Befehls
- Führen Sie es erneut aus
Wenn der fehlgeschlagene Befehl nicht im Verlauf gespeichert wäre, könnte ich ihn nicht einfach wiederherstellen, um ihn zu reparieren und erneut auszuführen.
Antwort2
Die einzige Möglichkeit, die mir hierfür einfällt, wäre die Verwendung von history -d
in $PROMPT_COMMAND
. Das Problem bei diesem oder jedem anderen Ansatz besteht darin, dass es unmöglich ist, festzustellen, ob ein Befehl mit einem Fehler beendet wurde oder erfolgreich mit einem Exit-Code ungleich Null abgeschlossen wurde.
$ grep non_existent_string from_file_that_exists
$ echo $?
1
Antwort3
Es ist gut, den letzten falschen Kommentar zu haben, um ihn zu korrigieren, aber kurz danach wird er zu potenziell verwirrendem Müll.
Mein Ansatz besteht aus zwei Schritten: Speichern Sie fehlgeschlagene Befehle, wenn dies der Fall ist, und entfernen Sie sie zu einem späteren Zeitpunkt.
Speichern Sie Befehle, die fehlschlagen, wenn dies der Fall ist:
error_handler() {
FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}
trap error_handler ERR
trap command signals
wird ausgeführt command
, wenn eines von signals
„erhöht“ wird.
$(command)
, führt aus command
und erfasst seine Ausgabe.
Wenn der Befehl fehlschlägt, erfasst dieser Codeausschnitt die Verlaufsnummer vonletzter Befehl im Verlauf gespeichert, und speichert es 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,Verlaufsnummer des letzten im Verlauf gespeicherten Befehlsist der vorherige Befehl. Wenn also der falsche 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 zu einem späteren Zeitpunkt 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 Beenden von Bash für jede eindeutige Verlaufsnummer den entsprechenden Verlaufseintrag und
löschen Sie dann die FAILED_COMMANDS
Option, um Befehle nicht zu entfernen, die Verlaufsnummern von bereits gelöschten Befehlen geerbt haben.
Wenn Sie sicher sind, dass es FAILED_COMMANDS
keine Duplikate enthält, können Sie einfach darüber iterieren
(d. h. schreiben for i in $FAILED_COMMANDS
). Wenn Sie jedoch erwarten, dass es nicht von groß nach klein sortiert ist (in diesem Fall ist es das immer), ersetzen Sie es uniq
durch sort -rnu
.
Die Verlaufsnummern FAILED_COMMANDS
müssen eindeutig sein und von der größten zur kleinsten sortiert werden, da beim Löschen eines Eintrags die Nummern der nächsten Befehle verschoben werden – wenn Sie beispielsweise eingeben history -d 2
, wird der 3. Eintrag zum 2., der 4. zum 3. usw.
Aus diesem Grund können Sie bei Verwendung dieses Codes nicht manuell aufrufen, history -d <n>
wobei n
die Zahl kleiner oder gleich der größten gespeicherten Zahl ist,FAILED_COMMANDS
und erwarten, dass der Code ordnungsgemäß funktioniert.
exit_handler
Es ist wahrscheinlich eine gute Idee, bei einzuhaken EXIT
, aber Sie können es auch jederzeit früher aufrufen.