如何使用Bash在屏幕会话中获取命令历史记录?

如何使用Bash在屏幕会话中获取命令历史记录?,bash,command-line,gnu-screen,Bash,Command Line,Gnu Screen,如果我使用screen-dmS name启动屏幕会话,我将如何使用脚本访问该屏幕会话的命令历史记录 使用↑, 最后执行的命令会出现,即使在屏幕中。屏幕不会保存您键入的命令的历史记录。您的shell可能保存历史记录,也可能不保存历史记录。由于您似乎使用了bash,因此可以使用history命令 screen看起来确实有一个粗略的历史搜索近似值(它只是在回滚缓冲区中搜索命令行。请参阅“history”命令下的screen手册页(默认情况下绑定到C-a{)。退出终端(或shell)时shell将其历史

如果我使用
screen-dmS name
启动屏幕会话,我将如何使用脚本访问该屏幕会话的命令历史记录


使用↑, 最后执行的命令会出现,即使在屏幕中。

屏幕
不会保存您键入的命令的历史记录。您的shell可能保存历史记录,也可能不保存历史记录。由于您似乎使用了
bash
,因此可以使用
history
命令


screen
看起来确实有一个粗略的历史搜索近似值(它只是在回滚缓冲区中搜索命令行。请参阅“history”命令下的
screen
手册页(默认情况下绑定到
C-a{
)。
退出终端(或shell)时shell将其历史记录写入$HISTFILE,因此要在另一个终端中获取其历史记录,您可以在您想要的终端中键入
exit
,然后将其写入

cat $HISTFILE
#or tac, less, $EDITOR, ... depending on how you want to "access" it

@technosaurus是对的。$HISTFILE是在bash退出时编写的,因此您可以退出一个bash会话,然后启动一个新会话,并且历史应该通过该文件保存

但是我认为有一个更好的方法来解决您的问题。bash手册包含了对的描述。它允许您使用
history-w[filename]
保存此历史记录,并使用
history-r[filename]
读取历史记录。如果您不提供文件名,它将使用$HISTFILE


因此,我建议您将屏幕会话中的历史记录保存到一个特定的文件(如果需要,也可以保存到默认的$HISTFILE)。然后读取要从中访问历史记录的其他bash会话中的历史文件。这样,您就不必退出原始bash会话。

我在系统上使用默认bash shell,因此可能无法与其他shell一起使用

这是我的
~/.screenrc
文件中的内容,因此每个新屏幕窗口都有自己的命令历史记录:

具有自己的命令历史记录的默认屏幕窗口 要打开一组默认屏幕窗口,每个窗口都有自己的命令历史文件,可以将以下内容添加到
~/.screenrc
文件中:

screen -t "window 0" 0 bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
screen -t "window 1" 1 bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
screen -t "window 2" bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind c screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind ^C screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
export PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND}"
确保新窗口具有自己的命令历史记录 默认屏幕设置意味着您可以使用
Ctrl+a c
Ctrl+a Ctrl+c
创建一个新窗口。但是,在
~/.screenrc
文件中仅使用上述设置,这些设置将使用默认的
~/.bash\u历史文件。若要解决此问题,我们将覆盖用于创建新窗口的键绑定。将其添加到文件中e> ~/.screenrc
文件:

screen -t "window 0" 0 bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
screen -t "window 1" 1 bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
screen -t "window 2" bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind c screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind ^C screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
export PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND}"
现在,每当您创建一个新的屏幕窗口时,它实际上是在启动一个bashshell,将
HISTFILE
环境变量设置为包含当前屏幕窗口编号的内容(
$window

命令历史文件将在具有相同窗口编号的屏幕会话之间共享

执行时将命令写入
$HISTFILE
与正常的bash行为一样,历史记录仅在退出shell/screen窗口时写入
$HISTFILE
文件。但是,如果您希望在命令执行后将命令写入历史记录文件,从而立即可用于具有相同窗口号的其他屏幕会话,则可以添加类似以下内容到您的
~/.bashrc
文件:

screen -t "window 0" 0 bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
screen -t "window 1" 1 bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
screen -t "window 2" bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind c screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind ^C screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
export PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND}"

history
将显示所有history命令。

使用以下命令: 屏幕-L 大写字母L 它将终端输入和输出的副本存储到名为screenlog.0的文件中
或者,如果使用-S命名,日志文件将获得屏幕名称

我将下一行放入我的.bashrc中:

case "$TERM" in
   screen)
       declare SCREEN_NAME=$(echo $STY | sed -nr 's/[^.]*\.(.*)/\1/p')
       if [[ $SCREEN_NAME ]]; then
           HISTFILE="${HISTFILE}.${SCREEN_NAME}.${WINDOW}"
           declare -p HISTFILE
       fi
       unset SCREEN_NAME
       ;;
   *)
       ;;
esac
我的默认.bashrc的“case”基本上带有“xterm*| rxvt*)值,因此我只在其中添加了“screen”部分。如果没有此“case”,则可以使用下一个来代替它:

if [[ $TERM == screen ]]; then
   declare SCREEN_NAME=$(echo $STY | sed -nr 's/[^.]*\.(.*)/\1/p')
   if [[ $SCREEN_NAME ]]; then
       HISTFILE="${HISTFILE}.${SCREEN_NAME}.${WINDOW}"
       declare -p HISTFILE
   fi
   unset SCREEN_NAME
fi
在我的所有屏幕的所有窗口都有自己的bash\u历史记录之后


注意:这在chroot中不起作用!

您的意思是在同一个会话中的不同窗口中(或者也可能在不同的会话中)?可能。这将涉及到解析目标窗口的滚动缓冲区。不过,我对screen不够熟悉,不知道如何以编程方式访问该缓冲区。您可以尝试阅读手册页以了解如何执行此操作。它是否仅写在
exit
?AFAIK上,直到它写入时存储在内存中,最多$HISTSIZE行es它将历史文件保留为$HISTFILESIZE行maxI忘记了
shopt-s histappend
请参见:但注意:这会记录输出和输入。这与我想要的最接近,但是…试图找到一种方法将其全部保存到一个历史文件中。
HISTSIZE
等如果将它们嵌入
屏幕中,则似乎不起作用命令。