在BASH历史记录中仅保留成功的命令


20

有时我会误解命令的语法:

# mysql -d test
mysql: unknown option '-d'
# echo $?
2

我再试一次并正确处理:

# mysql --database test
Welcome to the MySQL monitor.
mysql >
...

如何防止错误代码不为0的第一个命令进入历史记录?

Answers:


20

我不认为你真的想要那个。我通常的工作流程如下:

  • 输入命令
  • 运行
  • 注意它失败
  • 按上键
  • 编辑命令
  • 再次运行

现在,如果失败的命令没有保存到历史记录中,我将无法轻松地将其恢复并再次运行。


3
我想更好的设计应该是会议记录和永久记录。谢谢!
亚当·马坦

退出终端时,历史记录将被保存。因此,尽管您可以返回在此终端会话中键入的命令但实际上它会在退出终端时保存到bash历史记录中。

11

我能想到的唯一办法做到这一点是使用history -d$PROMPT_COMMAND。这种方法或任何方法的问题在于,无法判断命令是否以错误退出或是否使用非零退出代码成功完成。

$ grep non_existent_string from_file_that_exists
$ echo $?
1

4

最好有最后一个不正确的注释来更正它,但是此后不久,它可能会引起混乱。

我的方法分两步:存储失败的命令,并在以后的某个时间删除它们。

存储执行以下操作时失败的命令:

error_handler() {
    FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}

trap error_handler ERR

trap command signalscommand当其中之一signals被“提升” 时执行。

$(command),执行command并捕获其输出。

当命令失败时,此代码段将捕获保存到历史记录中最后一条命令的历史记录编号,并将其存储在变量中,以备将来删除。

很简单,但与HISTCONTROLHISTIGNORE不能正确使用-当命令由于变量之一而未保存到历史记录中时,保存到历史记录中的最后一条命令的历史记录编号是前一条命令的历史记录编号;因此,如果不正确的命令未保存到历史记录中,则先前的命令将被删除。

稍微复杂一点的版本,在这种情况下可以正常工作:

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)。但是,如果您希望它不会从最大到最小排序(在这种情况下始终是),请替换uniqsort -rnu

输入的历史记录编号FAILED_COMMANDS必须唯一,并按从大到小的顺序进行排序,因为删除条目时,下一条命令的编号将发生移位,即 当您发出时history -d 2,第3个条目将变为第2个,第4个条目将变为第3个,依此类推。

因此,在使用此代码时,您无法手动调用小于或等于存储在history -d <n>
其中的n最大数字的位置,FAILED_COMMANDS
并期望代码正常工作。

挂接exit_handler到也许是个好主意EXIT,但是您也可以在任何时候调用它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.