【Laravel】ログファイルのPermission deniedを恒久的に防ぐ

 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の方がより安全と考えて没になりました。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG