読者です 読者をやめる 読者になる 読者になる

ログ監視スクリプト

syslog-ngからこんな感じに起動してエラー発生時に指定の処理を行うスクリプトを書いた。

destination d_log_handle { program("cd /home/mikeda/bin;./log_handle.pl match_list"); };
log { source(s_sys); destination(d_log_handle); };


仕様は
・エラー定義ファイルからエラー概要とエラー条件のペアを取得
・標準入力からログを受け取り
・エラー条件にマッチする場合、エラー処理関数にホスト名、エラー概要、付加情報を渡す


エラー定義ファイルの例。カッコで括った部分が付加情報としてエラー処理関数に渡される。

#ファン障害
Fan Fail

#電源障害
Power Supply Error:.*(PS\d)
    
#ディスク障害
Disk fail.*(box \d):(bay \d)

#不明な障害
(.*(?i:error:fail).*)


プログラム本体

#! /usr/bin/perl
use strict;

### エラー処理関数は複数指定可能
my @err_funcs = (\&err_print, \&err_mail, \&err_snmptrap);
my @errors = ();
chomp(my $hostname = `hostname`);


### エラー定義ファイル読み込み
chomp(my @lines = grep !/^\s*(#|$)/, <>);
while(@lines){
  my ($desc, $reg) = (shift @lines, shift @lines);
  push @errors, [$desc, qr/$reg/];
}
print "@$_\n" for(@errors);


### ログ監視突入
while(<STDIN>){
  for my $e (@errors){
    my($desc, $reg) = @$e;

    next unless my @options = /$reg/;
    @options = () unless defined $1;

    &$_($hostname, $desc, @options) for @err_funcs;
    last;
  }
}
      

### エラー処理関数たち
sub err_print{
  my($hostname, $desc, @options) = @_;
  print "$hostname でエラー発生!!!\nDESC: $desc\n";
  print "MORE :", join(',',@options), "\n" if @options;
}

sub err_mail{
  my($hostname, $desc, @options) = @_;
  print "メール送ったり:$desc\n";
}

sub err_snmptrap{
  my($hostname, $desc, @options) = @_;
  print "トラップなげたり:@options\n";
}



しかし書いた直後に気づいたんだが、swatchでも全く同じことができる!!!
$1とか使った後方参照できるのか、そりゃPerl書かれてるもんな・・・