📄articles 📋snippets 📁categories ⚙️uses ✏️about 🔍search

WP-Cron 替代方案:systemd timer 和宝塔计划任务实战

WP-Cron 替代——WordPress 内置的 WP-Cron 是一个出名的性能杀手。它不是一个真正的系统级定时任务:每次有人访问你的网站,WordPress 才检查“有没有到期的任务要跑”。这意味着高并发时可能触发多次、低流量时根本不会跑、PHP 执行超时直接中断。生产环境必须做 WP-Cron 替代。

WP-Cron 替代方案:systemd timer 对比 WordPress 内置 Cron

为什么 WP-Cron 需要替代

WordPress 的 WP-Cron 依赖页面访问触发。一个 2C2G 的 VPS 跑三个站,用户每次 F5 都在赌“这次会不会撞上 wp-cron.php”。替代 WP-Cron 的三个原因:

  • 性能:每次请求都可能触发 PHP 进程执行定时任务,拖慢响应
  • 可靠性:凌晨没人访问,定时发布文章根本发不出去
  • 可控性:没有日志、没有重试、不知道任务到底跑了没

禁用了 WP-Cron 必须有 WP-Cron 替代方案,否则定时发布、插件更新、自动备份全部停摆。我在一台 2C2G 的 VPS 上跑三个 WordPress 站,之前在高峰期遇到过 wp-cron.php 被触发 4 次导致 PHP-FPM 全部占满的情况——就是因为没做 WP-Cron 替代。改成外部定时触发后,PHP 进程数稳定在 5-8 个,再也没有突然飙到 30+。下面两个 WP-Cron 替代方案,选一个。

WP-Cron 替代方案一:systemd timer(推荐)

systemd timer 是生产环境最干净的 WP-Cron 替代。零依赖、自带日志、可以精确到秒、支持失败重试。适用于任何 Linux 服务器。

Step 1:禁用 WP-Cron

wp-config.php 里加一行,彻底关掉内置 WP-Cron:

define('DISABLE_WP_CRON', true);

保存后,所有 WordPress 定时任务(定时发布、更新检查、备份插件)都不会自动执行了。这正是我们做 WP-Cron 替代的目的——换成可控的外部触发器。

Step 2:创建 systemd service 文件

sudo tee /etc/systemd/system/wp-cron.service << 'EOF'
[Unit]
Description=WordPress Cron Trigger
After=network.target

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/bin/curl -sS -o /dev/null -w "%%{http_code}" 
  -H "User-Agent: WordPress/wp-cron" 
  https://你的域名/wp-cron.php?doing_wp_cron=1
EOF

Step 3:创建 systemd timer 文件

sudo tee /etc/systemd/system/wp-cron.timer << 'EOF'
[Unit]
Description=WordPress Cron Timer - Every 5 Minutes
Requires=wp-cron.service

[Timer]
OnCalendar=*:0/5
Persistent=true
Unit=wp-cron.service

[Install]
WantedBy=timers.target
EOF

Persistent=true 保证如果服务器在触发时刻是关机的,开机后立即补跑一次。这是 WP-Cron 替代方案的一个关键配置。

Step 4:启用并验证

sudo systemctl daemon-reload
sudo systemctl enable --now wp-cron.timer

# 查看 timer 状态
sudo systemctl status wp-cron.timer

# 看每次执行的返回码
sudo journalctl -u wp-cron.service -f

如果日志里每 5 分钟出现一次 HTTP 200,WP-Cron 替代就完成了。以后看日志只需要一条命令:journalctl -u wp-cron.service --since "1 hour ago"

WP-Cron 替代方案二:宝塔面板计划任务

如果你已经在用宝塔面板,这个 WP-Cron 替代方案更直观——图形界面,不需要碰 systemd。

  1. 宝塔面板 → 计划任务 → 添加
  2. 任务类型:Shell 脚本
  3. 任务名称:WordPress Cron
  4. 执行周期:每 5 分钟
  5. 脚本内容:
#!/bin/bash
/usr/bin/curl -sS -o /dev/null -w "%{http_code}n" 
  -H "User-Agent: WordPress/wp-cron" 
  https://你的域名/wp-cron.php?doing_wp_cron=1 
  >> /www/wwwroot/cron-logs/wp-cron.log 2>&1

先创建日志目录:sudo mkdir -p /www/wwwroot/cron-logs。然后点“执行”手动跑一次,到 /www/wwwroot/cron-logs/wp-cron.log 确认输出是 200。

WP-Cron 替代:两个方案对比

systemd timer宝塔计划任务
依赖无,纯 Linux 系统功能需要宝塔面板
日志journalctl 统一管理手动指定日志文件
精确度可以到秒级最短 1 分钟
失败重试支持 OnFailure不支持
迁移两个文件 scp 到新机器就能用需要在面板里重新创建
推荐场景任何 Linux 服务器已用宝塔、不想碰命令行

WP-Cron 替代常见问题

curl 返回 000 或 403

返回 000 通常意味着连接失败——域名解析不到或者 Nginx 没响应。排查:

# 确认域名能解析到本机
dig +short 你的域名
# 如果解析不到,加 hosts
echo "127.0.0.1 你的域名" >> /etc/hosts
curl -v https://你的域名/wp-cron.php?doing_wp_cron=1

403 是 Nginx 安全规则拦截——检查有没有屏蔽空 User-Agent、有没有拦截本地 IP(127.0.0.1)、wp-cron.php 有没有被 Nginx 规则禁止访问。我们已经加了 User-Agent: WordPress/wp-cron 绕过空 UA 拦截。

定时任务在执行,但文章没有定时发布

先确认 WP-Cron 替代确实在跑:看日志里 HTTP 200 是否每 5 分钟出现。如果 200 正常但定时文章没发,可能是 cron 事件队列出了问题。用 WP-CLI 检查:

wp cron event list --path=/www/wwwroot/你的域名
wp cron event run --due-now --path=/www/wwwroot/你的域名

多个 WordPress 站怎么管理

一台服务器上有多个站都做了 WP-Cron 替代,两种做法:

  • 每个站一个 systemd timer,文件命名用站点前缀区分(site-a-cron.timer、site-b-cron.timer)
  • 一个统一脚本,把所有站的 wp-cron.php URL 写进数组循环 curl,一个 timer 管所有站

总结

WP-Cron 替代是 WordPress 生产环境必须做的事。禁用了内置 WP-Cron 之后,定时发布、备份、更新才不会在每次页面访问时随机触发——代价就是你必须自己搭一个外部触发器。两个 WP-Cron 替代方案:systemd timer 适合任何 Linux 环境,零依赖、有 journalctl 日志、支持精确到秒和失败重试,是我个人推荐的生产方案;宝塔计划任务 适合已经有面板的环境,图形化操作省心。选哪个看你的习惯,但必须选一个——禁用了不补,定时文章永远发不出去。

如果你在做服务器优化,这两篇可能对你有用:Nginx FastCGI Cache 完整指南Linux BBR 加速

© 2026 WP-Cron 替代方案:systemd timer 和宝塔计划任务实战 · 本文由 Charlie 原创撰写,发布于 sodebug.com。 未经授权禁止转载、洗稿、机器抓取。AI 训练数据使用需获得书面授权。
GK
独立开发者,在 WordPress、Nginx 和各种 API 之间切换。不写没用的东西。

related相关文章

#01Typecho生成sitemap.xml1 min#02VPS常用测试脚本大全2 min#03centos 7 远程 ssh connection refused解决方案1 min
$ echo "less bullshit, more debugging" | send-to-inbox
新文章直接发到邮箱,一个月 2-4 封。
$ subscribe →