如何使命令行历史记录适用于所有终端

Sco*_*ame 7 command-line

我总是至少打开 3 个终结器(一个终端程序)窗口,但有时打开另一个终端只是为了快速做一些事情。我怎样才能使命令历史在所有这些命令中都是通用的?

Sco*_*ame 3

感谢上面 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
Run Code Online (Sandbox Code Playgroud)

说明:函数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
Run Code Online (Sandbox Code Playgroud)

我建议使用以下 Bash 选项。

## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify
Run Code Online (Sandbox Code Playgroud)

奇怪的错误:运行通过管道传输到任何内容的历史命令将导致该命令在历史记录中列出两次。例如:

$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false
Run Code Online (Sandbox Code Playgroud)

一切都将两次载入史册。我不知道为什么。

改进想法:修改函数 _bash_history_sync(),使其不会每次都执行。例如,它不应在提示符上按 CTRL+C 之后执行。当我决定不想执行长命令行时,我经常使用 CTRL+C 来放弃该行。有时我必须使用 CTRL+C 来停止 Bash 完成脚本。

当前会话中的命令应始终是当前会话历史记录中的最新命令。这还会产生副作用,即给定的历史记录编号会保留该会话中的历史记录条目的值。