如何在不同选项卡之间共享 Bash 历史记录

如何在不同选项卡之间共享 Bash 历史记录

我用的是https://unix.stackexchange.com/a/1292/41729以在单独的 Bash 终端之间启用实时共享历史记录。如上面的答案所述,这可以通过将以下内容添加到来实现.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, save and reload history
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

如果 Bash shell 是分开的(例如使用CTRL+ ALT+打开不同的 Bash 终端T),这种方法很有效。但是,如果我使用标签(从打开的终端CTRL++ SHIFTT而不是新窗口。为什么会有这种行为差异?我如何在各个选项卡之间共享 Bash 历史记录?

更新:我注意到一个不寻常的行为:如果我输入CTRL+ C,那么在任何其他终端(无论是否为选项卡)中输入的最后一个命令都会正确显示。这就像CTRL+C强制刷新历史记录,以便正确共享它一样。

举例来说,输出(T1 表示端子 1,T2 表示端子 2):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<up> (i.e. I press the up arrow)
ls -lah # i.e the last command in terminal 1 is shown rather than the last of terminal 2
^C (i.e. I press CTRL+C)
<up>
cd Documents # the last command issued in terminal 2 is correctly displayed

答案1

您似乎正在尝试访问其他终端的历史记录同步发生。PROMPT_COMMAND在打印新提示之前执行,即您运行一个命令,然后才输入下一个命令。因此它不会在 T1 中立即发生;您必须显示一个新的提示。

为了测试这一点,请在您的步骤中尝试此变体(我<enter>在 T1 中添加了一个额外的内容):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<enter>
<up> (i.e. I press the up arrow)

再次按下回车键后,您将获得一个新的提示,它将运行PROMPT_COMMAND并同步您的历史记录,因此我希望这个向上箭头能够检索cd而不是检索ls。不幸的是,我认为没有办法让同步在所有终端中立即发生,而无需运行任何命令,而这似乎正是您想要的;实际上,这将要求您的所有登录会话始终持续同步其历史记录列表,这将浪费大量的 CPU 和磁盘吞吐量。

答案2

我问了同样的问题,这是我得出的答案......

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

答案3

将这些行添加到您的.bashrc文件中

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

trap 'history -r' USR1 
export PROMPT_COMMAND="history -a ; history -c; ps a | awk '/ bash$/ {system (\"kill -USR1 \" \$1)}'; $PROMPT_COMMAND"

笔记:

最初,我在测试舱中使用 killall 向 bash 发送 USR1 信号,后来我想到使用一个唯一的 shell 名称,一个名为 testshell 的 bash 副本,以避免杀死可以运行的自己的 shell(例如 cron 进程),但奇怪的是,这不起作用。

killall 的选择性不够,我用一个脚本替换了它,该脚本只杀死与 tty 紧密相关的 bash 进程(ps a仅报告与 tty 绑定的进程)

不要忘记重新启动会话以获得新的 PROMPT_COMMAND,当我测试时,我看到许多以前的测试都堆叠在 PROMPT_COMMAND 里面。

答案4

当我尝试创建复杂的 bash 提示符以显示其他登录次数时,我在 Yakuake 中遇到了同样的奇怪行为。选项卡的数量没有增加。我的解决方法是告诉 Yakuakebash在每个新选项卡中再次运行,本质上是在 bash 中启动 bash。它开始完美地工作。也许它也会对你有所帮助。我的盲目猜测是控制台的 GUI 会自行加载 bash 配置,然后将它们提供给 bash 实例。可能是为了能够摆弄它们。

相关内容