cron_schedule 里一片 missed,但 SSH 下执行 bin/magento cron:run 又能成功。这个现象反而说明 PHP 和 Magento 命令本身大概率可用,差异在“谁、什么时候、用什么环境自动执行”。
先证明系统Cron真的每分钟触发
检查运行 Magento 的系统用户 crontab,不要只看 root。确认路径是当前 release,标准输出和错误没有被静默丢弃。部署切换软链接后,旧 crontab 指向过期目录也是常见原因。
crontab -u www-data -l
journalctl -u cron --since "30 minutes ago"
ps -ef | grep '[c]ron:run'
在 crontab 中使用绝对 PHP 路径和 Magento 根目录。交互 Shell 里可用的 PHP 版本、PATH、内存限制和环境变量,cron 用户不一定有。把 php -v 和必要环境写入临时诊断日志,很快能看出差异。
missed表示错过调度窗口,不等于任务代码报错
查看 scheduled_at、executed_at 和 finished_at。某个任务运行太久或锁未释放,会让后续任务来不及在允许窗口内启动。按 job_code 分组统计 pending、running、missed 数量,比只看最新十行更有用。
SELECT job_code, status, COUNT(*)
FROM cron_schedule
WHERE created_at > UTC_TIMESTAMP() - INTERVAL 2 HOUR
GROUP BY job_code, status;
如果总是同一个 job_code 长时间 running,就查它的业务和外部依赖。不要先批量把 running 改成 success,那只会隐藏锁和重复执行风险。
多节点只能让正确的节点负责调度
Web 节点都装了相同 crontab 时,若没有合适锁机制可能重复跑;发布时所有节点又同时停 cron,则会集体漏跑。明确 cron 主机、消费者主机和共享数据库,并记录每次执行的 hostname。
修复后至少观察两个调度周期,确认 schedule 记录按预期提前生成、到点执行、状态 success。手动跑通一次只能证明当前命令可运行,持续没有 missed 才说明自动调度恢复。

