我在 x86 上的 RHEL 2.6 上运行 KSH。 KSH版本是:
sh (AT&T 研究) 93u+ 2012-08-01
切换到 Bash 或返回 Tcsh(我很高兴在我以前的工作中使用它)是不可能的。
关于 KSH,我注意到的第一件烦人的事情是,有时当使用向上键滚动历史记录时,来自不同终端的历史记录(我一次打开多个终端)会混合在一起。然后我了解到我的所有终端共享一个 HISTFILE。很好,但还是很奇怪,他们并不总是混合在一起。我还注意到 HISTFILE 并不总是立即更新。最终我确定 KSH 可能正在缓冲一些命令历史记录并定期将内容刷新到 HISTFILE。我找不到任何地方记录这种行为,但这似乎是一个合理的解释。
我真的希望每个会话都有不同的历史记录,因此我将其添加到我的 .kshrc 文件中:
HISTFILE=~/.hist.$(tty | sed 's;.*/;;')
它应该为每个终端提供一个唯一的 HISTFILE。它做到了这一点,这很棒。但是......这些历史文件似乎会定期被清除。我现在的大部分文件大小都是 0 字节。
更新: 我所有打开的终端的各个历史文件每 10 分钟就会被清除一次。有规律的。
有人以前见过这个吗???
更新:两年后,我仍然距离答案还很远。最近特别烦人。开始研究 ksh 源代码,但我是一名硬件设计师,没有太多评论,所以这非常困难。
好吧,也许这是一个线索。我的历史文件中的每一行都以 ^@ 字符开头(由 emacs 呈现)。我认为这意味着 0x40(@ 字符)+ 0x80(控制位)= 0xc0 = 八进制 300。据我所知,history.c 中提到的唯一特殊字符是 0201 和 0202。我的历史文件确实开始与 \201 (同样,由 emacs 渲染,我猜这是八进制)。
这是一个典型历史文件的示例,这看起来正常吗:
�ls
pwd
clear
ls
ls
tty
嗯,这些控制字符无法正确显示。转录为常规字符,如下所示:
\201^Als
^@pwd
^@^@clear
^@^@ls
^@ls
^@tty
^@^@
有时我会收到两个 ^@ 字符,有时会收到一个,但我不明白为什么。这可能不是线索,但我现在没有其他线索。
更新: 解决了!好吧,差不多了。我一发布这个帖子,就开始在history.c 中搜索其他一些东西。我看到了这个:
/*
* clean out history file OK if not modified in HIST_RECENT seconds
*/
static int hist_clean(int fd)
{
struct stat statb;
return(fstat(fd,&statb)>=0 && (time((time_t*)0)-statb.st_mtime) >= HIST_RECENT);
}
毫不奇怪,HIST_RECENT 设置为 600,正是我正在寻找的 10 分钟间隔。我还没有完全弄清楚如何禁用它,但无论我多么讨厌它,它看起来确实是故意的行为。
答案1
是的,ksh93
将其命令行历史记录写入文件,同时bash
在 shell 退出时写入。挖掘虽然一些源代码,似乎内存中的历史缓冲区是 4k(HIST_BSIZE
在代码中),但我无法弄清楚它是否在满时或在一定数量的命令之后刷新它(谁可能HIST_MARKSZ
在这段代码中做什么? )。
是的,如果许多交互式会话使用相同的HISTFILE
设置,它们就会共享历史记录。这是有记录的(我的重点):
命令重新输入。
从终端设备输入的最后(默认 512)命令的文本
HISTSIZE
保存在历史文件中。如果未设置变量或它命名的文件不可写,则$HOME/.sh_history
使用该文件。HISTFILE
shell 可以访问使用相同名称的所有交互式 shell 的命令HISTFILE
。
历史文件将保留为指定的大小,HISTSIZE
但不会像您遇到的那样定期被截断。你正在发生的事情是,我思考,由于您用于为每个交互式 shell 会话tty
设置唯一的HISTFILE
,因此退出和重新启动交互式会话可能会也可能不会拾取“正确”历史文件,具体取决于 shell 连接到的 TTY。
如果为 shell 会话分配了一个新的 TTY(以前从未与会话一起使用过),那么它的历史文件自然会是空的。