WordPress 定时发布不生效或计划任务堆积:先核 WP-Cron 与系统 crontab,再查 Action Scheduler

定时文章到点不发、后台「计划任务」越积越多,或 WooCommerce 相关队列 Pending/Failed 狂涨------这和今天槽位里写过的表单「提交成功但收不到邮件」、「建立数据库连接时出错」、「全站 HTTPS 后仍显示不安全 / 混合内容」,以及登录 Cookie、502/503、PHP 白屏/插件冲突、媒体上传失败、固定链接 404、Woo 支付回调不是一类故障。站点多半能打开、能写文章,卡在 WP-Cron 从未真正跑起来、DISABLE_WP_CRON 与系统 crontab 脱节、时区导致「未来稿」卡住,或 Action Scheduler 积压拖垮计划发布与后台任务。

更稳的顺序是:先分清是 Cron 根本不触发 / 触发了但定时稿卡住 / Action Scheduler 堆积 / 对象缓存与 transient 副作用 → 核 wp-config 与 wp cron event list → 在 DISABLE_WP_CRON 为真时补系统 crontab 或 curl → 再清 Action Scheduler 与定时稿状态。别一上来就装「伪 cron」插件叠床架屋,也别在没备份前批量删 AS 队列。

先分清:Cron 不触发 vs 定时稿卡住 vs AS 积压 vs 缓存副作用

「定时发布不生效 / 计划任务堆积」常见落在四条线上,别和 SMTP、数据库连接、HTTPS 混合内容混着改:

  • WP-Cron 从未触发 :默认依赖访客请求捎带跑 cron;站点几乎无真实流量、被全页缓存拦掉 wp-cron.php、或 DISABLE_WP_CRON 已开却没系统 crontab,事件会一直「到期未跑」。
  • Cron 在跑,但定时稿仍 future :时区(timezone_string / gmt_offset)与服务器时间不一致、编辑器点了「定时」却未真正落到 post_status=future、或发布钩子被插件短路。
  • Action Scheduler 积压(Woo / 订阅 / 邮件队列常用):Pending、Failed 暴涨;单次 batch 超时、锁未释放、对象缓存异常,表现为后台慢、相关计划任务「看起来死了」。
  • 对象缓存 / transient 副作用:cron lock、AS claim 锁、或 transient 被持久对象缓存「粘住」,表现为偶发「有时能跑有时不能」。
  • 插件互抢触发权:多个「Heartbeat / 替代 cron / 队列加速」插件同时声明自己是唯一 runner,结果谁都不稳定,或把同一批 due 事件跑多遍。

先记下:DISABLE_WP_CRON 是否为 true、最近有没有真实前台流量、wp cron event list 里 due 事件是否推进、Woo「计划操作」里 Pending/Failed 数量、是否装了超过一个伪 cron 类插件。再决定是改系统 crontab 还是清 AS。

第一步:核 wp-config、WP-Cron 事件与「访客触发」前提

能复现「到点不发 / 任务堆积」的站点上:

  1. 打开 wp-config.php,确认是否存在 define('DISABLE_WP_CRON', true);。为 true 时,WordPress 不会再靠页面访问捎带跑 cron ,必须靠系统 crontab 或外部 HTTP 打 wp-cron.php。
  2. 用 WP-CLI(有权限时):wp cron event list、wp cron test(若可用),看哪些 hook 已 due、上次 run 时间是否停滞。
  3. 无 WP-CLI 时:临时用可靠的 cron 管理插件只做只读观察(看事件列表与下次运行),不要同时开多个「替代 cron」插件互抢。
  4. 默认可视触发路径:有人访问前台/后台时,WordPress 才有机会 spawn cron。全页缓存、CDN 把 HTML 缓存到边缘且从不回源、或站点长期零流量,都会让「到点不发」变成常态。
  5. 直接浏览器或 curl 访问 https://你的域名/wp-cron.php?doing_wp_cron(注意频率,别当压测),看是否推动 due 事件;若这里能跑而日常不能,基本坐实「缺触发源」。
  6. 核对服务器时间与 WordPress 设置 → 常规里的时区;date / 面板时钟与站点时区差几小时,会直接让「定时」看起来像失灵。
  7. 若前面有 CDN / 防火墙:确认 /wp-cron.php 未被 WAF 误拦、未被强制缓存成 200 空响应;需要时对这一路径设置绕过缓存或不缓存。

