在多个终端窗口中保留 bash 历史记录

在多个终端窗口中保留 bash 历史记录

我一直有多个终端打开。从两个到十个,做各种零碎的事情。现在假设我重新启动并打开另一组终端。有些人记得某些事情,有些人忘记了。

我想要这样的历史:

  • 记住每个终端的所有内容
  • 可以从每个终端立即访问(例如,如果我ls在一个终端中,切换到另一个已经运行的终端,然后按向上键,ls显示)
  • 如果命令前面有空格,不要忘记命令。

我能做些什么来让 bash 更像那样工作吗?

答案1

将以下内容添加到您的~/.bashrc

# Avoid duplicates
HISTCONTROL=ignoredups:erasedups
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend

# After each command, append to the history file and reread it
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

答案2

所以,这就是我所有与历史相关的.bashrc事情:

export HISTCONTROL=ignoredups:erasedups  # no duplicate entries
export HISTSIZE=100000                   # big big history
export HISTFILESIZE=100000               # big big history
shopt -s histappend                      # append to history, don't overwrite it

# Save and reload the history after each command finishes
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

在 Mac OS X 10.5 上使用 bash 3.2.17 进行测试,在 10.6 上使用 bash 4.1.7 进行测试。

答案3

这是我对 Bash 会话历史记录共享的尝试。这将使 bash 会话之间的历史共享成为可能,历史计数器不会混淆,历史扩展也!number能工作(有一些限制)。

在 Ubuntu 10.04 LTS (Lucid Lynx) 下使用 Bash 版本 4.1.5。

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
    builtin history -a         #1
    HISTFILESIZE=$HISTSIZE     #2
    builtin history -c         #3
    builtin history -r         #4
}

history() {                  #5
    _bash_history_sync
    builtin history "$@"
}

PROMPT_COMMAND=_bash_history_sync

解释:

  1. 将刚刚输入的行附加到$HISTFILE(默认为.bash_history)。这将导致$HISTFILE增长一行。

  2. 将特殊变量设置$HISTFILESIZE为某个值将导致 Bash通过删除最旧的条目来截断$HISTFILE不超过行的长度。$HISTFILESIZE

  3. 清除正在运行的会话的历史记录。这将减少历史计数器的数量$HISTSIZE

  4. 读取内容$HISTFILE并将其插入到当前正在运行的会话历史记录中。这将使历史计数器增加 中的行数$HISTFILE。请注意, 的行数$HISTFILE不一定是$HISTFILESIZE

  5. history()函数会覆盖内置历史记录,以确保历史记录在显示之前已同步。这对于按数量进行历史扩展是必要的(稍后会详细介绍)。

更多解释:

  • 步骤 1 确保当前运行会话中的命令写入全局历史文件。

  • 步骤 4 确保其他会话中的命令被读入当前会话历史记录中。

  • 因为步骤 4 会增加历史计数器,所以我们需要以某种方式减少计数器。这是在步骤 3 中完成的。

  • 在步骤 3 中,历史计数器减少$HISTSIZE。在步骤 4 中,历史记录计数器按 中的行数增加$HISTFILE。在步骤 2 中,我们确保 的行数$HISTFILE准确无误$HISTSIZE(这意味着$HISTFILESIZE必须与 相同$HISTSIZE)。

关于历史扩展的限制:

当使用按数字扩展历史记录时,您应该总是查号码立即地在使用它之前。这意味着在查找号码和使用号码之间不会显示 bash 提示符。这通常意味着没有 Enter 也没有 ctrl+c。

一般来说,一旦您有多个 Bash 会话,就无法保证按数字进行的历史扩展会在两次 Bash 提示符显示之间保留其值。因为当PROMPT_COMMAND执行时,所有其他 Bash 会话的历史记录都会集成到当前会话的历史记录中。如果任何其他 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 完成脚本。

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

答案4

为此,您需要将两行添加到您的~/.bashrc

shopt -s histappend
PROMPT_COMMAND="history -a;history -c;history -r;$PROMPT_COMMAND"

man bash

如果启用了 histappend shell 选项(请参阅下面的 SHELL BUILTIN COMMANDS 下的 shopt 描述),则这些行将追加到历史文件中,否则历史文件将被覆盖。

相关内容