Laravel日志出现权限问题的常见情况
背景#
近期时不时会因为日志文件权限问题,抛出 “failed to open stream: Permission denied” 的异常。解决的办法可以无脑给这个文件、目录甚至整个项目授予 777 的权限,迅速解决问题,但是再迅速也得等人登上服务器去改一下权限,下次出现问题依然会导致服务中断。
我分析了一下,主要原因是有多个系统用户针对同一个日志文件进行操作。总结了一些复现的场景,希望能让你 debug 的时候你少踩点坑。这里只是针对日志文件场景,其他文件理论上是相通的。
laravel 日志记录方式#
laravel 默认是以单个文件的形式存放到项目的 storage/logs/laravel.log 这个地方
如果你改成了按日期的,文件名就会使用 laravel-YYYY-MM-DD.log 这样子的格式生成。
如图这个例子,日志文件的拥有者有 root 以及 www-data
如果是按日期保存,你把全部文件 777 了,只能保证当前全部文件不会有问题。但是明天可能会有新的日志文件生成出来,这个新生成的文件权限未必是 777 的哦。这就很容易出现因为权限问题导致的无法写入。一旦某个用户(比如 root)生成了今天的日志文件,那 FPM 就很可能无法写入。
如果是单个文件的形式保存,chmod 777 laravel.log 理论上可以快速解决。
可能存在的多用户写入场景#
首先查看 FPM 的用户:
ps -aux |grep php
然后可以看到 FPM 用户是 www-data,下面开始排查
1. 队列#
laravel 的队列一般是由 Supervisor 来维护,如果你用了队列,请检查运行队列监听命令的用户与 FPM 进程的用户是否一致。
Supervisor 配置文件通常存储在 /etc/supervisor/conf.d 目录。
需要注意的是 Supervisor 配置文件里 stdout_logfile 一般存放在 /var/log/supervisor/ 或你自己喜欢的路径,主要是记录在什么时间处理了什么任务,如果你在队列的执行过程中 echo 了一些信息也会写到这个日志,跟项目里 storage/logs/laravel.log 的日志不是一个东西,不要共用。
2. cli 命令#
cli 命令主要包括
- 你或你的同事使用 root、ubuntu、ec2-user 等用户登入服务器,在项目里执行 php artisan XXXXX
- 你或你的同事使用 cron/crontab 等工具调度,最后执行了 php artisan XXXXX 等的项目命令
如果是你或你的同事登入服务器操作,建议退出前去看一下日志的拥有者 / 权限。
如果是通过 cron/crontab 方式运行的,那就需要检查运行命令的用户是否与 FPM 用户一致,如果不是需要修改成一样的。以我的 www-data 用户为例,使用 crontab 的定时任务查看:执行上面这个命令就会显示出 www-data 的定时任务,如果服务器有 crontab 的调度,但显示 no crontab for www-data 或者显示的全是 #开头的,那大概率这里会导致的日志文件拥有者不一致。crontab -u www-data -l
3. 其他,说不定是同事坑你了#
上面的 2 种场景应该是很常见的,你都确认了没有问题,就得结合你的服务器实际情况慢慢排查了,欢迎交流。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: