php のエラーログ、php.ini
で次のように設定していると・・
error_log = /var/log/php/php.log
log_errors = On
なにかの拍子で root で php を実行してエラーが出力されると /var/log/php/php.log
が root 所有の 0644 とかで作成されてしまい、アプリケーションの実行ユーザーからエラーログが書けなくなってしまいます。
この問題を解決するためのいくつかの案。
案:logrotate で 0666 でファイルを作成する
logrotate で次のように create 0666 root root
を指定します。
/var/log/php/*.log {
missingok
notifempty
create 0666 root root
}
こうしておけばローテーション時に 0666 でログファイルができるので、root でログに書き込んでしまっても Web アプリからのエラーログが書き込めなくなったりはしません。
と思ったら次のような問題があるらしいです。
logrotateがrenameして新しいファイルを作るよりはやくPHPのloggerがファイルを作ってしまい、logrotateがfile existsで死んでしまう。どうしてPHPはファイルを開きっぱなしにできないのかしら
https://twitter.com/kazeburo/status/960717004494684161
うーん・・・
案:php.ini ではエラーログを設定しない
php.ini ではエラーログのファイル名を空にして SAPI のデフォの出力先に出るようにします(CLI なら標準出力?か標準エラー?、mod_php なら Apache の error_log、php-fpm なら??)。
php.ini
error_reporting = -1
display_errors = off
display_startup_errors = off
error_log =
log_errors = On
その上で httpd.conf とか php-fpm.conf とかの SAPI に固有の設定ファイルでエラーログの出力先を指定します。
httpd.conf
php_value error_log /var/log/php/apache.log
php-fpm.conf
php_value[error_log] = /var/log/php/apache.log
もしくは php-<sapi>.ini
のような特定の SAPI でだけ読まれる php.ini でも良いかもしれません。
cron とかから CLI を実行するときはコマンドラインオプションで指定します。
cron.d/app
SHELL=/bin/bash
MAILTO=root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * apache php -d error_log=/var/log/php/batch.log -d display_errors=stderr /path/to/batch.php | logger -i -t app
logrotate では nocreate を指定します。
/var/log/php/*.log {
missingok
notifempty
nocreate
}
これで不意に root で php -r xxx
とかしてしまってもログファイルは作成されません。
さいごに
PHP を使い始めた最初のころから php.ini で↓みたいにするのは鉄板だと思ってたのですが、
error_log = /var/log/php/php.log
log_errors = On
実はそうでもなくて世間一般では SAPI 固有の設定ファイルで指定してたりする? のだろうか。いや、syslog という手もあるか。。。
追記
Web アプリケーションを root で動かすことは一般的にはありえないですが、サーバのオペレーション用のスクリプトやちょっとしたワンライナーを PHP で作って root で実行とかすると、サーバグローバルな php.ini でログを吐く設定していると問題になることがあるということですね。ログ以外でも php.ini で出力先が設定できるものは同様です(なにかあったっけ?思いつかない)。アプリケーションのキャッシュとかは PHP のコアが吐くわけではないので問題ありません(それはアプリケションが吐くものなので)。
もっとも、PHP で Web アプリケーション以外を作ることはまあまずないですけど・・実際のところシステムの運用中にこの問題が起こったことはないと思います。
ただ、たまに PHP が一番得意だという理由で PHP でなんでも書く人はいますしそれをあまり止めたりもしないです。もちろん、Web アプリケーションと同じ言語で書いてしまうと Web アプリケーションの都合で言語のバージョンアップをするときに影響範囲がわかりにくくなるので、サーバオペレーション系のスクリプトはディストリから提供されているものをそのまま使うのが良いだろうと思います(Bash とか Python とか)。Web アプリケーション用の PHP とサーバオペレーション用の PHP を別々に入れる? それはやめておいたほうが良いと思いますね、、、どっちの PHP で実行されるかわからなくて新規の人がとてつもなく混乱しそうです(勝手なイメージですが Ruby だと Web アプリケーションとサーバオペレーションをを同じ Ruby で実行してることが多そう?)。