有時我會誤解指令的語法:
# mysql -d test
mysql: unknown option '-d'
# echo $?
2
我再試一次並得到正確的結果:
# mysql --database test
Welcome to the MySQL monitor.
mysql >
...
如何防止錯誤代碼不為 0 的第一條命令進入歷史記錄?
答案1
我不認為你真的想要那樣。我平常的工作流程是這樣的:
- 輸入命令
- 運行
- 注意它失敗了
- 按向上鍵
- 編輯命令
- 再次運行
現在,如果失敗的命令沒有保存到歷史記錄中,我就無法輕鬆地將其修復並再次運行。
答案2
我能想到的唯一方法是使用history -d
in $PROMPT_COMMAND
。這種方法或任何方法的問題在於,無法判斷命令是否因錯誤退出或以非零退出代碼成功完成。
$ grep non_existent_string from_file_that_exists
$ echo $?
1
答案3
最好能有最後一個錯誤的評論來糾正它,但不久之後,它就會變成潛在的令人困惑的垃圾。
我的方法分為兩個步驟:儲存失敗的命令,並在稍後刪除它們。
儲存失敗的命令:
error_handler() {
FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}
trap error_handler ERR
trap command signals
command
當其中一個signals
被“引發”時執行。
$(command)
,執行command
並捕獲其輸出。
當命令失敗時,這段程式碼會捕捉歷史數量最後一條命令保存到歷史記錄中,並將其儲存在變數中以供將來刪除。
簡單,但與HISTCONTROL
and一起使用時無法正常工作HISTIGNORE
– 當由於其中一個變數而未將命令保存到歷史記錄中時,保存到歷史中的最後命令的歷史編號是上一個命令的命令;因此,如果錯誤的命令沒有儲存到歷史記錄中,則先前的命令將被刪除。
稍微複雜一點的版本,在這種情況下可以正常工作:
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
稍後刪除儲存的命令:
exit_handler() {
for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
do
history -d $i
done
FAILED_COMMANDS=
}
trap exit_handler EXIT
解釋:
退出 Bash 時,對於每個唯一的歷史記錄編號,刪除對應的歷史記錄條目,
然後清除FAILED_COMMANDS
以不刪除從已刪除的命令繼承歷史記錄編號的命令。
如果您確定它FAILED_COMMANDS
不會重複,您可以簡單地對其進行迭代
(即 write for i in $FAILED_COMMANDS
)。但是,如果您希望它不是從最大到最小排序(在本例中始終如此),請替換uniq
為sort -rnu
。
歷史記錄中的編號FAILED_COMMANDS
必須是唯一的,並且從大到小排序,因為當您刪除條目時,下一個命令的編號會發生變化 - 即。當您發出 時history -d 2
,第 3 個條目變為第 2 個條目,第 4 個條目變為第 3 個條目,依此類推。
因此,在使用此程式碼時,您無法手動呼叫history -d <n>
wheren
小於或等於儲存的最大數字FAILED_COMMANDS
並期望程式碼正常運作。
exit_handler
掛接可能是個好主意EXIT
,但您也可以提前隨時呼叫它。