一个每天凌晨四点备份的站点,日志里连续十二天没生成新包。站点是新建的,日访问量不到二十,服务器负载和磁盘都正常。备份插件后台显示“下次执行:前一天凌晨四点”,日期一直往回滚,像是被什么东西卡住了。
WordPress没有系统级的定时器。wp-cron.php是一个普通PHP文件,只有在有页面访问时才可能被触发:每次有人打开站点,WordPress检查有没有到期任务,有就用一个异步请求去调它。没人打开页面,这个检查根本不会发生,队列里的任务就一直不跑。
新建站、内网测试站、刚上线还没推广的站,最容易撞上这一条。判断很快,看两处:插件列表里搜不到带系统定时字样的条目,服务器上crontab -l打出来是空的。两处都空,任务就一直挂在队列里,等下一次访问。
改法是把触发权交给系统。先在wp-config.php里加一行define('DISABLE_WP_CRON', true);,写在“That's all, stop editing!”那句注释之前,写在后面不生效。这一行只关掉由访问触发这一条路径,wp-cron.php本身仍然可以被访问,队列里的任务不会丢。
然后写系统任务。装了WP-CLI的机器用这条最省事:*/5 * * * * cd /www/wwwroot/example.com && /usr/bin/wp cron event run --due-now --quiet。没装WP-CLI就用curl或wget打一下wp-cron.php,带上doing_wp_cron参数,例如wget -q -O - 'https://example.com/wp-cron.php?doing_wp_cron=1',输出丢进/dev/null即可。两种写法都要用站点自己的用户跑,别用root,否则生成的文件属主变成root,后续上传和更新会报权限错误。
频率不要设成一分钟一次。每个周期启动一次PHP进程、加载整套WordPress,开销不小,五分钟一次对绝大多数任务够用。备份、推送、清理这类任务本身按小时或按天调度,跑得再勤也不会提前执行,只是白耗资源。WP-CLI那条命令里的cd不能省,cron执行时工作目录是用户的家目录,不切进去wp会找不到站点,报“Error: This does not seem to be a WordPress installation.”。
改成系统触发之后还有一处要跟着改。插件里原来设置了“错过时间就补跑”的,现在不会再补,因为系统cron跳过的那几次不会留下记录,队列里直接跳过。任务对时间敏感的,比如按日结算、按小时推送,把频率提到五分钟并加一把锁,写成*/5 * * * * flock -n /tmp/wp_cron.lock -c 'cd /www/wwwroot/example.com && /usr/bin/wp cron event run --due-now --quiet'。flock加-n的意思是拿不到锁立刻退出,两次执行重叠时后来那个直接放弃,不会两份备份同时往磁盘写。要是嫌wp-cron.php每次都要走一遍完整的WordPress启动,可以只让它在后台跑,前台请求那条路已经关掉了,不影响访问速度。
改完过一天再翻一次日志,连着出现十二天的空档会补上。你手上如果是日访问几百以上的站,wp-cron一直在正常工作,问题多半出在任务本身报错,那种去看插件的执行记录,换触发方式解决不了。
A5创业网 版权所有