logrotateについて



●参照URL

 参照URL:logrotate入門

●ローテート間隔、回数の変更

 ログ管理の都合上、下記のように変更します。
# vi /etc/logrotate.conf
#weekly
 ↓
daily

#rotate 4
 ↓
rotate 365


●logrotateで過去のログファイルの名前に日付を入れる

 logrotateでログファイルをローテーションさせていると、ファイル名が
messages
messages.1
messages.2
messages.3
messages.4
 となってしまい、いつのログであるかが分かりにくくなっています。
 今回は、logrotateで過去のログファイルの名前に日付を入れる方法について紹介します。簡単のため、日ごとにローテート(daily)させることにします。設定ファイル(Red Hat系では/etc/logrotate.d/以下)を開き、postrotateの記述があれば、以下のように変更します。
# /etc/logrotate.d/httpd
/var/log/httpd/*log {
    missingok
    notifempty
    sharedscripts
    postrotate
        /sbin/service httpd reload > /dev/null 2>/dev/null || true
        DT=`date -d -1day +%Y%m%d`
        for f in $1; do
            if [ -f "$f.1" ]; then
                mv $f.1 $f.$DT
            fi
        done
    endscript
}
 アクセス解析ソフトなどで前日分までは必要なことがありますので、その場合は
DT=`date -d -1day +%Y%m%d`
 ↓ 変更
DT=`date -d -2day +%Y%m%d`
if [ -f "$f.1" ]; then
 ↓ 変更
if [ -f "$f.2" ]; then
mv $f.1 $f.$DT
 ↓ 変更
mv $f.2 $f.$DT
のように変更してください。
 これには以下のような情報があるので注意していただきたい。
 http://tech.ckme.co.jp/linuxadmin.shtml
これによると、「CentOS 5では、logrotateにバグがあり、dateextやcompressなどのオプションが使えない。」ということです。
 試してみると確かにそのようだ。
 しかし、CentOS 5.x の logrotate で postrotate を無視するバグが直ってるっぽいという情報もあります。
 そんでもって、世代が管理できなくなってしまいますというような情報もあります。
 いずれも出典はOpenGrooveからです。

●logrotateの動作確認

 ログローテートが実行される際の流れは、概ね以下のようになります。
  • cronが主設定ファイルの/etc/cron.daily/logrotateを読み込む。
  • /etc/logrotate.confの読み込みからlogrotateが起動される。
  • /etc/logrotate.confはそのディレクティブincludeにより、/etc/logrotate.d/配下にある各ログ個別の設定を読み込む。
  • http://www.asahi-net.or.jp/~aa4t-nngk/logrotate.htmlから抜粋

 logrotate.dディレクトリ以下の全ての対象テスト
# logrotate -d /etc/logrotate.conf
 個別のスクリプトのテストは、「/etc/logrotate.d/個別のスクリプト」を指定します。
# logrotate -d /etc/logrotate.d/httpd
 -dvとして-vオプションもつければ詳細表示が可能です。
 -fオプションで強制的に実行します。
# logrotate -f /etc/logrotate.conf
 正常にログのローテーションが行われているか確認します。最後にローテーションされたログファイルの日付を確認するには、/var/lib/logrotate.statusを確認します。ただし、cronが実行した場合、/var/lib/logrotate/logrotate.statusに記録されます。
# cat /var/lib/logrotate.status
 ローテーションを実際に実行させて確認したい場合、/var/lib/logrotate.statusの日付をローテーションされる周期の日付より前に戻してから/usr/sbin/logrotateを実行してみます。
参考:http://blog.goo.ne.jp/cgeryuji/e/746d27a3d2ec92f751cc78cbc05906f9
 ログローテートが機能していないようだ、という時には様々な原因が考えられますが、取り急ぎ確認すべき設定ファイルは以下のとおりです。
/etc/logrotate.conf
/etc/logrotate.d/syslog(他、個別設定ファイル)
/etc/cron.daily/logrotate
/var/lib/logrotate.status
/var/lib/logrotate/logrotate.status
 logratateがうまくいかない時は下記を参照してみてください。
 logrotateでログファイルがローテーションされない事への対処

●logrotate失敗時とその確認方法

 corosyncのログが正常にローテーションされなかった時の状況を示します。
 /etc/logrotate.d/corosyncの内容は下記のとおりです。確認のため、ファイルサイズが10k以上であればローテーションするように設定しています。
# cat /etc/logrotate.d/corosync
/var/log/corosync.log {
    compress
    missingok
    size 10k
    create 660 hacluster haclient
    notifempty
    sharedscripts
    postrotate
        systemctl reload corosync.service
    endscript
}
 ところがローテーションを試してみると正常にローテーションされませんでした。その時の結果が下記のとおりです。ログの最終行に「そのようなファイルやディレクトリはありません」という出力がありますが、ローテーションされていないので当然の動作でありこの箇所は問題ありません。
# logrotate -dv /etc/logrotate.d/corosync
reading config file /etc/logrotate.d/corosync
Handling 1 logs
rotating pattern: /var/log/corosync.log  10240 bytes (no old logs will be kept)
empty log files are not rotated, old logs are removed
considering log /var/log/corosync.log
  log needs rotating
rotating log /var/log/corosync.log, log->rotateCount is 0
dateext suffix '-20150526'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/corosync.log.1.gz to /var/log/corosync.log.2.gz (rotatecount 1, logstart 1, i 1), 
renaming /var/log/corosync.log.0.gz to /var/log/corosync.log.1.gz (rotatecount 1, logstart 1, i 0), 
renaming /var/log/corosync.log to /var/log/corosync.log.1
disposeName will be /var/log/corosync.log.1.gz
creating new /var/log/corosync.log mode = 0660 uid = 189 gid = 189
running postrotate script
running script with arg /var/log/corosync.log : "
        systemctl reload corosync.service
"
compressing log with: /bin/gzip
removing old log /var/log/corosync.log.1.gz
error: error opening /var/log/corosync.log.1.gz: そのようなファイルやディレクトリはありません
 上記のログでは良くわからないので強制的にローテーションさせて動作を確認します。
# logrotate -f /etc/logrotate.d/corosync
Failed to reload corosync.service: Job type reload is not applicable for unit corosync.service.
error: error running shared postrotate script for '/var/log/corosync.log '
 「Failed to reload corosync.service: Job type reload is not applicable for unit corosync.service.」というエラーが出力されています。ここに該当する部分をコメントアウトします。
# cat /etc/logrotate.d/corosync
/var/log/corosync.log {
    compress
    missingok
    size 10k
    create 660 hacluster haclient
    notifempty
    sharedscripts
#    postrotate
#        systemctl reload corosync.service
#    endscript
}
 再度強制的にローテーションさせます。
# logrotate -f /etc/logrotate.d/corosync
# ls -l /var/log/corosync.log*
-rw-rw---- 1 hacluster haclient     0  5月 26 11:29 /var/log/corosync.log
-rw-rw---- 1 hacluster haclient 19938  5月 26 10:53 /var/log/corosync.log.1

 エラーは出力されず、ローテーションされていることがわかります。

 参考URL:ログローテーション(logrotate)を使ってみる ( httpd(apache)の設定例 )

 また、過去1度もローテーションしていない場合、log does not need rotatingと出力される場合があります。この場合は、1度だけ-fオプションを付けて強制的にローテーションを実行するとその後ローテーションが正常に動作する場合があります。

●apacheのログがローテートされなくなった

 cronから飛んでくるメールでapacheのログがローテーションされていないことに気がつきました。

 対応その2

 こちらの方法で問題が解決されました。
    prerotate
        `rpm -ql awstats|grep "awstats_updateall\.pl"` now -configdir="/etc/awstats" -awstatsprog="`rpm -ql awstats|grep "awstats\.pl"`" >/dev/null
    endscript
  ↓↓↓
    prerotate
        /usr/share/awstats/tools/awstats_updateall.pl now -configdir="/etc/awstats" -awstatsprog="`rpm -ql awstats|grep "awstats\.pl"`" >/dev/null
    endscript
 awstats_updateall.plのパスを絶対パスに変更したところ正常にローテーションするようになりました。

 rpm -ql awstats|grep "awstats_updateall\.pl"を実行すると問題なくパスが表示されるのですが、何故cronの場合、正常にローテーションできなくなるのか不明です。

 対応その1

logrotate_script: 行 1: now: コマンドが見つかりません
error: error running shared prerotate script for '/var/log/httpd/*log '
 /var/log/messagesにそれらしきログが残っていました。
Nov 28 04:05:13 serverA logrotate: ALERT exited abnormally with [1]
 /etc/logrotate.confには「dateext」が記載されているにもかかわらず、末尾に「.0」等を付けようとする動きになっています。
 logrotate.confの内容は下記のとおりです。

# cat /etc/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
#weekly
daily

# keep 4 weeks worth of backlogs
#rotate 4
#rotate 12
rotate 90

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
compress

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
monthly
create 0664 root utmp
minsize 1M
rotate 1
}

/var/log/btmp {
missingok
monthly
create 0600 root utmp
rotate 1
}

# system-specific logs may be also be configured here.


 logrotateコマンドのデバッグ結果は下記のとおりです。

# logrotate -d /etc/logrotate.d/httpd
reading config file /etc/logrotate.d/httpd
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/httpd/*log 1048576 bytes (24 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/httpd/access_log
log needs rotating
considering log /var/log/httpd/error_log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/mod_jk.log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/modsec_audit.log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/modsec_debug.log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/ssl_access_log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/ssl_error_log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/ssl_request_log
log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/httpd/access_log, log->rotateCount is 24
dateext suffix '-20171128'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/httpd/access_log.24 to /var/log/httpd/access_log.25 (rotatecount 24, logstart 1, i 24),
renaming /var/log/httpd/access_log.23 to /var/log/httpd/access_log.24 (rotatecount 24, logstart 1, i 23),
renaming /var/log/httpd/access_log.22 to /var/log/httpd/access_log.23 (rotatecount 24, logstart 1, i 22),
renaming /var/log/httpd/access_log.21 to /var/log/httpd/access_log.22 (rotatecount 24, logstart 1, i 21),
renaming /var/log/httpd/access_log.20 to /var/log/httpd/access_log.21 (rotatecount 24, logstart 1, i 20),
renaming /var/log/httpd/access_log.19 to /var/log/httpd/access_log.20 (rotatecount 24, logstart 1, i 19),
renaming /var/log/httpd/access_log.18 to /var/log/httpd/access_log.19 (rotatecount 24, logstart 1, i 18),
renaming /var/log/httpd/access_log.17 to /var/log/httpd/access_log.18 (rotatecount 24, logstart 1, i 17),
renaming /var/log/httpd/access_log.16 to /var/log/httpd/access_log.17 (rotatecount 24, logstart 1, i 16),
renaming /var/log/httpd/access_log.15 to /var/log/httpd/access_log.16 (rotatecount 24, logstart 1, i 15),
renaming /var/log/httpd/access_log.14 to /var/log/httpd/access_log.15 (rotatecount 24, logstart 1, i 14),
renaming /var/log/httpd/access_log.13 to /var/log/httpd/access_log.14 (rotatecount 24, logstart 1, i 13),
renaming /var/log/httpd/access_log.12 to /var/log/httpd/access_log.13 (rotatecount 24, logstart 1, i 12),
renaming /var/log/httpd/access_log.11 to /var/log/httpd/access_log.12 (rotatecount 24, logstart 1, i 11),
renaming /var/log/httpd/access_log.10 to /var/log/httpd/access_log.11 (rotatecount 24, logstart 1, i 10),
renaming /var/log/httpd/access_log.9 to /var/log/httpd/access_log.10 (rotatecount 24, logstart 1, i 9),
renaming /var/log/httpd/access_log.8 to /var/log/httpd/access_log.9 (rotatecount 24, logstart 1, i 8),
renaming /var/log/httpd/access_log.7 to /var/log/httpd/access_log.8 (rotatecount 24, logstart 1, i 7),
renaming /var/log/httpd/access_log.6 to /var/log/httpd/access_log.7 (rotatecount 24, logstart 1, i 6),
renaming /var/log/httpd/access_log.5 to /var/log/httpd/access_log.6 (rotatecount 24, logstart 1, i 5),
renaming /var/log/httpd/access_log.4 to /var/log/httpd/access_log.5 (rotatecount 24, logstart 1, i 4),
renaming /var/log/httpd/access_log.3 to /var/log/httpd/access_log.4 (rotatecount 24, logstart 1, i 3),
renaming /var/log/httpd/access_log.2 to /var/log/httpd/access_log.3 (rotatecount 24, logstart 1, i 2),
renaming /var/log/httpd/access_log.1 to /var/log/httpd/access_log.2 (rotatecount 24, logstart 1, i 1),
renaming /var/log/httpd/access_log.0 to /var/log/httpd/access_log.1 (rotatecount 24, logstart 1, i 0),
running prerotate script
running script with arg /var/log/httpd/*log : "
`rpm -ql awstats|grep "awstats_updateall\.pl"` now -confdir="/etc/awstats" \
-awstatsprog="`rpm -ql awstats|grep "awstats\.pl"`" >/dev/null
"
fscreate context set to system_u:object_r:httpd_log_t:s0
renaming /var/log/httpd/access_log to /var/log/httpd/access_log.1
running postrotate script
running script with arg /var/log/httpd/*log : "
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
"
removing old log /var/log/httpd/access_log.25
error: error opening /var/log/httpd/access_log.25: そのようなファイルやディレクトリはありません


 最終行でエラーとなっています。
 ローテーションの末尾が「.yyyymmdd」となるように/etc/logrotate.d/httpd「dateext」を追記します。

# logrotate -d /etc/logrotate.d/httpd
reading config file /etc/logrotate.d/httpd
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/httpd/*log 1048576 bytes (24 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/httpd/access_log
log needs rotating
considering log /var/log/httpd/error_log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/mod_jk.log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/modsec_audit.log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/modsec_debug.log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/ssl_access_log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/ssl_error_log
log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/httpd/ssl_request_log
log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/httpd/access_log, log->rotateCount is 24
dateext suffix '-20171128'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
glob finding old rotated logs failed
running prerotate script
running script with arg /var/log/httpd/*log : "
`rpm -ql awstats|grep "awstats_updateall\.pl"` now -confdir="/etc/awstats" -awstatsprog="`rpm -ql awstats|grep "awstats\.pl"`" >/dev/null
"
fscreate context set to system_u:object_r:httpd_log_t:s0
renaming /var/log/httpd/access_log to /var/log/httpd/access_log-20171128
running postrotate script
running script with arg /var/log/httpd/*log : "
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
"


 これで正常にローテーションするか待ちます。
 残念ながらローテーションされていませんでした(20171128)。