在 Mac 上使用 cron 服务来实现 Laravel 项目任务调度
在查看 Laravel 任务调度文档 本地运行调度程序 时,发现 Laravel 框架提供了一个任务调度运行指令:
该命令将在前台运行,并每分钟调用一次调度程序,直到你终止该命令为止
# 项目目录下执行
~ php artisan schedule:work
INFO Running scheduled tasks every minute.
2023-10-20 16:06:00 Running ['artisan' app:sync-user] ........... 227ms DONE
⇂ '/usr/local/Cellar/php/8.2.8_1/bin/php' 'artisan' app:sync-user > '/dev/null' 2>&1
每次执行的日志都明明白白的显示在终端上,这不是完美解决本地任务调度的问题吗?似乎不需要本地启用 cron 了。
新建的一个 Laravel 项目,需要测试一下任务调度功能,当时突然想的就是,为什么不能像 Linux 系统一样安装使用 cron 服务呢?百度了一下,还真的可以在 Mac 下安装使用 cron。以下内容主要参考:【系统】Mac 本地crontab定时任务详解,
在 Mac 上使用 crontab 服务。
启用 Mac 下的 cron 服务
查看 cron 任务是否存在
Mac 的定时任务由 launchctl 来管理,查看 launchctl 任务列表:
~ launchctl list| grep cron
# 已存在,会显示出来
41082 0 com.vix.cron
未启动时默认时找不到的。
查找 cron 任务启动项的配置
~ locate com.vix.cron
# 已启动的会显示配置地址
/System/Library/LaunchDaemons/com.vix.cron.plist
未启动会有指令提示:
WARNING: The locate database (/var/db/locate.database) does not exist.
To create the database, run the following command:
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist
Please be aware that the database can take some time to generate; once
the database has been created, this message will no longer appear.
加载 cron 配置
执行 sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist
以加载配置。
该指令执行完没有给出结果,执行需要时间完成。重复执行记载配置或者查找配置都是无用功,需要耐心等待。我这边重复执行报错:
Load failed: 5: Input/output error
Try running `launchctl bootstrap` as root for richer errors.
到现在还是这样,所以可以通过查找指令 locate com.vix.cron
来观察是否加载成功。
查看配置中 crontab 是否启动
~ cat /System/Library/LaunchDaemons/com.vix.cron.plist
...
<key>KeepAlive</key>
<dict>
<key>PathState</key>
<dict>
<key>/etc/crontab</key>
<true/>
</dict>
</dict>
...
/etc/crontab
如果不存在会印象 cron 的执行,所以需要判断是否存在,不存在就创建(也有说这个文件不重要的,不管,按照步骤执行):
~ ls /etc/crontab
ls: /etc/crontab: No such file or directory
~ sudo touch /etc/crontab
添加 Laravel 任务调度配置
~ sudo crontab -e
# 底栏显示的配置文件
"/tmp/crontab.xxx"
# 添加配置项
* * * * * cd /path-to-your-project && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
启用过程中问题分析
需要注意的有两点:
- 关键点一:修改的配置所属用户应与 nginx 或 apache 等 web 服务执行用户一致
- 关键点二:由于在crontab文件中没有配置环境变量,php 需要完整访问路径:
/usr/local/bin/php
本地使用 MAMP PRO 搭建的开发环境,setting 中的 Ports & User 菜单设置中最下面有 Run servers as:
选择项,默认选择了 User mac
,也就是当前 Mac 的登录用户。所以对应指令:sudo crontab -u mac -e
,这里测试发现 sudo crontab -e
也行,这相当于是 Mac 系统的 root
用户,所以也可以写成 sudo crontab -u root -e
。
如果遇到 “创建了crontab,任务却无法自动执行,手动可以” 的情况,还可以考虑完善 php 或其他的可执行文件路径,关键点二也是一种最终导致 Laravel 项目任务调度没有执行的原因。
在修改指定用户 cron 配置时遇到报错:crontab: must be privileged to use -u
,这是要提权操作,即指令增加 sudo
。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。