Nginxでログが出力されなくなる場合
お客様から Amazon Linux2 上の Nginx で、ログが取られなくなることがあるということでお問い合わせをいただき調査を行いました。
環境は以下のとおりです。
- OS: Amazon Linux2
- Nginx version: nginx-1.20.0-2.amzn2.0.4.x86_64
結論からいうと、logrotation が入るとログファイルにログが出力されなくなっていました。
logrotation時、以下のコマンドを実行してNginxにログファイルを reopen させています。
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
Nginx は USR1シグナルを受けると worker process が /var/log/nginx/ にあるログファイルを開き直そうとするのですが(*1)、その際、/var/log/nginx ディレクトリのパーミッションが 0700(rwx------) root:root であるため、nginxユーザ(*2)からはアクセスできずに permission denied でオープンに失敗していました。エラーログのファイルも同様に開けていないため、permission denied のログも残らず調べるのに若干手間取りました。
この現象は、Nginx を reload をすると元に戻るのですが、これは、realod時は worker process を作り直すためです。reloadすると、master process でファイルを開き直してから、fork して worker process を作成し、その後、worker process は setuid で rootからnginxにユーザが変わります。 ソースコードを深くは追ってはいませんが、おそらく開いたファイルはmaster processのものを引き継いでいるので、worker process が nginxユーザになったとしてもそのままログファイルにアクセスできるのでしょう。
ただ、/var/log/nginx/のパーミッションが原因だとすると、以前から同様の問題が出ていそうではあります。私も何度かAmazon Linux2にnginxはインストールしたことはありますが、今回のケースには初めて遭遇しました。
調べてみると以前のインストールでは /var/log/nginx のパーミッションが異なるようです。
nginx-1.18.0-1.amzn2.0.2.src.rpm の nginx.spec を確認すると、以下のように、
install -p -d -m 0700 %{buildroot}%{_localstatedir}/log/nginx 略 %attr(770,%{nginx_user},root) %dir %{_localstatedir}/log/nginx
パーミッションを 0770(rwxrwx---) nginx:root に設定していたのが、nginx-1.20.0-2.amzn2.0.3.src.rpm では
install -p -d -m 0700 %{buildroot}%{_localstatedir}/log/nginx
のようにパーミッション設定しなくなっているので、0700(rwx------) root:root に変わったようです。
changelogをみると、1.20.0-2.amzn2.0.3 は 2021.5.25 のリリースのようなので比較的最近(?)変わったようです。 そういえば、ここ最近はAmazon Linux2にNginxを新規にインストールしたことはなかったので、この現象に遭遇しなかっただけのようです。
ということで対策は、/var/log/nginx/に以前と同じパーミッションを付与しておきました。
chmod 770 /var/log/nginx/ chown nginx:root /var/log/nginx/ systemctl reload nginx.service
この一年くらいで、Amazon Linux2 に Nginx をインストールした人は、確認しておいた方がいいかもしれません。何かの調査でログファイルを見てみたら空っぽだったということになりかねません。
(*1) http://nginx.org/en/docs/control.html
(*2) デフォルト設定なら、master processはroot、worker processはnginxユーザで動作しています。
投稿日:2022/04/14 15:43