![如何在不同选项卡之间共享 Bash 历史记录](https://linux22.com/image/967907/%E5%A6%82%E4%BD%95%E5%9C%A8%E4%B8%8D%E5%90%8C%E9%80%89%E9%A1%B9%E5%8D%A1%E4%B9%8B%E9%97%B4%E5%85%B1%E4%BA%AB%20Bash%20%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95.png)
我用的是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++ SHIFT)T而不是新窗口。为什么会有这种行为差异?我如何在各个选项卡之间共享 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 实例。可能是为了能够摆弄它们。