嗯,真香!使用 www-data 用户运行定时任务(cron)

感谢 @Larva 在评论区的评论,大家可以采用他说的简单的方式

你新建个用户放 www-data 组就完事了。你搞复杂了

===== 以下是原文 =========

其实这个没啥好说的,就是记录下解决的过程(说得好像跟一篇水文似的…)。或者给遇到这类问题的小伙伴提供个思路。

痛点

我们在部署 web 服务时,经常用到定时任务。正常的流程就是直接执行下面的指令来配置定时任务

crontab -e

问题来了,正常情况下,这个指令在哪个用户下面执行,这个权限就是谁的(如果你听不懂我在说啥,那基本就是属于 root的)。

定时任务本身的配置也是个精细活,你可以阅读下 博客:你一定是用了假的 Linux cron 看看你之前用的姿势是不是还能优化。

常见问题之日志权限

这怕是最常见的问题了。定时任务出错了,记录日志到 storage/logs 里了,一般就是 laravel.log 文件。

此时 laravel.log 所属者就是 root 了。

用户通过浏览器访问我们网站,如果出错,以 www-data 身份尝试记录到 storage/logs/laravel.log,然后写不进去,一直报错,真香!

解决

打开谷歌搜索 run cron job as www-data。找到了文章 askubuntu.com/questions/189189/how...

谷歌真香!

具体的意思,就是直接在 /etc/crontab 中编辑定时任务即可,加上用户名。

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#


# cron
* * * * *  www-data flock /tmp/flock1.lock -c 'timeout 200 /usr/local/bin/php /var/www/html/laravel/artisan command >> /home/log/laravel.log 2>&1'

啰嗦下:

  • flock 用来防止重复执行,起到原子锁作用
  • timeout 表示这个脚本执行过长,咱就干死它,可以有效避免各种循环或长时间占用问题
    - >> 表示向文件中追加内容
    - 2>&1 表示无论错误与否,都可以执行

关于划线的两个表述,感谢 @godruoyi 在评论区指正,大家可以看评论区,我摘录如下:

>> 表示向文件中追加内容
>&1 表示无论错误与否,都可以执行
上面这两点其实表述是不正确的:

> 表示覆盖追加
>> 表示尾部追加
这两个管道操作符,在执行期间发生错误时,是不会将错误输出写入后面的「文件」中的。

在 Linux 系统中 0、1、2 分别表示不同的设备类型,其中

0 标准输入设备,指键盘
1 标准正确输出设备
2 标准错误输出设备

php artisan command >> /home/log/laravel.log 2>&1'

上面命令的意思是将 php artisan command 的 标准正确输出 重定向到 laravel.log 文件。
而后面的 2>&1 是表示将标注错误输出重定向到标准正确输出。

从而达到错误输出和正确输出都记录在 laravel.log 文件中。

嗯。。。香!

真香后传(更新于 2019年11月06日19:38:27)

如果你按照上述的进行,你会发现还是执行不了定时任务。因为 www-data 默认是不能执行 bash 相关操作的。

使用真香的谷歌搜索 www-data run cron error,我们发现了宝藏 ubuntuforums.org/showthread.php?t=...

The www-data user is not able to invoke a shell by default. In /etc/passwd you’ll see
Code:\ www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\ If you want to be able to run scripts as that user, you’ll need to change “/usr/sbin/nologin” to “/bin/bash”.

好了,咱们把 /etc/passwd 里面 www-data 对应的那一行改下就可以了。

另外

其实你还可以用 crontab -u www-data CRON_FILE 来指定用户运行指定的定时任务。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 13
godruoyi
  1. >> 表示向文件中追加内容
  2. >&1 表示无论错误与否,都可以执行

上面这两点其实表述是不正确的:

  • > 表示覆盖追加
  • >> 表示尾部追加

这两个管道操作符,在执行期间发生错误时,是不会将错误输出写入后面的「文件」中的。

在 Linux 系统中 0、1、2分别表示不同的设备类型,其中

  • 0 标准输入设备,指键盘
  • 1 标准正确输出设备
  • 2 标准错误输出设备
php artisan command >> /home/log/laravel.log 2>&1'

上面命令的意思是将 php artisan command标准正确输出 重定向到 laravel.log 文件。
而后面的 2>&1 是表示将标注错误输出重定向到标准正确输出

从而达到错误输出和正确输出都记录在 laravel.log 文件中。

4年前 评论
流浪剑客

crontab -u 用户名 -e ,
使用 -u 可以指定用户的

4年前 评论
流浪剑客

crontab -u 用户名 -e ,
使用 -u 可以指定用户的

4年前 评论
rovast

@流浪剑客 斯温大哥说得对,学到了。

我的场景稍微特殊点,我是在 docker 里部署的,新建了 crontab 文件,挂到容器里的 /etc/crontab

4年前 评论
clyde-cn

这个是超级香的

4年前 评论
王举

大佬说得对,真的香 :+1:

4年前 评论
godruoyi
  1. >> 表示向文件中追加内容
  2. >&1 表示无论错误与否,都可以执行

上面这两点其实表述是不正确的:

  • > 表示覆盖追加
  • >> 表示尾部追加

这两个管道操作符,在执行期间发生错误时,是不会将错误输出写入后面的「文件」中的。

在 Linux 系统中 0、1、2分别表示不同的设备类型,其中

  • 0 标准输入设备,指键盘
  • 1 标准正确输出设备
  • 2 标准错误输出设备
php artisan command >> /home/log/laravel.log 2>&1'

上面命令的意思是将 php artisan command标准正确输出 重定向到 laravel.log 文件。
而后面的 2>&1 是表示将标注错误输出重定向到标准正确输出

从而达到错误输出和正确输出都记录在 laravel.log 文件中。

4年前 评论
rovast

@godruoyi :+1: 受教了

感谢指正,已更新

4年前 评论

看完不知道你是要解决什么问题以及如何解决了问题...... 尤其是没有遇到这个业务场景的情况下

各种逻辑混乱、跳跃

比如最后一句 咱们把 /etc/passwd 里面 www-data 对应的那一行改下就可以了

4年前 评论
raybon 2年前

You could create a crontab for the specific user like so:

crontab -u -e
Or more simply, you could just run crontab -e when logged in as that user.

Alternatively, you could prefix your command in your (root) crontab with sudo -u to run the command as the specified user.

4年前 评论
rovast (楼主) 4年前

还存在一种情况就是,部分job需要www部分需要root这种咋设置 :joy:

4年前 评论
rovast (楼主) 4年前

之前项目中遇到了这个问题 老是日志写不进去 最后才发现command在每天凌晨执行得是root;导致日志一生成就是root的,后边日志就无法写入了

4年前 评论
rovast (楼主) 4年前

你新建个用户放www-data组就完事了。你搞复杂了

3年前 评论
Larva (作者) 3年前
rovast (楼主) 3年前
Larva (作者) 3年前
jxdr 3年前

是的, 这样可以。

3年前 评论

sudo su - www-data -s /bin/bash 即可

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!