烦人的通知

作者:Kyle Rankin

2011 年 2 月刊中,我撰写了关于 screen,控制台窗口管理器,以及我如何配置其硬状态行以在我的终端窗口底部显示通知的文章。尽管有些人喜欢他们的桌面环境在收到新电子邮件或 IM 时弹出通知,但由于我大部分时间都在 screen 中度过,它集中了我的注意力,因此将重要通知放在那里是有意义的。在那篇2011 年 2 月的文章中,我介绍了如何设置硬状态行,并演示了我用来显示何时有新电子邮件的自定义脚本。

在本文中,我扩展了关于 screen 通知的主题,介绍了一个我发现非常有用新的通知脚本。自从我拥有了不止少数的服务器以来,我就依赖于像 Nagios 这样的监控程序来跟踪服务器的健康状况。尽管监控软件有其自身的通知方法,通过电子邮件或 SMS,但我发现将我当前的 Nagios 健康状况直接显示在我的 screen 会话中很有价值。它不仅为我的邮件通知提供了一个备份,而且还节省了我一直打开浏览器中的 Nagios 窗口的时间。

如果您是 screen 的新手,并且还没有设置自定义的硬状态行,请先查看我的2011 年 2 月文章,以便快速入门。我假设您已经设置了一个基本的 .screenrc 文件,而不是从头开始重新讨论如何配置 .screenrc 文件,相反,我将跳过如何将这个 Nagios 脚本添加到您现有的 screen 会话中。

Screen 抓取用于 Screen

当我着手编写这个脚本时,我意识到有很多不同的方法可以捕获 Nagios 当前的健康状况。尽管我没有花太多时间研究它,但我认为我可以查询更底层的 API,但老实说,我真正想要的只是知道 Nagios 是否一切正常(绿色)或有任何警告或严重警报(黄色或红色),以及如果有,有多少。为了实现这一点,我决定最简单的方法是抓取其中一个 Nagios 状态页面以获取我需要的信息。老实说,只要它有一个 Web 界面,并且您有足够的正则表达式技巧来解析 HTML 以获取您需要的数据,这种相同的方法应该非常适用于您可能使用的任何监控程序。

我最初编写这个脚本是为了,如果 Nagios 状态正常,它将打印出来,如果有任何严重或警告警报,它将输出这些统计信息。我意识到我希望 screen 以绿色打印正常,黄色打印警告,红色打印严重警报。这样,即使我没有直接看着我的终端,我也可能会注意到问题。为了实现这一点,我实际上需要在 screen 中运行该脚本三次。

下面的脚本只接受两个参数:要轮询的 Nagios 主机(如果使用用户名和密码,则为可选)以及要报告的状态类型。我选择了颜色代码绿色、黄色和红色分别代表正常、警告和严重状态。我发现 http://nagioshostname/cgi-bin/nagios3/tac.cgi 页面是最容易抓取的,并且包含了我脚本所需的所有信息


#!/usr/bin/perl

# usage: nagios_scraper.pl [user:password@]nagios_host STATUS
# where STATUS is green, red, yellow, or all

$nagios_host=shift;
$show=shift;

open TAC, "wget --timeout=2 -q -O -
 ↪http://$nagios_host/cgi-bin/nagios3/tac.cgi |"; @tac = <TAC>;
close TAC;

foreach $line (@tac){
   if   ($line =~ /(\d+) Down/){        $hosts_down = $1; }
   elsif($line =~ /(\d+) Unreachable/){ $hosts_unreachable = $1; }
   elsif($line =~ /(\d+) Up/){          $hosts_up = $1; }
   elsif($line =~ /(\d+) Pending/){     $hosts_pending = $1; }
   elsif($line =~ /(\d+) Critical/){    $services_critical = $1; }
   elsif($line =~ /(\d+) Warning/){     $services_warning = $1; }
   elsif($line =~ /(\d+) Unknown/){     $services_unknown = $1; }
   elsif($line =~ /(\d+) Ok/){          $services_ok = $1; }
   elsif($line =~ /(\d+) Pending/){     $services_pending = $1; }
}

# remove the username and password from the output
$nagios_host =~ s/.*\@//;

if($show eq "green" && ($hosts_down == 0 && $services_critical == 0
 ↪&& $services_warning == 0)){
   print "$nagios_host: OK";
}
elsif($show eq "red" && ($hosts_down > 0 || $services_critical > 0)){
   print "$nagios_host: ${hosts_down}D ${services_critical}C ";
}
elsif($show eq "yellow" && $services_warning > 0){
   print "$nagios_host: ${services_warning}W ";
}
elsif($show eq "all"){
   print "${hosts_down}D ${hosts_up}U ${services_critical}C
   ↪${services_warning}W ${services_ok}OK";
}

