我总是打开至少 3 个终端程序窗口,但有时我会打开另一个终端来快速执行某些操作。我怎样才能使命令历史记录在所有窗口中都相同?
答案1
感谢上面 gertvdijk 提供的链接,我从中发布了我最喜欢的解决方案。
这是我尝试共享 Bash 会话历史。这将使 Bash 会话之间的历史共享成为可能,这样历史计数器就不会混淆,并且像 !number 这样的历史扩展将在某些限制下工作。
在 Ubuntu 10.04 LTS(Lucid Lynx)下使用 Bash 版本 4.1.5。
HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups
history() {
_bash_history_sync
builtin history "$@"
}
_bash_history_sync() {
builtin history -a #1
HISTFILESIZE=$HISTSIZE #2
builtin history -c #3
builtin history -r #4
}
PROMPT_COMMAND=_bash_history_sync
解释:history() 函数覆盖了内置的 history,以确保在显示之前同步历史记录。这对于按数字扩展历史记录是必要的(稍后会详细介绍)。
将刚刚输入的行附加到 $HISTFILE(默认为 .bash_history)。这将导致 $HISTFILE 增加一行。
将特殊变量 $HISTFILESIZE 设置为某个值将导致 Bash 通过删除最旧的条目来截断 $HISTFILE 以使其不超过 $HISTFILESIZE 行。
清除正在运行的会话的历史记录。这将使历史记录计数器减少 $HISTSIZE 的数量。
读取 $HISTFILE 的内容并将其插入到当前正在运行的会话历史记录中。这将使历史记录计数器增加 $HISTFILE 中的行数。请注意,$HISTFILE 的行数不一定是 $HISTFILESIZE。
更多解释:步骤 1 确保当前正在运行的会话的命令被写入全局历史文件。
步骤 4 确保来自其他会话的命令被读入当前会话历史记录中。
因为步骤 4 将提高历史计数器,所以我们需要以某种方式减少计数器。这在步骤 3 中完成。
在步骤 3 中,历史计数器减少 $HISTSIZE。在步骤 4 中,历史计数器增加 $HISTFILE 中的行数。在步骤 2 中,我们确保 $HISTFILE 的行数正好是 $HISTSIZE(这意味着 $HISTFILESIZE 必须与 $HISTSIZE 相同)。
关于历史扩展的限制:通常,一旦您有多个 Bash 会话,就无法保证按数字扩展的历史会在两个 Bash 提示显示之间保留其值。每次执行 PROMPT_COMMAND 时,来自另一个 Bash 会话的某些命令可能会潜入您当前的会话历史记录中,然后历史编号就会有所不同。这意味着您总是必须在使用它之前立即查找该编号。我发现这个限制是合理的。无论如何,我每次都必须查找该编号,因为我记不住任意的历史编号。
通常我使用像这样的数字来扩展历史
$ history | grep something #note number
$ !number
我建议使用以下 Bash 选项。
## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify
奇怪的错误:运行通过管道传输到任何内容的历史记录命令将导致该命令在历史记录中列出两次。例如:
$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false
所有内容都会在历史记录中列出两次。我不知道为什么。
改进思路:修改函数 _bash_history_sync(),使其不每次都执行。例如,它不应该在提示符上按 CTRL+C 后执行。当我决定不想执行该行时,我经常使用 CTRL+C 来丢弃长命令行。有时我必须使用 CTRL+C 来停止 Bash 完成脚本。
当前会话中的命令应始终是当前会话历史记录中的最新命令。这也会产生副作用,即给定的历史记录编号将保留其来自此会话的历史记录条目的值。