Laravel 定时任务导致日志写入失败问题的解决方案

初衷

好久没写博客了, 水上一篇

背景

最近使用 laravel 重构项目, 需要经常查看日志.
默认日志配置全部存在了同一个文件里, 非常不方便, 因此将默认通道修改为 daily.
修改完毕后, 发现新日志文件会有写入权限问题, 导致代码无法运行.

分析

原因其实很简单, 项目中运行的定时任务导致的.

日志文件的拥有者, 一般都是创建文件的进程用户.

Crontab 运行 Command 时, 使用的用户是 root.

运行代码的用户一般是启动 Apache Nginx等的用户, 比如我们的测试环境是运行在 laradock 容器里的, 启动 nginx 使用的是用户名称就是 laradock, log 文件拥有者也是 laradock.

检查了一下 monolog 的代码, 在 src/Monolog/Handler/StreamHandler.php 里发现了这么一句话

    * @param int|null        $filePermission Optional file permissions (default (0644) are only for owner read/write)

发现 monolog 默认文件权限是 0644, 也就是只有拥有者才能写入日志

修复

继续查看代码, 发现是 src/Monolog/Handler/RotatingFileHandler.php 继承了 src/Monolog/Handler/StreamHandler.php,
最终在 src/Illuminate/Log/LogManager.php 实例化了 RotatingFileHandler.php.
代码如下:

    /**
     * Create an instance of the daily file log driver.
     *
     * @param  array  $config
     * @return \Psr\Log\LoggerInterface
     */
    protected function createDailyDriver(array $config)
    {
        return new Monolog($this->parseChannel($config), [
            $this->prepareHandler(new RotatingFileHandler(
                $config['path'], $config['days'] ?? 7, $this->level($config),
                $config['bubble'] ?? true, $config['permission'] ?? null, $config['locking'] ?? false
            ), $config),
        ]);
    }

最终发现是 $config[‘permission’] 参数, $config 则是直接读取的配置文件.
至此, 解决方案就已经出炉了: 增加 permission 参数, 权限直接设置为 0666, 允许所有人写入.
实例如下:

        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => env('LOG_LEVEL', 'debug'),
            'days' => 14,
            'permission' => 0666,
        ],

备注

permission 必须是八进制数字, 至于原因, 就不赘述了


版权声明:本文为cs958903980原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>