死活監視

Pingで死活監視を行って、NGだったらメールを送信させたいなぁ・・・と思ったんだが。


普通に考えれば、ExPing辺りを使って死活監視を行ってメール送信のコマンドと組み合わせれば十分なんだけど。自由に使える環境にWindows機が無かったんで、Perl(5.8)でサクっと書いてみた。(実はBシェルで十分動く状態だったんだけど・・・何となくPerlで書き直した)



Net::SMTPとNet::Pingは必須なので、インストールします。
# perl -MCPAN -e shell
cpan> install Net::SMTP
cpan> install Net::Ping
逆にWindows+ActivePerlでもNet::SMTPとNet::Pingが入っているなら動くはず・・・。


#!/usr/bin/perl
# ================================================================
# ネットワーク死活監視
# Version 0.1
# ================================================================

use strict;
use Net::SMTP;
use Net::Ping;

# ================================================================
# パラメータ
# ================================================================

# 監視対象のホスト
my @host = ('192.168.100.1', '192.168.100.2', '192.168.100.3');
my %hostname = (
    "192.168.100.1" => "Server-1",
    "192.168.100.2" => "Server-2",
    "192.168.100.3" => "Server-3"
);

# pingのタイムアウト時間(秒)
my $timeout = 2;

# pingが何回連続して失敗したらホストダウンと見なすか
my $retrycount = 3;

# pingの実行間隔(秒)
my $timer = 1;

# 再実行の間隔(秒)
my $waittimer = 10;

# ホストダウン通知の送信先メールアドレス(複数指定可能)
my @mailto = ('mailaddress@hogehoge.co.jp', 'mail2@hogehoge.ne.jp');

# ホストダウン通知のメール件名
my $subject = 'Server down!! Alert Mail';

# ホストダウン通知の送信元メールアドレス
my $from = 'kanshi@hogehoge.co.jp';

# SMTPサーバのホスト名
use constant SMTPsvr => 'localhost';

# SMTPサーバに送信するHeloコマンドのドメイン名
use constant SMTPdomain => "hogehoge.co.jp";

# ログファイル名
my $filename = "server-ping.log";


# ================================================================
# プログラム
# ================================================================

my %count ;
my $ret ;
my $TRUE = 1;

# ================================================================
# メインルーチン
# ================================================================
while ( $TRUE ) {
    foreach ( @host ) {
        my $date = &date;
        my $msg = $date." ".$hostname{ $_ }."(".$_.")\n"."ping failure!!\n";
        my $ping = Net::Ping->new("icmp");
        print $date." ".$hostname{$_}."(".$_.") ";
        $ret = $ping->ping($_, $timeout);
        $ping->close();
        if ( ! $ret ) {
            $count{ $_ }++;
            if ( $count{ $_ } >= $retrycount ) {
                &logg( $msg );
                &smail( $msg );
                $count{ $_ } = 0;
                print "failure!!\n";
            } else {
                print "retry(".$count{ $_ }.")\n";
            }
        } else {
            $count{ $_ } = 0;
            print "ok!!\n";
        }
        sleep( $timer );
    }
   
    sleep( $waittimer );
}


# ================================================================
# メール送信のサブルーチン
#
# パラメータ     ( メッセージ文字列 )
# 戻り値        なし
# ================================================================
sub smail{
    my ( $msg ) = @_;
    my $to;
    my $date = &date;

    foreach $to ( @mailto ) {
        my $smtp = Net::SMTP->new(SMTPsvr, Hello=>SMTPdomain);
        $smtp->mail($from);
        $smtp->to($to);
        $smtp->data();
        $smtp->datasend("Date:$date\n");
        $smtp->datasend("From:$from\n");
        $smtp->datasend("To:$to\n");
        $smtp->datasend("Subject:$subject\n");
        $smtp->datasend("Content-Transfer-Encoding: 7bit\n");
        $smtp->datasend("Content-Type: text/plain;charset=\"ISO-2022-jp\"\n\n");
        $smtp->datasend("$msg\n");
        $smtp->dataend();
        $smtp->quit;
    }
}



# ================================================================
# ログ記録のサブルーチン
#
# パラメータ     ( メッセージ文字列 )
# 戻り値        なし
# ================================================================
sub logg {
    my ( $msg ) = @_;
    my $date = &date;
    open( FH, ">> $filename");
    print FH $msg;
    close( FH );
}



# ================================================================
# 日時表示のサブルーチン
#
# パラメータ    なし
# 戻り値        現在日時(文字列)
# ================================================================
sub date {
    $ENV{'TZ'} = "JST-9";
    my($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time);
    my @week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
    my @month = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
    my $d = sprintf("%s, %d %s %04d %02d:%02d:%02d +0900 (JST)",
        $week[$wday],$mday,$month[$mon],$year+1900,$hour,$min,$sec);
    return $d;
}


これに適当に名前を付けて(kanshi.plとでも)、
# perl kanshi.pl
もしくは
# chmod +x kanshi.pl
# ./kanshi.pl
とかして実行すれば動く。本当に最低限動くというだけだが。
止める方法は無いので、Ctrl-Cを押すか、Ctrl-Zでバックグラウンドに持って行って、jobsで確認して、kill %1とかで殺してしまえばいい。


とりあえずはこんなもんで十分かな・・・と。



Perlは簡単なので単目的のものをさらっと作るのは楽だなぁ。。。