PHP本身并没有内置的定时任务调度器——这事儿得靠外部工具来帮忙。主流的做法无非两种:要么跟系统级的Cron配合,要么在PHP内部解析Cron表达式来判断是否该干活了。核心思路说白了,就是让Cron来触发PHP脚本执行,或者反过来,在PHP代码里自己判断时间条件。
用Linux Cron调用PHP脚本
这是最稳、最常用的方式,没有之一。Cron是操作系统级别的调度工具,PHP只需要提供一个可执行的脚本就行。
有几个前提条件得先确认:
- PHP CLI模式可用——终端里敲php -v能正常看到版本号,说明没问题。
- 写一个独立的PHP脚本,比如放在/var/www/task.php,开头可以加上shebang(但不是必须的):
#!/usr/bin/env php - 给脚本加上执行权限:chmod +x /var/www/task.php
- 编辑当前用户的Cron表:crontab -e,然后添加一行,比如:
*/5 * * * * /usr/bin/php /var/www/task.php > /dev/null 2>&1
这行配置的意思是:每5分钟执行一次这个脚本。
至于输出重定向那部分,后面会细说,但先记住这个模式就行。
理解Cron表达式格式
Cron表达式看着复杂,但掌握规律后其实很简单。它通常由5个字段组成,用空格分隔,每个字段代表一个时间单位:
- 分钟(0–59)——比如*/10表示每10分钟触发一次。
- 小时(0–23)——比如9-17表示上午9点到下午5点之间。
- 日期(1–31)——比如1,15表示每月1号和15号。
- 月份(1–12)——*表示所有月份。
- 星期几(0–7,0和7都代表周日)——比如1-5表示周一至周五。
几个常见例子感受一下:
0 2 * * *→ 每天凌晨2点执行30 8 * * 1-5→ 工作日上午8:30执行0 */6 * * *→ 每6小时执行一次(也就是0点、6点、12点、18点)

在PHP中解析Cron表达式(非替代系统Cron)
有些场景下,系统Cron并不是唯一的选择。比如你需要做可视化任务管理、动态测试调度逻辑,或者在PHP运行时判断某个时间点是否匹配Cron表达式。这时候可以用轻量级的库,比如dragonmantank/cron-expression。
这个库Lara vel底层就在用,维护活跃,支持PHP 7.4+,而且没有框架依赖,很干净。
安装方式:composer require dragonmantank/cron-expression
用法示例:
$cron = CronExpression::factory('* * * * *'); // 每分钟
if ($cron->isDue()) {
echo "该执行了";
}
// 或检查指定时间:
$dt = new DateTime('2024-05-20 14:30:00');
if ($cron->isSatisfiedBy($dt)) {
echo "这个时间满足表达式";
}
关键方法就两个:isDue() 判断当前时间是否触发,getNextRunDate() 获取下次执行时间。注意时区要对齐,字段也要符合规范。
避免常见陷阱
最后说几个容易踩的坑,都是实战中遇到过的:
- 环境差异:Cron执行时使用的PATH环境变量通常比交互式Shell短得多,所以路径一定要写绝对,比如/usr/bin/php,而不是直接写php。
- 工作目录不确定:Cron启动时,当前目录可能是用户的家目录,而不是脚本所在目录。所以PHP脚本里最好用__DIR__或者chdir()显式切换目录。
- 输出重定向:不加> /dev/null 2>&1的话,Cron会把脚本输出通过邮件发给用户,如果脚本频繁执行,邮件会迅速堆积——尤其是root用户,很容易被忽略的邮件撑爆。
- Web和CLI的PHP配置不同:命令行模式下,PHP可能没有加载某些扩展(比如pdo、curl)。运行前最好用php -m确认一下需要的扩展已经启用。
路径写绝对、目录用__DIR__、输出别忘重定向——这三点能做到,基本就不会出大问题。