Screen 的强大会话

作者:Adam Lazur

Screen 是一个终端复用器,允许您通过一个物理终端管理多个进程。每个进程都有自己的虚拟窗口,您可以在虚拟窗口之间切换,与每个进程进行交互。由 screen 管理的进程在其窗口不活动时继续运行。

到目前为止,所描述的 screen 功能并非都那么令人兴奋或新颖。事实上,已经有一些 X11 终端应用程序提供了此功能(konsole 和 multi-gnome-terminal)。Screen 与其他终端应用程序的区别在于 screen 提供的一些核心功能。

Screen 提供了从会话中分离并在稍后重新连接到会话的能力。当从会话中分离时,screen 管理的进程将继续运行。然后,您可以在稍后重新连接到会话,您的终端仍然在那里,就像您离开时一样。

Screen 还为它管理的每个窗口维护单独的、可搜索的回滚缓冲区。您可以执行传统的“输入搜索词,我会为您找到它”的搜索,以及增量搜索。这是一个如此明显的功能,令人惊讶的是,更多的终端模拟器没有提供它。

screen 的其他值得注意的功能包括可配置的按键绑定、utf8 和多字节字符集支持、多重附加、可配置的输入和输出转换、输入和输出过滤器、具有访问控制列表 (ACL) 的多用户支持以及日志记录。

与 Screen 交互

在实际运行 screen 之前,重要的是要了解如何与其交互。Screen 将所有输入的文本发送到当前窗口,但命令字符除外。默认命令字符是 Ctrl-A(同时按下 Ctrl 键和 A 键)。Screen 手册页使用 C-,Emacs 风格,表示 Ctrl-。

命令字符用于通知 screen 您想要控制 screen 本身,而不是当前窗口中的应用程序。在命令字符之后按下的键指定您想要执行的 screen 命令。

表 1 显示了一些更有用的命令及其按键绑定。

表 1. 命令及其按键绑定

对于许多常用命令,按键的 Control 版本也绑定到该命令。一个例子是 Ctrl-A C 和 Ctrl-A Ctrl-C 用于创建窗口。

要将 Ctrl-A 发送到应用程序而不被 screen 拦截,您可以按 Ctrl-A A。如果愿意,可以将命令字符更改为备用键。通常,Emacs 用户通过在其 .screenrc 中添加 escape Bb 将命令字符更改为 Ctrl-B。以下示例使用 Ctrl-A,因为它是默认值。

正如您可能期望的那样,.screenrc 是您主目录中的每个用户的配置文件,而 /etc/screenrc 是适用于所有用户的系统范围的配置文件。

窗口基础知识

既然您了解了与 screen 交互的基础知识,我们可以通过一个典型的 screen 会话示例来逐步了解 screen 的基本原理。Screen 最典型的用途可能是控制您拥有 shell 登录权限的远程计算机上的终端。

因此,对于那些在家中跟随操作的人,请登录到安装了 screen 的远程主机。如果您没有要 ssh 连接的远程主机,您可以安装 screen 并 ssh 连接到 localhost。大多数发行版都提供了 screen 的软件包。

您现在位于远程计算机上的 shell 提示符下。在提示符下键入 screen。您应该会看到一个启动画面,显示一些信息,说明 screen 在 GPL 下,在哪里报告错误等等。您可以按空格键绕过此画面(您可以使用 .screenrc 中的 startup_message off 永久禁用此启动画面)。接下来,您应该到达另一个 shell 提示符,这个提示符在 screen 内部运行。

在 screen 内部运行的新 shell 应该像您的第一个 shell 一样运行。如果您执行 printenv,您可能会注意到设置了一些新的环境变量。Screen 将 TERM 设置为 screen—每个 screen 窗口都提供自己的 vt100 兼容的虚拟终端。变量 WINDOW 设置为虚拟窗口号,变量 STY 设置为您的会话名称。稍后我将详细解释最后两个。

到目前为止,这个单独的 shell 的工作方式与您习惯在远程计算机上工作的方式完全相同。为了本示例的目的,假设我们正在从 screen 发行站点 ftp.uni-erlangen.de/pub/utilities/screen 下载当前版本的 screen(截至撰写本文时,screen 3.9.13)。当此文件正在下载时,您决定利用空闲时间清理您的主目录。如果您没有使用 screen,您将不得不打开另一个 xterm 并 ssh 连接到远程计算机。使用 screen,只需按 Ctrl-A C 即可创建一个新的 screen 窗口,其中包含一个新的 shell 进程。

