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

24
如果我使用screen -dmS name启动一个screen会话,如何在脚本中访问该screen会话的命令历史记录?
即使在screen中,使用键也会显示最后执行的命令。
7个回答

29

我使用系统默认的bash shell,所以可能无法与其他shell兼容。

这是我在~/.screenrc文件中的配置,以便每个新的screen窗口都有自己的命令历史记录:

具有自己命令历史记录的默认Screen窗口

要打开一组带有各自命令历史记录文件的默认screen窗口,您可以将以下内容添加到~/.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'

确保新窗口有自己的命令历史记录

默认的屏幕设置意味着您使用Ctrl+a cCtrl+a Ctrl+c创建一个新窗口。然而,如果您在~/.screenrc文件中只使用以上内容,则这些窗口将使用默认的~/.bash_history文件。为了解决这个问题,我们将覆盖创建新窗口的键绑定。请在您的~/.screenrc文件中添加以下内容:

bind c screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'
bind ^C screen bash -ic 'HISTFILE=~/.bash_history.${WINDOW} bash'

现在当您创建一个新的屏幕窗口时,实际上是启动了一个bash shell,并将HISTFILE环境变量设置为包含当前屏幕窗口编号($WINDOW)的内容。
具有相同窗口编号的屏幕会话将共享命令历史文件。
在执行时向$HISTFILE写入命令
正常情况下,历史记录只有在退出shell / screen窗口时才写入$HISTFILE文件。但是,如果您希望命令在执行后立即写入历史记录文件,并立即对具有相同窗口编号的其他屏幕会话可用,则可以将以下内容添加到您的~/.bashrc文件中:
export PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND}"

这是最接近我想要的,但是...我正在尝试找到一种将所有内容保存到一个历史文件中的方法。如果您将它们嵌入到上面的“screen”命令中,HISTSIZE等似乎不会生效。 - beroe

8

screen 不会保留您输入的命令历史记录。您的 shell 可能会保留历史记录。由于您使用的是 bash,因此可以使用 history 命令。

screen 看起来有一个粗略的历史搜索近似值(它只是在滚动缓冲区中搜索命令行)。请参阅 screen 手册中的“history”命令(默认绑定为 C-a {)。


1
你的意思是在同一会话中的不同窗口(或可能还包括不同的会话)吗?有可能。这将涉及解析目标窗口的滚动缓冲区。但我对如何以编程方式访问screen并不熟悉。你可以尝试阅读man页面以获取有关如何执行此操作的信息。 - chepner

3

@technosaurus是正确的。$HISTFILE在bash退出时被写入,因此您可以退出一个bash会话,然后启动一个新的会话,历史记录应该通过文件得以保留。

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

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


2
当您退出终端(或shell)时,shell会将其历史记录写入$HISTFILE,因此要在另一个终端中获取其历史记录,您可以在要获取历史记录的终端中键入“exit”,然后它将被写入。
cat $HISTFILE
#or tac, less, $EDITOR, ... depending on how you want to "access" it

这只是在“exit”时编写的吗? - hexacyanide
1
据我所知,在此之前它会存储在内存中,最多保留$HISTSIZE行记录,当它写入时,将历史文件保留在$HISTFILESIZE行记录的最大值。 - technosaurus
我忘记了 shopt -s histappend,请参考:http://unix.stackexchange.com/questions/6501/why-would-anyone-not-set-histappend-in-bash - technosaurus

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

1
但请注意:这将记录输出和输入。 - abalter

1
我将下面的行添加到我的 .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_history。

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


0

history会显示所有的历史命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接