Nginx + uWSGI + Djangoのwebアプリケーション環境を作る (その4)

Django

第4回 uWSGIのログをローテート

第3回では、uWSGIをsystemdのサービスとして登録してOS起動時にuWSGIも自動的に起動するようにしました。
第4回ではuWSGIのログをローテートし、ログファイルが無限に増えてディスク容量を圧迫しないようにします。また、せっかくなので一般的にサービスと同じようにログファイルの保存場所を /var/log/demo 配下に移動します。

uwsgi.iniの編集

uwsgi.iniの [uwsgi] セクションにパラメータを追加・編集する。

daemonize        = /var/log/demo/demo.log
logfile-chown
disable-logging  = false
log-4xx          = false
log-5xx          = true
touch-logreopen  = /var/log/demo/logreopen

第2回と重複するパラメータも記載するが、ログ関連の設定内容を以下に列挙する。
実際に変更・追加したのは、ログファイルのパスを /var/log/demo 配下に変更するための daemonize と、ログローテート関連の logfile-chown および touch-logreopen となる。

パラメータ意味
daemonizeuWSGIのログを記録するファイルのパス。(編集)
logfile-chown作成するログファイルの所有権を、別途uid、gidパラメータで指定したuWSGIワーカープロセスと同じオーナーおよびグループに変更する。
disable-loggingリクエスト毎にログ記録しない。
log-4xxHTTP STATUS 4xxのエラーをログに記録する。
log-5xxHTTP STATUS 5xxのエラーをログに記録する。
touch-logreopen指定したパスの更新日時が変わったらログを再度オープンする。

touch-logreopen

後述するlogrotateが行うローテート機能のデフォルト動作は、現行のログファイルをリネームして新たなログファイルを作成する。しかしuWSGIは現行のファイルをオープンしているため、新たなログファイルを作成してもリネームされたファイルに書き込みを続けてしまう。
touch-logreopenは、uWSGIにログファイルを再オープンするタイミングを伝える。このパラメータに指定したファイルの更新日時が変わった時、uWSGIはログを再オープンし、新しいログファイルに書き込みを始める。

logfile-chown

uWSGIマスタープロセスをrootユーザで起動すると、ログファイルのオーナーはrootになる。しかしながら、touch-logreopenでログを再オープンした後はuWSGIワーカープロセスのユーザで書き込もうとする (uWSGI 2.0.19にて確認。本当に仕様?) ため、ログファイルのオーナーをワーカープロセスに合わせる。

ログファイル配置場所の作成

ログファイルを /var/log/demo 配下にするため、uWSGI起動スクリプト start.sh に以下を追加する。

LOG_DIR=/var/log/demo
mkdir -p $LOG_DIR

uWSGIの再起動

uWSGIを再起動し、ログファイルが作成されていれば正しく設定されたことがわかる。

$ sudo systemctl restart demo
$ ls -la /var/log/demo
total 8
drwxr-xr-x   2 root   root        22 Aug 15 18:45 .
drwxr-xr-x. 10 root   root      4096 Aug 15 15:27 ..
-rw-r-----   1 hiyoko www-users 2056 Aug 15 18:45 demo.log

logrotateのインストール

ほとんどの場合はlogrotateコマンドがデフォルトでインストールされているが、CentOS 8をMinimalインストールした場合は入っていないため、インストールする。

$ sudo dnf install logrotate

logrotateの設定

logrotateはcronで定期実行され、/etc/logrotate.d/ 配下の設定ファイルに従ってログファイルをローテートする。/etc/logrotate.d/ 配下に demo というファイルを以下の内容で作成する。

/var/log/demo/*.log {
        dateext
        daily
        rotate 7
        notifempty
        missingok
        compress
        delaycompress
        create 640 hiyoko www-users
        sharedscripts
        postrotate
                touch /var/log/demo/logreopen
        endscript
}

logrotateの設定ファイルに指定した内容は以下のとおり。

パラメータ内容
dateextローテートしたファイルの拡張子を日付 (.YYYYMMDD) にする。デフォルトは通し番号。
daily日次ローテートする。
rotate指定数のローテートファイルを保持し、それ以上古いものは削除する。
notifemptyファイルが空の場合はローテートしない。
missingokファイルが無くてもエラー表示を行わない。
compressローテートしたファイルを圧縮する。
delaycompressローテートした1世代目のファイルは圧縮しない。(ローテートの瞬間にまだログ書き込みしている可能性があるため)
create指定したパーミッション、ユーザ、グループで新規ログファイルを作成する。
sharedscriptsログファイルに対し、postrotateまたはprerotateで指定したスクリプトを実行する。
postrotateローテート後に実行するコマンド。ここでは touch コマンドで logreopen ファイルを作成し、uWSGIにログ再オープンのタイミングを伝えている。
endscriptコマンドスクリプト指定の終了。

logrotateの仮実行

作成した定義ファイルにより正しく動作できるか、logrotateを仮実行して確かめる。-d はデバッグモード実行で、ログファイルは実際にはローテートされない。-f は強制指定で、定義ファイル内で日次ローテートを指定しても強制的にローテートを行う。

$ sudo logrotate -d -f /etc/logrotate.d/demo
WARNING: logrotate in debug mode does nothing except printing debug messages!  Consider using verbose mode (-v) instead if this is not what you want.

reading config file /etc/logrotate.d/demo
Reading state from file: /var/lib/logrotate/logrotate.status
Allocating hash table for state file, size 64 entries
Creating new state

Handling 1 logs

rotating pattern: /var/log/demo/*.log  forced from command line (7 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/demo/demo.log
  Now: 2020-08-15 18:47
  Last rotated at 2020-08-15 16:10
  log needs rotating
rotating log /var/log/demo/demo.log, log->rotateCount is 7
dateext suffix '-20200815'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
glob finding logs to compress failed
glob finding old rotated logs failed
renaming /var/log/demo/demo.log to /var/log/demo/demo.log-20200815
creating new /var/log/demo/demo.log mode = 0640 uid = 1101 gid = 1100
running postrotate script
running script with arg /var/log/demo/*.log : "
                touch /var/log/demo/logreopen
"

これで、logrotateも正しく実行されることが確認できた。あとはcronにより実行され、ログファイルが日次ローテートするのを待つ。

コメント

タイトルとURLをコピーしました