![跨会话共享 shell 历史记录而不交错](https://linux22.com/image/127037/%E8%B7%A8%E4%BC%9A%E8%AF%9D%E5%85%B1%E4%BA%AB%20shell%20%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%E8%80%8C%E4%B8%8D%E4%BA%A4%E9%94%99.png)
有一个类似的问题这里,但我想实现不同的目标:我想在会话之间共享历史记录,但是无需将不同会话中执行的命令混合在一起。
例如,假设我有两个 shell 会话:A 和 B。我在 A 中键入一些命令:
A$ ls ~
A$ ls /etc
在B中:
B$ git status
B$ git log
当我输入history
shell 时,我想查看该 shell 中的所有命令一起,后来自其他 shell 的命令 - 这样我总是可以使用 uparrow 从当前 shell 获取最后的命令。换句话说,history
在 shell A 中应该显示
git status
git log
ls ~
ls /etc
在 shell B 中它应该显示
ls ~
ls /etc
git status
git log
这个怎么做?
答案1
似乎没有内置的解决方案,但事实证明手动实现它并不那么困难。人们必须单独存储每个会话的历史记录,并在每次提示时重新创建它(它并不像听起来那么慢)。核心逻辑如下:
# on every prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
history -a ${HISTFILE}.$$
history -c
history -r
for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
history -r $f
done
history -r "${HISTFILE}.$$"
}
export PROMPT_COMMAND='update_history'
# merge session history into main history file on bash exit
merge_session_history () {
cat ${HISTFILE}.$$ >> $HISTFILE
rm ${HISTFILE}.$$
}
trap merge_session_history EXIT
看这个要点完整的解决方案,包括一些保障措施和性能优化。
答案2
这并不完全是问题的答案,但仍然非常相似,所以有些人可能会觉得很有趣:
我的直觉是,uparrow 应该根据当地历史行事,但也Ctrl-r
应该根据全球共同历史行事。这是一种方法(使用 fzf):
# do not overwrite the history file on exit
shopt -s histappend
# immediately add the last command to the history file
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
# use a custom function that uses $HISTFILE for Ctrl-r
__my_history__() {
READLINE_LINE=$(fzf --query "$READLINE_LINE" < $HISTFILE)
READLINE_POINT=${#READLINE_LINE}
}
bind -x '"\C-r": __my_history__'