TT Lab
はじめる
学ぶ 学習パス コース

ログパイプラインの設計

ローテーションが何を失うのかを自分で見る

TT Labで続きを見る

目標

ログローテーションの2つの方式がそれぞれ何を失うかを、実際に作って確かめます。説明を読むことと、ファイルが0バイトのまま残っているのを見ることは違います。

なぜ重要なのか

ローテーションの設定を誤ると、次の2つのうちどちらかが起きます。

どちらも障害調査の最中に気づいたのでは、すでに手遅れです。

ステップ

  1. 書き込み続けるプロセス → /root/log/01-pid.txt
  2. 削除したのに空きが戻らないもの → /root/log/02-deleted.txt
  3. 再起動による後始末 → /root/log/03-restart.txt
  4. renameによる方式の再現 → /root/log/04-rename.txt
  5. copytruncateによる方式の再現 → /root/log/05-truncate.txt
  6. logrotate設定の作成 → /root/log/06-app.conf
  7. 何を失うか → /root/log/07-tradeoff.md
  8. 後始末 → /root/log/08-clean.txt

参考

書き込み続けるプロセスを作る

書き込み続けるプロセス → /root/log/01-pid.txt

ログを書き込み続けるプロセスをバックグラウンドで起動します。ファイルを開いたまま書き込む必要があります。このラボが見せようとしている現象はすべて「開いているファイル」が原因で起きるためです。

mkdir -p /root/log
( i=0; while true; do i=$((i+1)); echo "line $i"; sleep 0.05; done ) >> /root/log/app.log &
echo $! > /root/log/01-pid.txt

リダイレクトをループの外側に置くことが核心です。echo ... >> 파일(プレースホルダーはファイル名です)のように内側に置くと、毎回開閉するため、ファイルを削除してもハンドルが残らず、renameしても新しいファイルに書き込むことになります。実際のデーモンはファイルを一度開いて書き込み続けます。

削除しても空きが戻らないことを確認する

削除したのに空きが戻らないもの → /root/log/02-deleted.txt

rm /root/log/app.logを実行してから、ls -l /proc/<PID>/fd | grep deleted(プレースホルダーはプロセスIDです)を見てください。結果を/root/log/02-deleted.txtに保存します。ファイルは消えたのにプロセスはまだ書き込んでおり、そのブロックは解放されません。

再起動して後始末する

再起動による後始末 → /root/log/03-restart.txt

そのプロセスをkill <PID>(プレースホルダーはプロセスIDです)で終了し、新しく起動してください。/root/log/03-restart.txtに2行書きます。終了後のls -l /proc/*/fd 2>/dev/null | grep -c deletedの結果と、なぜ再起動が解決策になるのかを説明する1行です。

renameによる方式を再現する

renameによる方式の再現 → /root/log/04-rename.txt

新しいwriterを起動してからmv /root/log/app.log /root/log/app.log.1を実行し、5秒待ってからwc -lで2つのファイルの行数を確認してください。/root/log/04-rename.txtに2つのファイルの行数を書きます。新しいapp.logは作成すらされていないはずです。それがSIGHUPが必要な理由です。

copytruncateによる方式を再現する

copytruncateによる方式の再現 → /root/log/05-truncate.txt

cp /root/log/app.log.1 /root/log/app.log.2 && : > /root/log/app.log.1でコピーしてから切り詰めを行います。そのあと5秒後にwc -l /root/log/app.log.1を確認してください。/root/log/05-truncate.txtに、切り詰め直後と5秒後の行数を書きます。プロセスが書き込み続けていることを確認するのが目的です。

logrotateの設定を書く

logrotate設定の作成 → /root/log/06-app.conf

/root/log/06-app.confにlogrotateの設定を書きます。必要なもの: パスのパターン、daily、rotate 14、compress、delaycompress、missingok、notifempty、そしてcreateまたはcopytruncateのどちらか1つ。logrotateコマンドがなくても構いません。設定を読み書きできるようになることが目的です。

何を失うかを書く

何を失うか → /root/log/07-tradeoff.md

/root/log/07-tradeoff.mdに4行書きます。createが失うもの / copytruncateが失うもの / 自分が選んだ方式 / その理由です。どちらもタダではないということが、このラボの結論です。

後始末をする

後始末 → /root/log/08-clean.txt

記録しておいたPIDで終了します: kill $(cat /root/log/01-pid.txt)。そのあとrm -f /root/log/app.log*でファイルを削除し、何も残っていないことをpgrep -f sleep | wc -lのようなもので確認して、/root/log/08-clean.txtに書いてください。

⚠️ pkill -f 'while true'は使わないでください。pkillの-fは自分自身のコマンドラインまで対象に含めるため、その文字列を含むシェル自身を終了させてしまいます。実務でもpkill -fで自分のセッションを切ってしまう事故はよくあります。PIDを記録しておき、それで終了するほうが常に安全です。