Nagios Core 3系でコマンドラインからステータスとアラート履歴を取得する

開発

はじめに

Nagiosの監視状況を確認したいとき、通常はWebブラウザでダッシュボードを開いて確認したい場合があります。ですが他のスクリプトと組み合わせて何かしたいなという場合にブラウザベースでデータを取得して整形したりするのが手間だったりします。
「コマンドラインからサクッとステータスが取れたらな」と思って調べた結果、2つの便利スクリプトができたのでまとめておきます。

環境

  • Nagios Core 3.2.3(CentOS 6系)
  • Nagios CGI: /usr/lib64/nagios/cgi/
  • ログディレクトリ: /var/log/nagios/

注意: Nagios Core 4系以降であれば statusjson.cgi というJSON APIが使えるが、3系にはない。今回はそれが使えない環境での話。同じコマンドでCGIのパスは違うがNagios Core 4系でも使えることは確認済み

アラート履歴の取得

ログファイルの構造

Nagiosのログはこんなパスに格納されています。

/var/log/nagios/nagios.log # 現在のログ
/var/log/nagios/archives/nagios-MM-DD-YYYY-00.log # アーカイブ(日次ローテーション)

アーカイブのファイル名は nagios-05-25-2026-00.log のように日付が入っているので、直近30日分のファイルを絞り込めます。
ログの中身はこんな形式。タイムスタンプはUNIXタイム。

[1778080216] SERVICE ALERT: example.com;SMTP;CRITICAL;SOFT;1;接続を拒否されました

このままだと日時がわかりにくいので date -d @タイムスタンプ で変換して人間が読める形に整形します。

スクリプト

#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(strftime);

sub get_nagios_alerts {
  my ($hostname) = @_;

  # 直近30日分のアーカイブファイルを取得
  my @files = `find /var/log/nagios/archives/ -name "nagios-*-*.log" -mtime -30`;
  push @files, "/var/log/nagios/nagios.log\n";
  chomp @files;

  for my $file (sort @files) {
    open(my $fh, '<', $file) or next;
    while (<$fh>) {
      next unless /\Q$hostname\E/;
      next unless /ALERT/;
      next if /;OK;/;
      if (/\[(\d+)\] (.*)/) {
        my ($ts, $body) = ($1, $2);
        my $dt = strftime('%Y-%m-%d %H:%M:%S', localtime($ts));
        print "$dt $body\n";
      }
    }
    close($fh);
  }
}

my $hostname = $ARGV[0] or die "Usage: $0 \n";
get_nagios_alerts($hostname);

/usr/local/bin/get_nagios_alerts として保存して chmod +x しておきます。

実行例

$ /usr/local/bin/get_nagios_alerts example.com
2026-05-08 12:30:16 SERVICE ALERT: example.com;SMTP;CRITICAL;SOFT;1;接続を拒否されました
2026-05-11 08:10:06 SERVICE ALERT: example.com;POP;CRITICAL;SOFT;1;接続を拒否されました
2026-05-19 03:02:20 SERVICE ALERT: example.com;SUBMISSION;CRITICAL;SOFT;1;(Service Check Timed Out)
2026-05-19 03:04:20 SERVICE ALERT: example.com;POP;CRITICAL;SOFT;1;CRITICAL - Socket timeout after 30 seconds

現在ステータスの取得

まずcurlを試した

最初は単純に curl でWebUIのHTMLを取得してパースしようとしました。

curl -s -u nagiosadmin:password \
  "http://nagios.example.com/nagios/cgi-bin/status.cgi?host=example.com" \
  | grep -A3 'statusOk\|statusCritical'

一応動きますが、HTML構造がネストしていてパースが面倒だし、認証情報をコマンド履歴に残すのはどうかなという感じです。

CGIをローカルから直接呼ぶ

Nagiosの各CGIは /usr/lib64/nagios/cgi/ (Nagios4系は /usr/lib64/nagios/cgi-bin/) に実行ファイルとして置かれています。試しに直接実行してみると:

$ /usr/lib64/nagios/cgi/status.cgi
getcgivars(): Unsupported REQUEST_METHOD -> ''
In order to do that, you need to set the REQUEST_METHOD environment
variable to either "GET", "HEAD", or "POST".

環境変数で REQUEST_METHOD や QUERY_STRING を渡せばいいらしいということがわかります。実際に試すと動きました。

REQUEST_METHOD=GET \QUERY_STRING="host=example.com" \
REMOTE_USER=nagiosadmin \
/usr/lib64/nagios/cgi/status.cgi

HTMLが出力されるので、あとはPerlでパースするだけ。ネットワーク越しのHTTP通信もBasic認証も不要なので、ローカルで動かす用途にはこちらの方がクリーンですね。

スクリプト

#!/usr/bin/perl
use strict;

my $hostname = $ARGV[0] or die "Usage: $0 \n";

my $html = `REQUEST_METHOD=GET QUERY_STRING="host=$hostname" REMOTE_USER=nagiosadmin /usr/lib64/nagios/cgi/status.cgi`;

while ($html =~ /service=[^>]+>([^<]+)<\/A>.*?([^<]+)<\/TD>.*?]*>[^<]+<\/TD>.*?]*>[^<]+<\/TD>.*?]*>[^<]+<\/TD>.*?]*valign[^>]*>([^<&]+)/gsi) {
  my ($name, $status, $info) = ($1, $2, $4);
  $info =~ s/^\s+|\s+$//g;
  printf "%-15s %-12s %s\n", $name, $status, $info;
}

/usr/local/bin/nagios_status として保存します。

実行例

$ /usr/local/bin/nagios_status example.com
DISK            OK           SNMP OK - 57
FTP             OK           FTP OK - 0.028 second response time on port 21
HTTP1           OK           HTTP OK: HTTP/1.1 200 OK - 203 bytes in 0.030 second response time
MAILDELAY       OK           delay OK - 0.54 sec, threshold = 600 sec
PING            OK           PING OK - Packet loss = 0%, RTA = 0.99 ms
POP             OK           POP OK - 0.027 second response time on port 110
SMTP            OK           SMTP OK - 0.037 sec. response time
SSH             OK           SSH OK - OpenSSH_5.3 (protocol 2.0)
SUBMISSION      OK           SMTP OK - 0.037 sec. response time

まとめ

作成した2つのコマンド:

コマンド 用途
nagios_status <hostname> ホストの現在のサービス状態を一覧表示
get_nagios_alerts <hostname> 直近30日分のアラート履歴を表示

障害通報が来たときに get_nagios_alerts でいつ何が起きたかを把握し、nagios_status で今の状態を確認するという使い方が便利ですね。
あるいは月のレポートを作成したい場合にも使えると思います。
Nagios 4系以降なら statusjson.cgi を使ったほうがパースも楽でおすすめですが、古い環境にはこの方法が使えます。同じく古いNagios環境で困っている人の参考になれば。