预期 :能说清「谁负责触发 cron」;DISABLE_WP_CRON 状态与真实触发方式一致;due 事件在手动触发后有推进。若手动触发后定时稿仍不动,进系统 crontab 与 AS,而不是继续刷新前台碰运气。

第二步:DISABLE_WP_CRON 为真时补系统 crontab(或 curl),并防重复叠加

确认需要「真实时钟触发」而不是访客碰运气时:

  1. 常见 crontab 行(路径按实际 PHP/WP-CLI 调整),每分钟跑到期事件:
    • * * * * * cd /path/to/site && wp cron event run --due-now >/dev/null 2>&1
    • 或 * * * * * curl -s -o /dev/null "https://你的域名/wp-cron.php?doing_wp_cron"(仅在未禁用且适合 HTTP 触发时)
  2. 不要 同时:未关访客 cron + 多条重叠 crontab + 多个「强制 cron」插件。重复跑会把 CPU 打满,反而拖慢前台------计划任务本身也会变成性能问题。关于 cron 风暴、队列堆积如何抬高 TTFB、拖垮后台响应,可对照 WordPress 性能优化与站点加速 把「触发频率、batch 大小、对象缓存锁」和应用层优化放在同一张清单里核,再决定是降频、拆队列还是先修锁。
  3. crontab 用户要有读站点文件与跑 WP-CLI/PHP 的权限;容器/面板环境确认任务落在正确机器(别写在已下线的旧主机)。
  4. 时区:系统 TZ、PHP date.timezone、WordPress 时区三者对齐;只改其中一处,定时稿「提前/延后一截」很常见。
  5. 日志:短期内把 cron 输出接到文件,确认每分钟有跑、无 permission denied / PHP fatal;稳定后改回丢弃或轮转,避免日志盘暴涨。
  6. 生产注意:改 crontab 前记下旧条目;回滚时先停新任务再恢复旧触发方式,避免双轨并行。

预期 :系统级每分钟有稳定触发;wp cron event list 中 due 事件被消费;前台不再依赖「碰一个访客才发稿」。

第三步:Action Scheduler ------ Pending / Failed 积压怎么查、怎么清

WooCommerce、订阅、部分邮件/同步插件把重活丢进 Action Scheduler(后台路径常见为 WooCommerce → 状态 → 计划操作,或独立的 Action Scheduler 屏幕):

  1. 打开计划操作列表,按状态过滤 Pending / Failed / In-progress,记下数量级与最老任务的 hook 名、预定时间。
  2. Failed 先看失败原因(timeout、数据库死锁、远程 API 4xx/5xx、内存耗尽),先修根因再重试;盲目「全部重试」只会再次打满队列。
  3. Pending 长期不降:检查是否有 claim 锁未释放、对象缓存异常、或 cron 根本没跑(回到第一步)。WP-CLI 可用时:wp action-scheduler 相关子命令(版本不同以 --help 为准)做列表与受控运行,避免在网页点「一次跑一万条」。
  4. 不要盲目清空表 (如直接 truncate AS 相关表):可能丢支付后置任务、邮件、库存同步。优先取消明确无用的重复 hook、修好失败任务后按批 run。
  5. 与 WP-Cron 的关系:AS 常依赖 cron 或自身 runner 被触发;只清 AS 界面却不修触发源,Pending 会马上回来。
  6. 改完保留:截图或导出「hook 名 / 失败信息 / 数量」,便于回滚策略与之后对比。
  7. 大站点:把「每分钟 due-now」与「AS 大批量 run」错开观察窗口,先确认 cron 触发稳定,再逐步提高 AS 消费吞吐,避免同一分钟内 CPU 与数据库双峰。

预期:Pending 趋势下降;Failed 有明确归因且不再指数反弹;后台「计划操作」页可在合理时间内打开。

第四步:定时发布专病 ------ future 稿、时区与编辑器「立即 / 定时」

