中山テック 代表の中山です。
スクリプト実行で1つのログファイルが大きくなり、可読性が悪くなることが多々あります。
systemctl可能なミドルはそんなに難しくないのですが、自前でこさえるとなるとなかなか大変。
リファレンス的に残す形であること、自前なので参考程度にご覧ください。
ログの準備
-rw-r----- 1 nginx root 112225 7月 12 13:06 access.log
-rw-r--r-- 1 root root 4863 7月 8 09:10 access.log-20240708.gz
-rw-r----- 1 nginx root 9487 7月 9 10:06 access.log-20240709.gz
-rw-r----- 1 nginx root 48617 7月 9 21:15 access.log-20240710.gz
-rw-r----- 1 nginx root 412 7月 11 11:30 access.log-20240711.gz
-rw-r----- 1 nginx root 729280 7月 12 12:23 access.log-20240712
-rw-r----- 1 nginx root 0 7月 10 15:31 error.log
-rw-r--r-- 1 root root 1940 7月 8 00:19 error.log-20240708.gz
-rw-r----- 1 nginx root 847 7月 9 10:06 error.log-20240709.gz
-rw-r----- 1 nginx root 22295 7月 9 19:36 error.log-20240710
-rw-r--r-- 1 nginx root 3307324 7月 12 23:28 zabbix_access.log
-rw-r--r-- 1 nginx root 1166 7月 12 13:07 zabbix_error.log
※既にローテートされているログ達ですが今後の流れを説明したいので
ローテートタイミングを1日とします。
赤字の「access.log」を昨日日付にリネームし、新たなaccess.logを作ることです。
ブログを執筆しているのが2024年9月11日ですので9月10のログとして残していきたい、という算段です。
ローテートスクリプト
「rotate.sh」という名前のファイルを作成して下記のプログラムを組みます。
#!/bin/bash
# 今日日付
nowDate=$(date +"%Y%m%d") # ①現在日付を取得し
# ログ
log=/var/log/nginx/access.log
# ログファイルの日付を取得
logFileDate=$(find ${log} -printf '%TY%Tm%Td')
# ②ローテート対象ファイルの日付を取得
# ユーザ・グループ
user=nginx
group=root
if [ ${logFileDate} != ${nowDate} ]; then # ③ログファイルの日付と現在日付が相違の場合、昨日日付付でリネーム
yesterday_date=$(date -d "yesterday" + "%Y-%m-%d")
$(mv ${log} ${log}.${yesterday_date})
touch ${log}
chown ${user}:${group} ${log}
fi
実行
[root@study01 nginx]# ./rotate.sh
-rw-r--r-- 1 nginx root 0 9月 11 16:06 access.log
-rw-r--r-- 1 root root 4863 7月 8 09:10 access.log-20240708.gz
-rw-r----- 1 nginx root 9487 7月 9 10:06 access.log-20240709.gz
-rw-r----- 1 nginx root 48617 7月 9 21:15 access.log-20240710.gz
-rw-r----- 1 nginx root 412 7月 11 11:30 access.log-20240711.gz
-rw-r----- 1 nginx root 729280 7月 12 12:23 access.log-20240712
-rw-r----- 1 nginx root 112225 7月 12 13:06 access.log.2024-09-10
-rw-r----- 1 nginx root 0 7月 10 15:31 error.log
-rw-r--r-- 1 root root 1940 7月 8 00:19 error.log-20240708.gz
-rw-r----- 1 nginx root 847 7月 9 10:06 error.log-20240709.gz
-rw-r----- 1 nginx root 22295 7月 9 19:36 error.log-20240710
-rwxr-xr-x 1 root root 418 9月 11 16:05 rotate.sh
-rw-r--r-- 1 nginx root 3307324 7月 12 23:28 zabbix_access.log
-rw-r--r-- 1 nginx root 1166 7月 12 13:07 zabbix_error.log
新規access.logが作られ、古いaccess.logは日付付のoldファイルになりました。
ログに書き込む前に上記処理を入れておくことで日時ローテートを実現可能となります。
※リネーム後のファイル名は状況に応じて変えてみてください
応用
$(mv ${log} ${log}.${yesterday_date})
ファイルをリネームしただけなのでサイズが変わっておりません。
もし圧縮・アーカイブ化させたい場合は下記のように指定するのもOK
#!/bin/bash
# 今日日付
nowDate=$(date +"%Y%m%d")
# ログ
log=/var/log/nginx/access.log
log_dir=/var/log/nginx
logfile=access.log
# ログファイルの日付を取得
logFileDate=$(find ${log} -printf '%TY%Tm%Td')
# ユーザ・グループ
user=nginx
group=root
if [ ${logFileDate} != ${nowDate} ]; then
yesterday_date=$(date -d "yesterday" +"%Y-%m-%d")
#$(mv ${log} ${log}.${yesterday_date})
$(tar zcf ${log}-${yesterday_date}.tar.gz -C ${log_dir} ${logfile} )
#rm ${log} # ←必要に応じて
#touch ${log} # ←必要に応じて
#chown ${user}:${group} ${log} # ←必要に応じて
fi
上書き防止のため「-C」を使用してディレクトリとファイルを分けて指定します。
また、青文字の「必要に応じて」の箇所ですが、ファイルを削除して新たなファイルを作成するプログラムになります。
別のディレクトリに配置して良いですし、可能性は無限大です。
まとめ
問題発生時のアプローチとしてログは非常に重要です。
今回のケースに限らずですが、土日で監視する人がいない場合に土日どっちで起きたのか。
また何時ごろ起きたのか、ということを確認します。
膨大なサイズになってしまったログは開くのに時間が掛かる他、検索も非常に難しくなります。
今回は1日おきにローテートさせるプログラムとなりますが、場合によってはファイルサイズでローテートさせる必要も出るでしょう。
ローテートさせていない場合は是非実装してみてください!