到目前为止,您有一个 FTP 客户端和一个 shell 正在忙着整理您的主目录。您可以使用 Ctrl-A P 转到上一个窗口来检查原始 FTP 窗口中的下载进度。您可以使用 Ctrl-A N 返回到您的 shell。

当您检查下载进度时,它尚未完成(screen 下载不需要那么长时间,但为了演示,我们假设它需要)。是时候回到您凌乱的主目录了,对吗?在执行此操作之前,请按 Ctrl-A Shift-M 以监视当前窗口的输出。现在,当 FTP 窗口中有活动时,screen 将通知您。不再需要来回切换窗口来检查下载进度。这也适用于相反的情况;使用 Ctrl-A _ 监视静默(默认情况下为 30 秒)。监视静默对于长时间编译作业或其他喷出信息的事情很有用。

您可以继续生成新的 shell 并在远程计算机上并行执行操作。打开几个窗口后,很难跟踪哪个窗口在哪里。这就是窗口列表发挥作用的地方。按 Ctrl-A “,您将看到当前打开窗口的列表。使用 J 和 K 键导航列表。在条目上按 Enter 键将使其成为当前窗口。默认情况下,窗口名称不是那么具有描述性。您可以使用 Ctrl-A Shift-A 自己设置窗口名称来补救此问题。您可以自动设置这些标题,就像您在 xterm 中设置标题一样,方法是发送 Esc-K,然后是标题,然后是 Esc-\。很可能您可以调整特定于 shell 的配方,以使用上述转义序列设置 screen 窗口名称的 xterm 标题栏。

为了完成我们窗口化的基本演练,让我们关闭您现有的窗口。如果您退出 screen 生成的 shell,则窗口将自动删除。您可以使用 kill 命令(默认 Ctrl-A K)手动删除窗口。当您退出所有 screen 窗口时,screen 将退出。您也可以通过发出 quit 命令 (Ctrl-A \) 来告诉 screen 退出并杀死您的所有窗口。

会话

现在您正在创建新窗口并在它们之间来回切换,您可以并行启动许多操作。您可能有一些编辑器、一个 IRC 客户端和其他一些东西都在各自的窗口中运行。但是偶尔会发生灾难,您的网络连接断开(那些在家中仍然跟随操作的人可以杀死您的 SSH 客户端)。看起来是时候收拾残局并在远程计算机上重新启动您的所有应用程序了,对吗?使用 screen 则不然。

每次您在没有参数的情况下启动 screen 时,它都会创建一个新会话。这将生成两个进程:一个终端管理进程和一个客户端进程。客户端进程自动“附加”到终端管理进程。当您键入时,您输入的字符将发送到客户端,客户端将其发送到终端管理进程,然后终端管理进程将其发送到您的应用程序。

当您的网络连接断开时,客户端会捕获信号并从终端管理进程分离。终端管理进程继续管理您的终端,就好像什么都没发生一样。当您重新登录时,您可以通过在提示符下发出 screen -ls 来列出正在运行的会话。它应该显示类似于以下内容

There are screens on:
        24319.pts-9.hostname (Detached)
1 Sockets in /var/run/screen/S-youruserid.

这表明您的会话在您的连接断开时自动分离。

您可以通过几种方式重新连接到会话。您可以使用 screen -r sessionname 显式给出会话名称。您可以告诉它尽可能重新连接,否则通过运行 screen -R 启动新会话。或者您可以采用“尽一切努力获取 screen 会话”的方式并运行 screen -D -RR。最后一个选项将分离已附加的客户端并附加到列出的第一个会话。

当您运行这些命令之一时,您应该回到网络连接中断之前的位置。当您重新连接后,您可以继续工作,就好像什么都没发生过一样。

也可以多次附加到会话。如果您没有从另一台计算机关闭您的 screen 会话,或者您只是想并排显示来自同一会话的窗口,这将非常有用。您可以在附加时在 screen 的命令行选项中添加 -x 来进行多重附加。

最后,当一天结束,该回家时,您可以使用 Ctrl-A D 从您的会话中分离。当您第二天返回时,您可以重新连接,您将回到您离开的地方。

复制和粘贴/回滚模式

