19 December 2019

logwatchでsyslogファイルの解析やhddのS.M.A.R.T.データ出力を行う

logwatchの標準設定ファイルに含まれていないログ解析対象を追加する方法

/var/log/syslogからエラー行を抽出する

追加すべきファイルは次の3つ

/etc/logwatch/conf/services/zzz-syslog.conf
/etc/logwatch/conf/logfiles/zzz-syslog.conf
/etc/logwatch/scripts/services/zzz-syslog

設定ファイル名に zzz- と付けているのは、他のデフォルトで存在する設定ファイルと見分けるため。設定ファイルはどんな名前でも構わない。

それぞれ次のような内容で記述する

/etc/logwatch/conf/services/zzz-syslog.conf
Title = "Syslog Log"
LogFile = zzz-syslog

解析結果の先頭行に付けるタイトル文字列(Title)と、解析対象の検索条件を設定する設定ファイル名(LogFile)をここに記述する。

/etc/logwatch/conf/logfiles/zzz-syslog.conf
LogFile = /var/log/syslog
LogFile = /var/log/syslog.*[0-9]
Archive = /var/log/syslog.*[0-9].gz

ここでは、syslogのログ・ローテーションで作成される過去のファイルの検索パスも設定しておく。

/etc/logwatch/scripts/services/zzz-syslog
#!/usr/bin/perl
# Syslogよりエラーの行を抽出する
# (syslogファイルの検索パスは/etc/logwatch/conf/logfilesの設定ファイルに記述)
 
use strict;
use warnings;
use Digest::MD5;
# debug用 (Time::Piece::strftime)
#use Time::Piece;
 
# Logwatch の dates の使用宣言
use Logwatch ':dates';
 
# 除外する行に含まれる「キーワード」を配列で複数指定可能
#my @ignore_strings = ("GL command", "Fatal IO error");
my @ignore_strings = ();
# 重複行を検出するため、各行のmd5を格納する配列(初期状態は空で)
my @message_md5_db = ();
 
# 日付フィルタの文字列(例: Feb 25) 前日の月日が設定される
my $SearchDate = TimeFilter("%b %d");
 
#### debug (○○日前のログを対象) ####
#my $current_time = localtime() - 2*24*60*60;
#$SearchDate = $current_time->Time::Piece::strftime("%b %d");
####
 
print "Logwatch Date filter : $SearchDate\n";
 
# ログファイルを1行づつ読み込み処理します。
SYSLOG_LINE: while (defined(my $line = )) {
    # 指定日を抽出
    if ($line =~ /$SearchDate/) {
        chomp($line);
        # error と fatal が含まれる行を抽出
        if ($line =~ /error/i || $line =~ /fatal/i) {
        # 特定「キーワード」が含まれたら除外
        foreach my $ignore_string (@ignore_strings){
            if($line =~ /$ignore_string/i) { next SYSLOG_LINE; }
        }
        # 現在行のMD5値を算出 (先頭から33文字飛ばし、そこから20文字対象)
        my $md5_str = Digest::MD5::md5_hex(substr($line, 33, 20));
        # 過去に出現した行のMD5と一致すればこの行は読み飛ばす
        next SYSLOG_LINE if grep { $_ eq $md5_str } @message_md5_db;
        # 現在行を出力する
        print $line."\n";
        # 現在行のMD5値を配列に格納
        push(@message_md5_db, $md5_str);
        }
    }
}

ハードディスクのS.M.A.R.T.データを出力する

ログファイルからではなく、コマンドの実行結果を出力する場合は次のような設定ファイルとなる。

/etc/logwatch/conf/services/zzz-smartctl.conf
Title = "smartctl output"
LogFile = NONE
$target_disk = '/dev/sda';

ここでは、対象のログファイルは無い(LogFile = NONE)という設定となる

/etc/logwatch/scripts/services/zzz-smartctl
#!/usr/bin/perl
 
# conf/scripts 以下の環境設定ファイルから文字列target_diskを読み込む
my $target_disk = $ENV{'target_disk'} || '';
# コマンドの組み立て
my $command = '/usr/sbin/smartctl --log=scttemp --log=xerror --log=devstat ' . $target_disk;
# コマンドを実行し、文字列$outputに代入する
my $output = qx($command);
# 出力
if ($output) {
   print $output;
}

温度ログと、S.M.A.R.T.データの出力を行う設定としている。