DrB*_*eco 15 shell bash command-history signals
我知道这个问题并不晦涩,因为它在这里被问到不断更新(并在此处重复)。
我想要实现的目标有点不同。我不喜欢每次ls
键入时提示重写文件的想法( history -a; history -c; history -r
)。
我想在退出时更新文件。这很容易(实际上,默认),但您需要追加而不是重写:
shopt -s histappend
Run Code Online (Sandbox Code Playgroud)
现在,当终端关闭时,我想让所有其他保持打开状态的终端都知道更新。
我更喜欢这样做而不检查我输入的$PS1
每一个command
。我认为捕获某种信号会更好。你会怎么做?如果不可能,也许是一个简单的cronjob
?
我们如何解决这个难题?
Mic*_*mer 15
你说有创意和涉及信号?好的:
trap on_exit EXIT
trap on_usr1 USR1
on_exit() {
history -a
trap '' USR1
killall -u "$USER" -USR1 bash
}
on_usr1() {
history -n
}
Run Code Online (Sandbox Code Playgroud)
把它塞进.bashrc
去然后走。这使用信号告诉每个bash
进程在另一个进程退出时检查新的历史记录条目。这非常糟糕,但它确实有效。
它是如何工作的?
trap
为系统信号或 Bash 的内部事件之一设置信号处理程序。该EXIT
事件是外壳的任何控制终止,而USR1
为SIGUSR1
,我们占有一个毫无意义的信号。
每当 shell 退出时,我们:
SIGUSR1
处理程序并使这个 shell忽略信号。bash
从同一用户向所有正在运行的进程发送信号。当 aSIGUSR1
到达时,我们:
因为这样猛砸手柄信号,你就不会真正得到新的历史数据,直到你打Enter接下来的时间,所以这不会做对前面的任何优于把history -n
成PROMPT_COMMAND
。但是,它确实会在没有发生任何事情时不断读取文件,并且在 shell 退出之前根本没有写入。
然而,这里仍然存在一些问题。第一个是默认响应SIGUSR1
是终止shell。任何其他bash
进程(例如,运行 shell 脚本)都将被终止。.bashrc
不是由非交互式 shell 加载的。相反,加载了一个名为 by 的文件BASH_ENV
:您可以在您的环境中全局设置该变量以指向一个文件:
trap '' USR1
Run Code Online (Sandbox Code Playgroud)
在其中忽略其中的信号(解决问题)。
最后,虽然这符合您的要求,但您得到的订单会有点不寻常。特别是,当历史片段被分别加载和保存时,它们会以不同的顺序重复。这本质上是您所要求的内容,但请注意,此时向上箭头历史变得不那么有用了。不过,历史替换等将被共享并且运行良好。