本文开头列出的主要功能之一是 screen 的可搜索回滚。这是一个我无法离开的功能。对于新的 screen 用户来说,它并不立即显而易见,但 screen 的回滚是通过复制命令访问的。(您可以使用 Ctrl-A [ 或通过 copy 命令进入复制模式。)导航按预期工作,可以使用方向键和 Page Up/Down 或 vi 移动等效项。搜索可以通过 / 和 ? 进行 vi 风格的搜索,也可以通过 Ctrl-S 和 Ctrl-R 进行增量搜索。可以使用 screen 命令 ignorecase yes 打开不区分大小写的搜索。如果您仅将复制模式用于回滚,则可以随时按 Esc 键退出。

要复制文本,请将光标移动到所需文本的开头,然后按空格键标记它。然后将光标定位在您想要的文本末尾,再次按空格键标记它。当您标记末尾时,文本将复制到 screen 的内部复制缓冲区中,并且复制模式将退出。您可以使用 Ctrl-A ] 将复制缓冲区中的文本粘贴到活动窗口中。

您应该了解的关于复制和粘贴模式的最后一件事是回滚缓冲区默认限制为 100 行。在我看来,这还不够。您可以通过在您的 .screenrc 中添加命令 defscrollback 1024 将其调整为更高的值(例如 1,024)。

使用 screenrc 打开窗口

我已经提到您可以在您的 .screenrc 中添加命令来更改 screen 的行为。这并不立即显而易见,但您可以在 screenrc 中放置任何 screen 命令。这非常有用,可以用于使用 screen 命令自动生成窗口。

此知识的一个典型应用是在 screen 启动时启动一组预定义的窗口。以下是一个示例 screenrc,它将执行此操作

# read in your normal screenrc
# before anything else
source $HOME/.screenrc
# now start opening windows
screen top
# it's possible to set the window title with
# the -t option
screen -t irc epic
# you can also specify the window number
# to launch in
screen -t mail 8 mutt
screen -t daemon 9 tail -f /var/log/daemon.log

如果您将其保存到 $HOME/.screenrc.multiwin,您可以通过运行 screen -c $HOME/.screenrc.multiwin 告诉 screen 使用它而不是您的普通 .screenrc。

您还可以从启动脚本启动更多面向系统的 screen 会话。系统 screen 会话的一个常见应用是串行控制台服务器。Screen 非常适合此任务,因为它内置了对串行终端和日志记录的支持。用于此目的的 screenrc 的注释示例是

# This assumes that serialuser has proper
# permissions to access the serial ports and to
# write to the log files specified in the screenrc.
# turn logging on for all windows
deflog on
# tell screen to log to /var/log/serial.$WINDOW
logfile /var/log/serial.%n
# open windows on the serial ports
screen /dev/ttyS0 38400
screen /dev/ttyS1 19200

如果您将此文件保存在 /etc/screenrc.serial 中,您可以使用运行以下命令的脚本在启动时启动它

su serialuser -c \
'screen -dmS serial -c /etc/screenrc.serial'
-dmS serial 选项告诉 screen 在分离模式下启动会话并将会话命名为“serial”。用户 serialuser 可以登录并附加到此会话,就像任何其他普通 screen 会话一样。如果首选,启动分离的 screen 也可以用于从 cron 作业启动 screen。

可以设置一个允许多个用户连接到它的系统范围的 screenrc。Screen 支持多用户模式,其中每个窗口都有 ACL,用于定义每个用户可以做什么和不能做什么。但是,多用户 screen 会话要求 screen 设置为 setuid root。由于此要求,我不会在入门文章中包含多用户 screen 会话的示例。如果您想设置多用户 screen 会话,请阅读 screen 文档,戴上您的“向复杂代码添加 setuid root 权限”的偏执狂帽子,并准备好尽可能严格地锁定所有内容。

作为第三个应用,您可以合并前两个示例,并通过 screenrc 启动系统范围的交互式程序。一个很好的用途是在启动时启动 mutella,一个基于 curses 的 gnutella 客户端。使用 screen,您可以启动此程序并偶尔连接到它以查看状态、运行查询等。

更多信息

您可以在 screen 文档中找到有关 screen 的更多信息。文档以 man 和 info 格式提供。我在浏览时更喜欢 info 格式,在搜索特定内容时更喜欢 man 页面,但这只是个人偏好。

还有一些面向 screen 用户的在线资源。首先是 Sven Guckes 的 screen 页面,网址为 www.math.fu-berlin.de/~guckes/screen。其次是在 groups.yahoo.com/group/gnu-screen 的有用的 screen 邮件列表。在您已用尽可用的文档后,邮件列表是您应该提出的第一个问题的地方。您必须订阅才能发帖。

Adam Lazur 是一位 Linux 顾问,从事从嵌入式 Linux 到 Beowulf 集群的各种工作。在业余时间,Adam 喜欢用第三人称来写自己。Adam 欢迎对本文的评论,请发送至 adam@lazur.org

加载 Disqus 评论