Cron 与 AS 都健康、仍有单篇「到点不发」时:

  1. 在文章列表过滤「定时」或直接查库/wp post get <ID> --field=post_status,确认状态是 future 而不是误存成 draft / pending。
  2. 编辑器侧:块编辑器「发布」面板里是「定时」还是别人协作时改成了「立即发布」又撤回;修订记录里看最后一次状态变更时间。
  3. 时区:设置 → 常规的时区与预期一致;作者按「北京时间 09:00」选的定时,若站点仍是 UTC,会表现为「晚八小时才动」或「好像从没到点」。
  4. 专用插件/编辑器扩展若接管发布流程,临时禁用后再用原生定时测一篇最小复现稿(标题+一段正文即可)。
  5. 钩子被短路:主题或插件 remove_action 了发布相关 hook,或把 future 转成私有状态;用健康检查 / 查询监视器看 publish_future_post 是否在到期后执行。
  6. 多时区编辑团队:约定「以站点时区为准」写进发布清单,避免每个人按本机时钟估点。

预期 :测试 future 稿在到期后自动变 publish;时区与服务器一致;无插件在到期瞬间把状态改回草稿。

第五步:验证、回滚与验收清单

  1. DISABLE_WP_CRON 与真实触发方式一致(访客 / crontab / curl 三选一为主,避免并行风暴)。
  2. wp cron event list(或等价 UI)显示 due 事件被定期消费;手动 wp cron event run --due-now 后列表有变化。
  3. 系统 crontab 仅保留必要条目;无重复 wp-cron.php 与 WP-CLI 双轨狂奔;短时日志无 fatal。
  4. Action Scheduler:Pending 下降趋势可解释;Failed 有根因记录;未擅自 truncate 业务表。
  5. 至少一篇测试定时稿:到期后前台可见、状态为 publish;时区符合预期。
  6. 抽检 TTFB / 后台「计划操作」页打开时间,确认修 cron 后没有引入新的队列风暴。
  7. 回滚预案:保留改前 crontab 原文与 AS 数量截图;若新触发方式异常,先停新任务再恢复旧方式,避免双轨并行。
  8. 验收只看技术结果(触发、消费、发稿、队列),不把「再装一个伪 cron 插件」当成收尾。

小结

定时发布不生效或计划任务堆积时,按 触发源(WP-Cron / crontab)→ Action Scheduler 积压 → 单篇 future / 时区 → 验证回滚 推进,每次只改一层并保留旧 crontab 与队列快照。把它和 SMTP 投递、数据库连接、HTTPS 混合内容、登录 Cookie、502、白屏、媒体上传、支付回调区分开,能少走很多「狂装伪 cron 插件却越积越多」的弯路。DEVDIY 实务里把「谁触发、谁消费、谁积压」三列记一笔,下次换主机或上 Woo 队列时能直接对备忘,而不是从零猜。

相关推荐
echome8881 天前
Linux 定时任务:crontab 写法与常见失效原因
linux·运维·网络·定时任务·crontab
snysy1 天前
WordPress伪静态404故障排查笔记
android·笔记·wordpress
代龙涛2 天前
WordPress Query 查询机制详解(WP_Query)
开发语言·后端·php·wordpress
李纲明2 天前
WordPress 更新插件后白屏或致命错误:先开 debug.log 与恢复模式,再二分法定位冲突插件
wordpress·白屏·致命错误·恢复模式·插件冲突·devdiy·debug.log
孙琦Ray2 天前
PrivacySafe 发布 57 个免费开源安全脚本,覆盖 139 个漏洞
wordpress·开源安全·漏洞防护·php2shell·privacysafe
李纲明2 天前
WordPress 报建立数据库连接时出错:先核 wp-config 四元组,再查 MySQL 服务与表修复
运维·数据库·mysql·wordpress·排障·devdiy
李纲明2 天前
WordPress 登录后跳回登录页或提示「Cookie 被阻止」:先核站点 URL 与 HTTPS 一致,再查安全插件与 CDN
https·登录·cdn·wordpress·cookie·devdiy·站点url
李纲明2 天前
WordPress 提示「建立数据库连接时出错」:先核 wp-config 与数据库服务,再查表损坏与磁盘配额
数据库·wordpress·devdiy
李纲明2 天前
WordPress 全站 HTTPS 后仍显示「不安全」或锁被划掉:先清混合内容,再核证书链与强制跳转
网络协议·安全·https·wordpress·devdiy·混合内容