Laravelに限った話でないですが、あるプログラムを異なるユーザが実行し同じ宛先のログファイルに追記をしようとする場合、書き込み権限を持っておらずPermission deniedで弾かれることがあります。この記事ではLaravelにおけるこのエラーの防ぎ方を書きます。
前提としてsudo php artisan hogehoge(root以外が触れられるべきでないローカル領域に触れる処理とか)とwebサーバによるpublic/index.php(webページの表示)の二つが走るものとします。この前提の鬼門はrootユーザ製ログファイルにapache等のwebサーバがログを追記しようとする場合です。デフォルトでは次のようなファイルができあがり、webサーバに書き込み権限がないままwebサーバがログを書こうとしてこけます。
-rw-r--r-- 1 root root 1368 10月 1 17:13 laravel-2019-10-01.log
いくつか試した対応策で私的に最も有効なのは次です。
// config/logging.php <?php use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogUdpHandler; // whoamiコマンドを実行して現在のPHPプロセスの所有者を得る // whoamiはwhoamiを実行したユーザの有効なuserid(ユーザ名)を表示するコマンド $__current_process_user = trim(shell_exec('whoami')); return [ /// 省略 /// 'channels' => [ /// 省略 /// 'daily' => [ 'driver' => 'daily', // whoamiから得た名前別にログファイルを分ける 'path' => storage_path('logs/laravel-'.$__current_process_user.'.log'), 'level' => 'debug', ], /// 省略 /// ], ];
コードのコメントにある通りwhoamiコマンドからプログラムの実行ユーザを得て、名前別にログファイルを分けるやり方です。
これを用いると次のようにログファイルが分割され、権限による問題が起きなくなります。
-rw-rw-r-- 1 apache apache 234 10月 1 17:25 laravel-apache-2019-10-01.log -rw-rw-r-- 1 cplab cplab 1332 10月 1 17:25 laravel-cplab-2019-10-01.log -rw-rw-r-- 1 root root 1368 10月 1 17:13 laravel-root-2019-10-01.log
ログを時系列順に見たいならcat, sortコマンドがいくらか役に立ちます。
cat laravel-*-2019-10-01.log | sort
とすれば、Laravelログ共通の[2019-10-01 17:19:00] local.DEBUG: を用いて各行が時系列順に結合された結果を見れます。いくらか、というのはスタックトレース等の複数行に渡るメッセージが壊れるからです。残念ながらこれの対策は個別にファイルを見るぐらいしか見つけられていません。
以下の二つは余談的な他のPermission denied対策です。状況によっては有効かもしれません。
一つ目はログファイルのデフォルトアクセス権限を変えるやり方です。
// config/logging.php 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', 'permission' => 0666,// 権限が設定できる ],
デフォルトのアクセス権限を誰でも読み書き可にすることでroot:rootなログファイルがあってもwebサーバから追記できます。誰でも既存のログを破壊できる点が気になって没にしました。
二つ目はPHP組み込み関数get_current_userを使うやり方です。
// config/logging.php 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel-'.get_current_user().'.log'), 'level' => 'debug', ],
一見shell_exec(‘whoami’)と同様の結果を得られそうな関数名ですが異なる動作をします。get_current_userは現在のPHPスクリプトの所有者の名前を返します。どういうことかというと
-rw-r--r-- 1 cplab cplab 1686 9月 19 12:02 artisan
というファイルがあって
sudo php artisan hoge
とするとget_current_userはcplabを返します。しかしプロセス所有者はrootなので生成されるログファイルの所有者はrootです。artisanとwebページを分ける意味では適していますが実行ユーザ基準でログを分離するwhoamiの方がより安全と考えて没になりました。