在查看 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