Linux の標準機能として提供されている logrotate コマンドを利用すると、設定ファイルに記載された条件にしたがって特定のログファイルをリネームしたり古すぎるものを削除したりすることができます。これによってログファイルが肥大化してディスクの容量を圧迫することを回避できます。実用上 logrotate コマンド自体は直接的には実行しません。cron に設定されたシェルスクリプト内で間接的に利用します。
初期状態は以下のようになっています。必要に応じて設定項目を調べて編集します。
/etc/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
weekly
# keep 4 weeks worth of backlogs
rotate 4
# 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.
/etc/logrotate.d には yum でインストールされた RPM パッケージが設置した設定ファイルが格納されています。例えば以下のようになっています。/var/log/messages がログローテートされるのは syslog の設定ファイルのためであることが分かりました。
$ ls /etc/logrotate.d/
dracut mysqld nginx syslog yum
$ cat /etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
/var/log/wtmp および /var/log/btmp は syslog などで管理されないため直接 /etc/logrotate.conf に設定が書かれています。それぞれ last および lastb コマンドで利用されるログインに関するログファイルです。
ログイン履歴
$ last
username pts/0 123.123.123.123 Tue May 26 22:40 still logged in
username pts/0 123.123.123.123 Tue May 26 21:26 - 21:27 (00:00)
username pts/0 123.123.123.123 Tue May 26 20:39 - 20:39 (00:00)
username pts/1 123.123.123.123 Tue May 26 01:22 - 01:28 (00:05)
username pts/1 123.123.123.123 Tue May 26 00:28 - 01:14 (00:46)
username pts/1 123.123.123.123 Tue May 26 00:21 - 00:22 (00:00)
...
不正ログイン履歴 (実際にはログインできなかったもの)
ubnt ssh:notty 185.19.94.207 Tue May 26 09:25 - 09:25 (00:00)
sales ssh:notty 72.167.254.54 Tue May 26 09:10 - 09:10 (00:00)
admin ssh:notty 72.167.254.54 Tue May 26 09:10 - 09:10 (00:00)
admin ssh:notty 72.167.254.54 Tue May 26 09:10 - 09:10 (00:00)
default ssh:notty 72.167.254.54 Tue May 26 09:10 - 09:10 (00:00)
cisco ssh:notty 72.167.254.54 Tue May 26 09:10 - 09:10 (00:00)
...
関連情報としてローテートはされませんが /var/log/lastlog を利用する lastlog コマンドもあります。
$ lastlog
ユーザ名 ポート 場所 最近のログイン
root **一度もログインしていません**
nobody **一度もログインしていません**
postfix **一度もログインしていません**
nfsnobody **一度もログインしていません**
sshd **一度もログインしていません**
vagrant pts/2 10.0.2.2 火 5月 26 22:40:44 +0900 2015
mysql **一度もログインしていません**
memcached **一度もログインしていません**
...
/etc/cron.daily/logrotate
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf >/dev/null 2>&1
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
各ログの過去のローテート情報は以下のファイルに記載されています。
$ cat /var/lib/logrotate.status
logrotate state -- version 2
"/var/log/nginx/error.log" 2015-5-26
"/var/log/yum.log" 2015-5-21
"/var/log/dracut.log" 2015-5-21
"/var/log/wtmp" 2015-5-21
"/var/log/spooler" 2015-5-26
"/var/log/btmp" 2015-5-21
"/var/log/maillog" 2015-5-26
"/var/log/secure" 2015-5-26
"/var/log/nginx/access.log" 2015-5-21
"/var/log/messages" 2015-5-26
"/var/log/cron" 2015-5-26
/etc/logrotate.d/myapp
/var/log/myapp/*.log {
create 0644 ec2-user ec2-user
daily
rotate 30
missingok
notifempty
compress
sharedscripts
postrotate
/etc/init.d/myapp reload # restart する場合は renice しましょう https://www.qoosky.io/techs/3d9a0c3482
endscript
}
検証 (dry run)
sudo /usr/sbin/logrotate -fd /etc/logrotate.d/myapp
実行
sudo /usr/sbin/logrotate -f /etc/logrotate.d/myapp
CentOS 等の場合 /etc/cron.daily/logrotate
は /etc/anacrontab
の設定で実行されます。
/etc/anacrontab
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
以下の例では早くて AM 3:00 頃に処理が実行されることが分かります。また nice
コマンドで実行されるため postrotate
で restart
すると nice 値が 0 以外の値の優先度が低いプロセスになってしまうことも分かります。
postrotate
ではなく copytruncate
を用いると上記問題を回避できます。ログを cp
してからコピー元ファイルの内容を消去するため、アプリケーションは同じファイル (同じ i ノード番号) への書き込みを継続できます。
/var/log/myapp/*.log {
daily
rotate 14
missingok
notifempty
compress
copytruncate
}