Hack 和 / - Screen 中的状态消息
如果您使用命令行有一段时间了,可能有人向您介绍过一个名为 screen 的程序。如果您不熟悉它,screen 允许您在同一个程序中管理多个控制台会话,因此您无需处理选项卡或多个终端窗口,只需按几个键即可在控制台会话之间切换。除此之外,screen 还允许您完全分离这些控制台会话,同时它们仍在运行,然后在稍后重新连接到它们。一个用途可能是在工作日快结束时在 screen 会话中启动一个可能需要一段时间的过程,从会话中分离,然后在当天晚上晚些时候在家重新连接以确保它已完成。
我将 screen 与 Irssi 一起用在我保持运行的服务器上,这样我可以始终登录到 IRC,并且只需从我碰巧使用的任何机器连接到该 screen 会话即可。我还将其他控制台会话保存在 screen 中,设置为 mutt 和 SSH 实例到各种服务器,这样我可以从同一个会话访问所有内容。老实说,我大部分时间都在 screen 会话中的计算机前度过。
因为我将大部分注意力都集中在一个 screen 窗口上,所以我发现利用 screen 中的状态行来通知我任何可能需要我注意的事情非常方便。状态行通常默认是关闭的;但是,一旦启用,它会在您的控制台底部占据一行。您可以将其配置为列出各种信息,从当前日期和时间等基本信息到您可以想象的任何 shell 程序的输出等复杂信息。
在 screen 中配置状态行很快就会变得非常复杂。存在一个强大的字符串转义语法,允许您控制状态行中所有项目的右对齐和左对齐以及着色。特殊的字符串转义还允许您指定当前时间、主机名和系统负载。描述所有这些选项很像第一次向某人描述 printf 语法。在这里我不再赘述所有这些,我建议您参考 screen 手册页中标题为 STRING ESCAPES 的部分。要到达那里,请键入man screen,一旦您进入手册页,请键入/^STRING ESCAPES,然后按 Enter。
在本专栏中,我将展示如何在 screen 中启用状态行并对其进行调整,使其显示一些基本的系统信息。最后,我将解释如何添加自定义脚本输出。如果您决定想要使用花哨的彩色状态行,我相信您会乐于尝试手册页中的所有选项。
每个用户的个人 screen 设置都在 ~/.screenrc 中配置,因此要启用基本状态行,您可以使用 hardstatus 配置选项。要创建显示“hello world”的状态行,请将以下行添加到您的 ~/.screenrc
hardstatus alwayslastline hardstatus string 'hello world'
现在当您启动 screen 时,您应该在窗口底部看到反相视频(即,您的前景色和背景色将反转)中的“hello world”。有些人喜欢这样,但如果您想要白色文本,请将 hardstatus 字符串更改为
hardstatus string '%{= w}hello world'
下次您加载您的 screen 会话时,文本将为白色。如果需要,您也可以从 screen 会话本身更改 .screenrc 并重新加载它。一旦您保存了对 .screenrc 的任何更改,只需按 Ctrl-a :(即先按 Ctrl-a,然后按 : 键),然后键入source ~/.screenrc,然后按 Enter。
既然状态行现在可以工作了,让我们使其显示更多有用的信息,例如当前日期和时间以及系统负载。将您的 hardstatus 字符串更改为
hardstatus string '%{= w}%Y-%m-%d %c | %l'
这看起来有点复杂,但让我们分解一下。%{= w}screen 的这一部分将前景色设置为白色。我可以用以下方式表示年、月和日%Y, %m和%d,在本例中,我在每个值之间添加了一个连字符 (-),以便更容易阅读。然后,我添加了一个空格和%c,它被扩展为当前时间。最后,我添加了一个 | 符号和一些空格作为填充,以及%l,它扩展为当前负载。
正如您在我的示例中看到的,screen 为您可能希望在状态行中获得的一些常见输出提供了一些字符串转义。它还允许您定义它可以运行的自定义命令,并在状态行上显示输出。您只需通过 backtick 选项在您的 .screenrc 中定义一个命令,然后在 hardstatus 字符串中引用该命令即可。例如,这是一个简单的 Perl 脚本,我编写它来解析fetchmail -c(它检查我的一个 IMAP 帐户是否有新消息)的输出。如果我的任何已定义文件夹有新消息,它会将它们用空格分隔输出。将以下脚本命名为 /usr/local/bin/new_mail_check.pl
#!/usr/bin/perl open FETCHMAIL, "/usr/bin/fetchmail -t 10 -c 2>/dev/null |" ↪or die "Can't run fetchmail: $! \n"; while(<FETCHMAIL>){ if(/^(\d+) messages \((\d+) seen.*?folder (.*?)\)/){ $m+=$1; $s+=$2; $f=$3; # you might have to change this regex depending on # how your IMAP server displays subfolders $f =~ s/INBOX\.//; } if($1 > $2){ $fs{$f} = $1 - $2; } } close FETCHMAIL; $t = $m - $s; if($t > 0){ foreach $folder (sort { $fs{$a}<=>$fs{$b} } keys %fs){ push @folders, "$folder:$fs{$folder}"; } } print join " ", @folders;
确保脚本是可执行的,然后将您的 ~/.screenrc 更改为以下内容
backtick 101 60 60 /usr/local/bin/new_mail_check.pl hardstatus alwayslastline hardstatus string '%{= w}%Y-%m-%d %c | %l | %101`'
第一行定义了一个 backtick 命令,它将被称为 101。后面的两个 60 定义了命令的生命周期和自动刷新时间(以秒为单位)。生命周期定义为输出被视为有效的秒数,之后如果遇到字符串转义,命令将再次运行。自动刷新值定义何时刷新 hardstatus 字符串的显示。对于我的 backtick 命令,我通常将这两个值定义为相同的值。在本例中,我每 60 秒检查一次新邮件。命令中的最后一个参数是您要运行的命令的完整路径。如果您需要指定任何参数,可以将它们放在命令之后。另请注意,我添加了%101`到我的 hardstatus 字符串的末尾。%`字符串转义会将指定的 backtick 输出放入状态中。在这种情况下,%101`会将我定义为 101 的 backtick 命令的输出放入其中。如果我想添加另一个命令,我会在我的 .screenrc 中添加另一个 backtick 行,并将其定义为 102。
那么,您接下来要做什么呢?嗯,除了使用所有字符串转义来着色您的状态行之外,您真正受到的限制只是您的 shell 脚本编写能力。例如,Irssi 有一个名为 fnotify 的程序,您可以使用它来将所有在 Irssi 中突出显示您的句柄的人记录到一个文件中。我编写了一个简单的脚本来从该文件中提取最后一行,解析它,并在我的状态栏上显示最后一位在 IRC 上与我交谈的人的日期和句柄。您还可以编写脚本来显示来自 Twitter 的信息、您喜爱网站的头条新闻、Nagios 警报摘要,甚至来自 fortune 命令的随机输出。但如果您像我一样,您将花费大部分时间调整所有颜色以及左右填充,以便您的状态看起来恰到好处。
Kyle Rankin 是旧金山湾区的系统架构师,也是多本书的作者,包括 The Official Ubuntu Server Book、Knoppix Hacks 和 Ubuntu Hacks。他目前是 North Bay Linux Users' Group 的总裁。