为什么当 Bash 中的 histappend 设置为 off 时,历史记录不会覆盖而是追加?

为什么当 Bash 中的 histappend 设置为 off 时,历史记录不会覆盖而是追加?

几天前,我让一个终端选项卡在执行ssh,而另一个在本地执行大量工作。然后我重新启动了机器(在带有 Mavericks 的 Mac 上)。

当我再次运行终端时,我发现第二个选项卡的所有命令历史记录都不存在。只有ssh命令。

所以然后我搜索了如何以某种方式“合并”历史记录,发现我们需要shopt -s histappend在我们的~/.bashrc文件中执行 a 以便历史记录会附加,而不是“覆盖”——我们不希望一组历史记录覆盖另一组历史记录放;我们想要追加。

但是,当我转到 OS X Yosemite 盒子并使用 时shopt,我看到它histappend已关闭,但是当我打开两个选项卡,一个在执行echo abc,另一个在执行echo def,然后退出它们时,我再次重新打开终端并发出history命令,并看到了echo abcecho def命令。

然后我在 VirtualBox 上运行 Ubuntu 2014-10 并做了类似的事情,并且仍然看到记录的历史记录(我首先shopt -u histappend在两个 Bash 中运行以先将选项设置为关闭)。

那么到底是什么机制在这样做呢?那么histappend就没有意义了,如果设置为开或关都没有关系的话?

我还注释掉了shopt -s histappend我的.bashrc终端并重新启动并再次尝试,并看到两个选项卡能够组合的历史记录......所以这确实是奇怪的行为,是什么原因导致的?

答案1

@戴大卫关于这个 bash-help 线程的说法是正确的。

这里bash是C中的相关代码。

if (history_lines_this_session <= where_history () || force_append_history)
  {
    result = append_history (history_lines_this_session, hf);
    history_lines_in_file += history_lines_this_session;
  }
else
  {
    result = write_history (hf);
    history_lines_in_file = history_lines_this_session;
  }

shopt -s histappend设置force_append_history为非零 ( true)。

history_lines_this_sessionbash是您在此交互式会话中键入的命令数。当你第一次启动 bash 时,它是 0。每执行Enter一个保存到历史记录的命令,它就会增加 1。

where_history()是内存中历史记录列表的索引,从索引 0 开始。它指向要写入历史记录的下一个索引。例如,当您有 0 条历史记录时,它将是索引 0。当您有 6 行历史记录时,它将是索引 6。

当你第一次开始bash并且你有历史记录时HISTFILEwhere_history()增加但会受到限制<= HISTSIZE。所以where_history()有最大值HISTSIZE.

读取后HISTFILEwhere_history()会增加,但history_lines_this_session仍为 0。当您Enter HISTSIZE + 1执行命令数 时,history_lines_this_session == HISTSIZE + 1where_history() == HISTSIZE(因为它有最大值)。此时,如果关闭,(history_lines_this_session <= where_history()) == false历史记录将被覆盖。histappend

您可以自己测试一下bash。如果histappend关闭,一旦运行HISTSIZE + 1命令数量history_lines_this_session将超过where_history()1 并且HISTFILE将被覆盖。您必须确保其他命令不会干扰您的历史记录才能使测试正常进行(发生在 macOS 上)。使用以下命令关闭可能会扰乱历史记录的命令:

trap - EXIT
PROMPT_COMMAND=
SHELL_SESSION_HISTORY=0 # for macOS only

答案2

我相信histappend这是为终端。

在新终端中尝试以下操作:

shopt -s histappend
export HISTSIZE=1
export HISTFILESIZE=500

然后关闭终端。然后,您将看到您的历史文件如何包含它已经包含的最后 499 个最后命令以及export HISTFILESIZE=50您刚刚键入的“”。您的历史记录已被追加,然后被截断为 500。

现在在另一个新终端中尝试此操作:

shopt -u histappend
export HISTIZE=1
export HISTFILESIZE=500

再次关闭终端。您将看到现在您的终端只有一个命令“ export HISTFILESIZE=500”。

诀窍是,如果没有histappend,历史文件将被终端历史记录中当前的内容(一个命令)覆盖。

你不会注意到它的行为 if HISTFILE=HISTFILESIZE但我相信它与在多个终端上工作无关,这必须由其他东西管理......

相关内容