在平常的开发中,日志可以记录应用出现的一些错误,也可以记录一些操作结果。
Laravel使用功能强大的Monolog库进行日志处理,使用起来非常方便。在使用过程中,使用Log的Facade可以轻松实现各种记录的需求。然而,有的时候却会遇到类似(log file) could not be opened: failed to open stream: Permission denied的错误。
问题分析
这是权限的问题,执行当前线程的用户(user)没有相关日志文件的操作权限,这里分两种情况。
-
日志文件已经存在,无法在已有日志文件中追加内容。因为
Linux是一个多用户的操作系统,出于安全的考虑,不同的用户有不同的权限,比如属于用户 A 的文件,用户 B 一般是没有操作权限的,尤其是写入的权限。 -
不存在日志文件,这是无法写新文件。
解决方案
以前遇到这种问题,基本就是使用
chmod命令更改相应文件或者目录的操作权限,甚至是将已存在的文件删除,也确实是立杆见影,命令执行完错误也不见了,然而指不定什么时候,熟悉的错误就又回来了,这就说明之前的操作治标不治本呀,没有从根本上解决问题。
无法创建日志文件的解决方案
这种问题其实好办,无法创建目录的问题一般出现在项目的创建初期,可能是 storage 目录的权限没有放开,只要执行以下 chmod 命令赋予修改一下权限就可以了。一般不建议直接将文件的权限属性改成 777,据说这样会有一些安全上的隐患。这个命令执行完,新创建日志文件的时候,基本不会再出现权限相关的错误了。
追加日志内容时无权限的解决方案
追加日志内容时的权限问题,基本是发生在应用有使用 Artisan 命令行执行任务调度的时候。一般我们用 supervisor 管理进程,进而实现定时任务的执行,其本质依旧是使用 crontab 来实现的,而执行 crontab 线程的默认用户是 root,而普通 web 访问时执行 php-fpm 线程的通常不是 root 用户,可能是 nobody 用户。如果一个日志文件是由 root 用户创建的,nobody 用户当然没有该文件的操作权限,运行的时候自然会出现错误。
当问题的原因分析清楚之后,解决方案就不那么难了,曾经傻乎乎地使用 chmod 命令去修改日志文件的访问权限,简直可笑呀,现在不能再那么做了。
在 Google 上一番搜索之后,终于找到了比较优雅的解决方案。
在使用 crontab 设置定时任务时,其实是可以指定用户的。默认情况下,crontab 处理的是 root 用户的任务,我们可以通过追加 -u 选项来指定用户。
crontab -u nobody -l
显示
nobody用户的用户列表
$ crontab -u nobody -l
* * * * * cd /var/www/StrawberryApi && /usr/local/bin/php /var/www/StrawberryApi/artisan schedule:run >> /dev/null 2>&1
* * * * * cd /var/www/Inquiry_Patient && /usr/local/bin/php /var/www/Inquiry_Patient/artisan schedule:run >> /dev/null 2>&1
crontab -u nobody -e
编辑修改
nobody用户的任务列表
$ crontab -u nobody -e
* * * * * some-command-you-want-to-add-for-user-nobody
在获知 crontab 的这个功能之后,问题就可以十分优雅地解决了。将报错时所执行的任务从 root 用户的任务列表中删除,并加入到 nobody 用户的任务列表,然后就好咯。