正如您所看到的,我实际上收集了比我最终使用的更多的统计信息,以防万一我想稍后参考它们。这个脚本中需要注意的重要一点是,在每种绿色、红色和黄色状态中,我只在有该状态的内容要打印时才打印。这至关重要,因为我不想使我的硬状态行混乱,并且我希望只在真正需要我注意时才看到黄色或红色文本。

将此脚本命名为 nagios_scraper.pl,将其放在 /usr/local/bin 中供所有人使用,或放在您用户的 ~/bin/ 目录中,确保它是可执行的,然后针对您的 Nagios 服务器对其进行测试,以确保您的语法正确。例如,如果您没有为 Nagios 设置用户名或密码,并且您的 Nagios 服务器名为 naggyhost,您将键入以下命令来测试一切是否正常


$ /usr/local/bin/nagios_scraper.pl naggyhost green

键入以下内容以测试严重警报


$ /usr/local/bin/nagios_scraper.pl naggyhost red

或者,键入以下内容以测试查看所有状态


$ /usr/local/bin/nagios_scraper.pl naggyhost all

我建议您为您 Nagios Web 访问设置用户名和密码(如果您尚未设置)。因为您用于此脚本的用户名和密码最终将以纯文本形式出现,所以我建议为 Nagios Web 界面设置一个帐户,该帐户可以登录,但只能查看 Nagios 状态,并且不能提交任何更改(如维护模式和确认)。假设我在 naggyhost 上设置了一个名为 readonly 的帐户,密码为 n0wr1t3。我将像这样调用脚本


$ /usr/local/bin/nagios_scraper.pl readonly:n0wr1t3@naggyhost red

同样,如果脚本在其中一种模式下不提供任何输出,则可能只是意味着该状态当前不适用。如果您想确定地测试这一点,请使用 all 参数而不是 green、yellow 或 red 运行脚本,以查看完整状态。

我们将,我们将,Nag 你

一旦您测试了脚本并使其工作,下一步就是将其添加到您的 ~/.screenrc 中。第一步是在 ~/.screenrc 中添加三个新的反引号配置行,这将分别使用 green、red 和 yellow 状态调用 nagios_scraper.pl。在我的例子中,我假设您可能定义了一些反引号命令,所以我从命令 110 开始


backtick 110 27 27 /usr/local/bin/nagios_scraper.pl
 ↪readonly:n0wr1te@naggyhost red
backtick 111 61 61 /usr/local/bin/nagios_scraper.pl
 ↪readonly:n0wr1te@naggyhost yellow
backtick 112 73 73 /usr/local/bin/nagios_scraper.pl
 ↪readonly:n0wr1te@naggyhost green

我已经将每个命令设置为以不同的时间间隔运行。我希望比警告或一切正常时更频繁地检查严重警报,所以我每 27 秒运行一次带有 red 参数的命令。然后我每 61 秒和 73 秒运行一次带有 yellow 和 green 的命令。请注意,我将这些间隔设置为奇数时间。我已经意识到错开我的 screen 通知脚本的价值,这样它们就不会冒着同时运行的风险,因此为了帮助实现这一点,我尝试选择奇数间隔。

一旦您定义了反引号行,下一步就是将它们添加到您的硬状态字符串中,以便它们以绿色、黄色和红色显示。在我的例子中,我粘贴了


%{+b r}%110`%{+b y}%111`%{= g}%112`

以便我从之前的文章修改的硬状态字符串将是


hardstatus string '%{= w}%Y-%m-%d %c | %l | %101`|
 ↪%{+b r}%110`%{+b y}%111`%{= g}%112`'

现在保存您对 ~/.screenrc 的更改,然后启动一个新的 screen 会话,或者键入 Ctrl-A : 并键入 source ~/.screenrc 以将这些更改加载到您现有的 screen 会话中。图 1 和图 2 显示了硬状态行在状态正常或存在严重警报时的外观。

图 1. 一切正常。

图 2. 一个主机宕机警报,带有五个严重服务。

当我深入研究 screen 通知时,最让我惊讶的是,一旦您掌握了窍门,向列表中添加新脚本是多么简单。即使您不使用 screen,修改脚本以使其输出到桌面通知也不会太困难(有关详细信息,请参阅我的2009 年 12 月专栏)。

Kyle Rankin 是 Linux Journal 的技术编辑和专栏作家,也是 Purism 的首席安全官。他是 Linux Hardening in Hostile NetworksDevOps TroubleshootingThe Official Ubuntu Server BookKnoppix HacksKnoppix Pocket ReferenceLinux Multimedia HacksUbuntu Hacks 的作者,也是许多其他 O'Reilly 书籍的贡献者。Rankin 经常在 BsidesLV、O'Reilly Security Conference、OSCON、SCALE、CactusCon、Linux World Expo 和 Penguicon 等会议上就安全和开源软件发表演讲。您可以在 @kylerankin 上关注他。

加载 Disqus 评论