Dobrze jest mieć ostatni niepoprawny komentarz, aby go poprawić, ale wkrótce potem staje się potencjalnie mylącym śmieciem.
Moje podejście jest dwuetapowe: przechowuj polecenia, które się nie powiedzie, i usuwaj je później.
Przechowuj polecenia, które nie działają, gdy:
error_handler() {
FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}
trap error_handler ERR
trap command signals
wykonuje się, command
gdy jeden z nich signals
jest „podniesiony”.
$(command)
, wykonuje command
i przechwytuje dane wyjściowe.
Gdy polecenie nie powiedzie się, ten fragment kodu przechwytuje w historii numer ostatniego polecenia zapisanego w historii i zapisuje go w zmiennej do przyszłego usunięcia.
Prosty, ale działa niepoprawnie z HISTCONTROL
i HISTIGNORE
- gdy polecenie nie jest zapisane w historii z powodu jednej ze zmiennych, numer historii ostatniego polecenia zapisanego w historii jest numerem poprzedniego polecenia; więc jeśli nieprawidłowe polecenie nie zostanie zapisane w historii, poprzednie polecenie zostanie usunięte.
Nieco bardziej skomplikowana wersja, która w tym przypadku działa poprawnie:
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
Usuń przechowywane polecenia później:
exit_handler() {
for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
do
history -d $i
done
FAILED_COMMANDS=
}
trap exit_handler EXIT
Wyjaśnienie:
Wychodząc z Bash, dla każdego unikalnego numeru historii usuń odpowiedni wpis historii,
a następnie usuń zaznaczenie, FAILED_COMMANDS
aby nie usuwać poleceń, które odziedziczyły numery historii z już usuniętych poleceń.
Jeśli masz pewność, że FAILED_COMMANDS
będą wolne od duplikatów, możesz po prostu iterować
(np. Pisać for i in $FAILED_COMMANDS
). Jeśli jednak można oczekiwać, że nie mogą być sortowane od największego do najmniejszego (w tym przypadku to zawsze jest), wymienić uniq
z sort -rnu
.
Numery historii FAILED_COMMANDS
muszą być unikalne i posortowane od największych do najmniejszych, ponieważ po usunięciu wpisu numery kolejnych poleceń są przesuwane - tzn. kiedy wydajesz history -d 2
, 3. wpis staje się 2., 4. staje się 3. itd.
Z tego powodu podczas korzystania z tego kodu nie można ręcznie wywoływać, history -d <n>
gdzie n
jest mniejszy lub równy największemu przechowywanemu numerowiFAILED_COMMANDS
i oczekiwać, że kod będzie działał poprawnie.
Prawdopodobnie dobrym pomysłem jest zaczepienie exit_handler
się EXIT
, ale możesz też zadzwonić w dowolnym momencie wcześniej.