CentOS

2007/3/06 08:26 PM 更新

syslog-ng

OSやアプリケーションが出力するログを管理するシスログサーバとしてOS標準のsyslogdではなくsyslog-ngを導入する。
syslog-ngの特長は下記の通り。
 ・TCPポートを使用したLISTENが可能
 ・特定キーワードに合致した場合にプログラムを実行することが可能
 ・ユーザ権限での動作が可能

以前はsyslog-ng-1.6.6をインストールしていたが、2.0系のバージョンがリリースされているのでバージョンアップすることにする。
1.6系のsyslog-ngはlibolが必要だったが2.0系ではGLib2.0とEventLogが必要になる。
CentOSではGLib2.0がRPMであるので利用する。
# rpm -qa |grep glib2
glib2-2.4.7-1
glib2-devel-2.4.7-1
EventLogはsyslog-ngの公式サイトで入手可能。
$ wget http://www.balabit.com/downloads/syslog-ng/2.0/src/eventlog-0.2.5.tar.gz
$ tar xvzf eventlog-0.2.5.tar.gz
$ cd eventlog-0.2.5
$ ./configure
$ make
# make install
準備ができたところでメインのsyslog-ngをインストールする。
インストール時にeventlog.pcを見つけられないためエラーが発生してしまった。
PKG_CONFIG_PATHを設定することで対応可能。
./configure時に以下エラーが出る。
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for GLIB... yes
checking for EVTLOG... Package eventlog was not found in the pkg-config search path.
Perhaps you should add the directory containing `eventlog.pc'
to the PKG_CONFIG_PATH environment variable
No package 'eventlog' found
configure: error: Cannot find eventlog version >= 0.2: is pkg-config in path?
PKG_CONFIG_PATHを設定してインストール。
$ wget http://www.balabit.com/downloads/syslog-ng/2.0/src/syslog-ng-2.0.2.tar.gz
$ tar xvzf syslog-ng-2.0.2.tar.gz
$ cd syslog-ng-2.0.2
$ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
$ export PKG_CONFIG_PATH

$ ./configure --sysconfdir=/etc
$ make
# make install
設定ファイルを作成する。
ここは運用を見ながら随時変更しているので参照する場合は自サイトに適した形に適宜変更することをお奨めする。
----------------------------------------------------------------------------------------------------
# syslog-ng configuration file.
#
# This should behave pretty much like the original syslog on RedHat. But
# it could be configured a lot smarter.
#
# See syslog-ng(8) and syslog-ng.conf(5) for more information.
#
# 20000925 gb@sysfive.com
#
# Updated by Frank Crawford (<Frank.Crawford@ac3.com.au>) - 10 Aug 2002
#       - for Red Hat 7.3
#       - totally do away with klogd
#       - add message "kernel:" as is done with klogd.
#
# Updated by Frank Crawford (<Frank.Crawford@ac3.com.au>) - 22 Aug 2002
#       - use the log_prefix option as per Balazs Scheidler's email
#

options { sync (0);
          time_reopen (10);
          log_fifo_size (1000);
          long_hostnames (off);
          use_dns (yes);
          use_fqdn (no);
          create_dirs (no);
          keep_hostname (yes);
          stats(86400);
          dir_perm(0755);
          perm(0644);
        };

#
# At around 1999 some distributions have changed from using SOCK_STREAM
# to SOCK_DGRAM sockets, see these posts about the issue:
#
# http://www.security-express.com/archives/bugtraq/1999-q4/0071.html
# http://marc.theaimsgroup.com/?l=sysklogd&m=96989685607952&w=2
#
# libc and syslog clients generally automatically detect the socket type,
# so you are free to decide which of unix-stream or unix-dgram you want to use.
#

#-------------------
# source
#-------------------
source int   { file ("/proc/kmsg" log_prefix("kernel: ")); unix-stream ("/dev/log"); internal(); };
source ext   { udp(); };



#-------------------
# destination
#-------------------
destination alluser     { usertty("*"); };
#destination auth       { file("/var/log/auth.log.$YEAR$MONTH"); };
#destination authpriv   { file("/var/log/authpriv.log.$YEAR$MONTH"); };
#destination lpr        { file("/var/log/lpr.log.$YEAR$MONTH"); };
destination boot        { file("/var/log/boot.log.$YEAR$MONTH"); };
destination console     { file("/dev/console"); };
destination cron        { file("/var/log/cron.log.$YEAR$MONTH"); };
destination daemon      { file("/var/log/daemon.log.$YEAR$MONTH"); };
destination kern        { file("/var/log/kernel.log.$YEAR$MONTH"); };
destination local0      { file("/var/log/local0.log.$YEAR$MONTH"); };
destination local1      { file("/var/log/local1.log.$YEAR$MONTH"); };
destination local2      { file("/var/log/local2.log.$YEAR$MONTH"); };
destination local3      { file("/var/log/local3.log.$YEAR$MONTH"); };
destination local4      { file("/var/log/local4.log.$YEAR$MONTH"); };
destination local5      { file("/var/log/local5.log.$YEAR$MONTH"); };
destination local6      { file("/var/log/local6.log.$YEAR$MONTH"); };
destination local7      { file("/var/log/local7.log.$YEAR$MONTH"); };
destination mail        { file("/var/log/mail.log.$YEAR$MONTH"); };
destination messages    { file("/var/log/messages.$YEAR$MONTH"); };
destination named       { file("/var/log/named.log.$YEAR$MONTH"); };
destination news        { file("/var/log/news.log.$YEAR$MONTH"); };
destination router      { file("/var/log/router.log.$YEAR$MONTH"); };
destination secure      { file("/var/log/secure.$YEAR$MONTH"); };
destination snmp        { file("/var/log/snmp.log.$YEAR$MONTH"); };
destination sshd        { file("/var/log/ssh.log.$YEAR$MONTH"); };
destination syslog      { file("/var/log/syslog.log.$YEAR$MONTH"); };
destination user        { file("/var/log/user.log.$YEAR$MONTH"); };

#-------------------
# filter
#-------------------
#filter f_auth          { facility(auth); };
#filter f_authpriv      { facility(authpriv); };
#filter f_lpr           { facility(lpr); };
filter f_console        { level(warn..emerg) and facility(kern); };
filter f_cron           { facility(cron); };
filter f_daemon         { facility(daemon); };
filter f_emergency      { level(emerg); };
filter f_kern           { facility(kern); };
filter f_local0         { facility(local0); };
filter f_local1         { facility(local1); };
filter f_local2         { facility(local2); };
filter f_local3         { facility(local3); };
filter f_local4         { facility(local4); };
filter f_local5         { facility(local5); };
filter f_local6         { facility(local6); };
filter f_local7         { facility(local7); };
filter f_mail           { facility(mail); };
filter f_messages       { level(info..warn) and not facility(auth,authpriv,cron,lpr,mail,news,local1,local2); };
filter f_named          { program("named"); };
filter f_news           { facility(news); };
filter f_secure         { facility(auth,authpriv); };
filter f_sshd           { program("sshd"); };
filter f_syslog         { program("syslog-ng"); };
filter f_user           { facility(user); };

#-------------------
# log
#-------------------
#log { source(int); filter(f_auth);       destination(auth); };
#log { source(int); filter(f_authpriv);   destination(authpriv); };
#log { source(int); filter(f_lpr);        destination(lpr); };
log  { source(int); filter(f_console);    destination(console); };
log  { source(int); filter(f_cron);       destination(cron); };
log  { source(int); filter(f_daemon);     destination(daemon); };
log  { source(int); filter(f_emergency);  destination(alluser); };
log  { source(int); filter(f_kern);       destination(kern); };
log  { source(int); filter(f_local0);     destination(local0); };
log  { source(int); filter(f_local1);     destination(snmp); };
log  { source(int); filter(f_local2);     destination(local2); };
log  { source(int); filter(f_local3);     destination(local3); };
log  { source(int); filter(f_local4);     destination(local4); };
log  { source(int); filter(f_local5);     destination(local5); };
log  { source(int); filter(f_local6);     destination(local6); };
log  { source(int); filter(f_local7);     destination(boot); };
log  { source(int); filter(f_mail);       destination(mail); };
log  { source(int); filter(f_messages);   destination(messages); };
log  { source(int); filter(f_named);      destination(named); };
log  { source(int); filter(f_news);       destination(news); };
log  { source(int); filter(f_secure);     destination(secure); };
log  { source(int); filter(f_sshd);       destination(sshd); };
log  { source(int); filter(f_syslog);     destination(syslog); };
log  { source(int); filter(f_user);       destination(user); };

log  { source(ext); filter(f_local4);     destination(router); };
設定ファイルに誤りがないか確認する。
誤りがある場合は下記のように該当する行数が出る。(ちなみにこれは175行目がおかしい場合)
# /usr/local/sbin/syslog-ng -f /etc/syslog-ng.conf -s
syntax error at 175
ソースに含まれているサンプルを基に起動スクリプトを作成する。
# cp $SOURCE/syslog-ng-1.6.6/contrib/init.d.RedHat-7.3 /etc/rc.d/init.d/syslog-ng
  /etc/rc.d/init.d/syslog-ng
################################################################################
#
# Program: syslog-ng init script for Red Hat
#
################################################################################
# the following information is for use by chkconfig
# if you are want to manage this through chkconfig (as you should), you must
# first must add syslog-ng to chkconfig's list of startup scripts it
# manages by typing:
#
#               chkconfig --add syslog-ng
#
# DO NOT CHANGE THESE LINES (unless you know what you are doing)
# chkconfig: 2345 12 88
# description: syslog-ng is the next generation of the syslog daemon. \
# syslog-ng gives you the flexibility of logging not only by facility and \
# severity, but also by host, message content, date, etc. it can also replace \
# klogd's function of logging kernel messages
#
# This following block of lines is correct, do not change! (for more info, see
# http://www.linuxbase.org/spec/refspecs/LSB_1.1.0/gLSB/facilname.html)
### BEGIN INIT INFO
# Provides: $syslog
### END INIT INFO
################################################################################
#
#  This is an init script for syslog-ng on the Linux platform.
#
#  It totally relies on the Redhat function library and works the same
#  way as other typical Redhat init scripts.
#
#
# Platforms (tested): Linux (Redhat 7.3)
#
#
# Author: Gregor Binder <gbinder@sysfive.com>
# Changed: October 10, 2000
#
# Last Changed: September 27, 2002
# Updated by: Diane Davidowicz
#       changes: Brought the start script up to snuff as far as compliance
#                with managing the startup script through chkconfig;
#                added PATH variable ability to hook in path to syslog-ng (if
#                its necessary); converted init script format to the
#                standard init script format in Red Hat (7.3 to be exact)
#                including using the /etc/sysconfig/syslog-ng file to
#                managed the arguments to syslog-ng without changing this
#                script, and disabled klogd but noted where and under what
#                conditions it should be enabled. HAPPY LOGGING.
#
#     Copyright (c) 2000 by sysfive.com GmbH, All rights reserved.
#
#
################################################################################
#
# configuration
#

#
# Source Redhat function library.
. /etc/rc.d/init.d/functions


# Source networking configuration.
[ -r /etc/sysconfig/network ] && . /etc/sysconfig/network

RETVAL=0
prog="syslog-ng"


# /etc/sysconfig/ is the standard way to pull in options for a daemon to use.
# Source config
if [ -f /etc/sysconfig/syslog-ng ] ; then
        . /etc/sysconfig/syslog-ng
else
        SYSLOGNG_OPTIONS=
        KLOGD_OPTIONS=
fi


# Tack on path to syslog-ng if not already in PATH
SYSLOGNG_PATH=":/usr/local/sbin"

PATH=$PATH$SYSLOGNG_PATH
export PATH


umask 077
ulimit -c 0

# See how we were called.
start() {
        # Start daemons.
        echo -n $"Starting $prog: "
        daemon syslog-ng $SYSLOGNG_OPTIONS
        RETVAL=$?

        # syslog-ng can handle kernel messages. If you do this, don't
        # run klogd. Consult the following FAQ question to find out why.
        #
        # http://www.campin.net/syslog-ng/faq.html#klogd
        #
        # If you still prefer to run klogd without syslog-ng handling
        # kernel messages, uncomment the following block of lines

        #echo -n $"Starting kernel logger: "
        #daemon klogd $KLOGD_OPTIONS
        #echo

        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/syslog-ng
        echo
        return $RETVAL
}

stop() {
        # Stop daemons.
        # Same here concerning klogd. Uncomment the following block of
        # code if you are needing to run it

        #echo -n $"Shutting down kernel logger: "
        #killproc klogd
        #echo

        echo -n $"Stopping $prog: "
        killproc syslog-ng
        RETVAL=$?

        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/syslog-ng
        echo
        return $RETVAL
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status syslog-ng
        RETVAL=$?
        ;;
  restart)
        stop
        start
        RETVAL=$?
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart}"
        exit 1
esac

exit $?
起動スクリプトを登録する。
# chmod 755 /etc/rc.d/init.d/syslog-ng
# /sbin/chkconfig --add syslog-ng
# /sbin/chkconfig syslog off
# /sbin/chkconfig --list
syslog            0:オフ  1:オフ  2:オフ  3:オフ  4:オフ  5:オフ  6:オフ
syslog-ng       0:オフ  1:オフ  2:オン  3:オン  4:オン  5:オン  6:オフ
syslog-ngを起動する。
# /sbin/service syslog stop
カーネルロガーを停止中:                                    [  OK  ]
システムロガーを停止中:                                    [  OK  ]

# /sbin/service syslog-ng start
syslog-ng を起動中:                                        [  OK  ]

# ps aux
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
root     15012  0.0  0.2  3340  596 ?        Ss   12:55   0:00 syslog-ng

# netstat -an |less
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
udp        0      0 0.0.0.0:514                 0.0.0.0:*
動作確認。
# logger -p kern.info "syslog test"

# tail /var/log/messages
Jan 30 13:17:29 bruna root: syslog test
サーバ稼働時のログ。
# tail /var/log/messages
Jan 30 12:54:57 bruna kernel: Kernel logging (proc) stopped.
Jan 30 12:54:57 bruna kernel: Kernel log daemon terminating.
Jan 30 12:54:59 bruna syslog: klogd 停止 succeeded
Jan 30 12:54:59 bruna exiting on signal 15
Jan 30 12:55:10 bruna syslog-ng[15012]: syslog-ng starting up; version='2.0.2'
Jan 30 12:55:10 bruna syslog-ng: syslog-ng 起動 succeeded

# tail /var/log/boot.log
Jan 30 12:55:10 bruna syslog-ng: syslog-ng 起動 succeeded
OS再起同時にsyslogとsyslog-ngの両方が起動しないようにsyslogを完全に停止させる。
# /sbin/chkconfig syslog off
# /sbin/chkconfig --list |grep syslog
syslog          0:off   1:off   2:off   3:off   4:off   5:off   6:off
syslog-ng       0:off   1:off   2:on    3:on    4:on    5:on    6:off

シスログサーバに出力されたログメッセージの中から特定キーワードに合致した場合に自動でメールを送信してサーバの不具合の早期発見が可能な仕組みを構築する。

まずはPerlによるメール送信スクリプトの作成。
このPerlスクリプトではsendmailコマンドを使用しているが、Sendmail、Postfix、qmailのいずれかのMTAがインストールされていればsendmailコマンドがインストールされているはずである。
  /usr/local/bin/alert_mail.pl
#!/usr/bin/perl

### For Sendmail
#$sendmail = '/usr/lib/sendmail';

### For Postfix
#$sendmail = '/usr/sbin/sendmail';

### For qmail
$sendmail = '/var/qmail/bin/sendmail';

$from = 'username@kajukaju.net';
$to = 'username@kajukaju.net';

$header = <<END;
From: $from
To: $to
Subject: Syslog-ng Alert!
Mime-Version: 1.0
Content-Type: text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding: 7bit
X-Mailer: syslog-ng auto sender program ver1.0 by kajukaju.net

END

while (<STDIN>) {
        if ($_) {
                  $body = $_;
                  $body =~ s/^<[0-9]*>//g;
                  open(MAIL, "| $sendmail -t -i");
                  print MAIL $header,$body;
                  close(MAIL);
        }
}
(例) “end msg”という文字列がシスログに出力された場合にメールを送信する場合。
syslog-ngの設定に追記する。
  /usr/local/etc/syslog-ng.conf
destination d_qmail_endmsg { program("/usr/local/bin/alert_mail.pl"); };
filter f_qmail_endmsg { match("end msg"); };
log { source(s_sys); filter(f_qmail_endmsg); destination(d_qmail_endmsg); };
設定を有効にするためにsyslog-ngを再起動。
# /sbin/service/syslog-ng restart

設定した宛先にメールが送信されることを確認する。