在 Yii2.0.48 中实现 Cron 定时任务需同时配置控制台命令与系统 crontab:先创建继承 yii\console\Controller 的控制器及 action 方法,再通过 crontab 调用 php yii 命令,并注意目录切换、日志追加、锁机制与权限设置。

在 Yii2.0.48 中配置 Cron 实现自动化定时任务,必须同时完成控制台命令开发与系统级 crontab 调度,漏掉任意一环任务都不会执行——因为框架本身不提供内置调度器,所有周期性逻辑都依赖外部触发。
创建可被调用的控制台命令
进入项目根目录,在 console/controllers/ 下新建 CleanController.php:
命名空间必须为 console\controllers,类名以 Controller 结尾,且继承 yii\console\Controller;方法名必须以 action 开头,例如 actionOldLogs,否则无法通过 php yii clean/old-logs 调用。
在方法内写清理逻辑,比如删除 30 天前的日志文件:
public function actionOldLogs() { $logPath = \Yii::getAlias('@app/runtime/logs'); $files = glob($logPath . '/*.log'); foreach ($files as $file) { if (filemtime($file)
这一步操作起来很简单,直接把文件拖进去就行。但注意:不要在 init() 或构造函数里连接数据库或扫描大目录,否则命令启动就卡住。
验证命令能否本地运行
切到项目根目录,执行:php yii clean/old-logs
看到输出或日志生成,说明命令结构正确。若报错 Class 'console\controllers\CleanController' not found,检查文件是否放在 console/controllers/ 下、类名拼写是否正确、命名空间是否为 console\controllers。
【必须确认该命令在当前用户权限下能成功执行,否则加进 crontab 后必然失败】
配置 crontab 行(Linux)
运行 crontab -e,添加一行:
方法一:基础写法(适合调试)
0 2 * * * cd /var/www/myapp && /usr/bin/php yii clean/old-logs >> /var/www/myapp/runtime/logs/cron.log 2>&1
方法二:生产环境推荐(防并发+超时)
0 2 * * * flock -xn /tmp/clean_old_logs.lock -c "timeout 600 /usr/bin/php /var/www/myapp/yii clean/old-logs" >> /var/www/myapp/runtime/logs/cron.log 2>&1
第一列是分钟,第二列是小时,所以 0 2 * * * 表示每天凌晨 2 点整执行;cd /var/www/myapp 是关键,不切换目录会导致 Yii 找不到配置;>> 追加日志比 > 更安全,避免覆盖历史记录;2>&1 把错误也写进日志,方便排查。
注意:路径中的 /var/www/myapp 必须替换成你真实的项目根目录,/usr/bin/php 要用 which php 查准,容器或宝塔环境常见路径是 /www/server/php/81/bin/php。
确保运行权限与日志可写
第一步:确认 crontab 所属用户对以下路径有读写权限:
① 项目根目录(尤其是 runtime/ 和 runtime/logs/)
② /tmp/clean_old_logs.lock 所在的临时目录
③ 日志文件路径(如 /var/www/myapp/runtime/logs/cron.log)
第二步:手动创建日志目录并赋权:mkdir -p /var/www/myapp/runtime/logschown -R www-data:www-data /var/www/myapp/runtime(根据实际 Web 用户调整)
第三步:测试锁机制是否生效:
执行一次 flock -xn /tmp/clean_old_logs.lock -c "echo test",返回 0 表示锁可用;返回 1 表示已被占用。
如果 runtime 目录不可写,命令会静默失败,日志里连错误都不会留下。
检查任务是否真正运行
① 查看 cron 日志:grep CRON /var/log/syslog(Ubuntu/Debian)或 grep cron /var/log/messages(CentOS)
② 查看自定义日志:tail -f /var/www/myapp/runtime/logs/cron.log
③ 手动触发并观察锁文件:ls -l /tmp/clean_old_logs.lock,存在说明 flock 生效;不存在可能是命令没跑起来,也可能是执行太快已释放。
④ 检查退出码:在命令末尾加 ; echo $? ,返回 0 表示成功,非 0 表示异常中断。


















