经常使用 WordPress 进行开发的朋友可能都知道,WordPress 有一套自己的计划任务系统(WP-Cron),这套 Cron 系统和 Linux 的 Cron系统有很大的区别。
- Linux Cron:只要到达指定时间且系统运行中,任务就会自动执行。
- WP-Cron:需要依赖网站访问才能触发,具体流程是:
- WordPress 将计划任务信息存储在数据库中
- 当用户访问网站时,系统检查是否有待执行的任务
- 如果存在需要执行的任务,则立即执行
WordPress 定时任务计划系统的问题
WP Cron 的这种设计带来了两个主要问题:
- 执行时间不准确:任务不一定在设定的确切时间执行
- 可能错过执行:如果在计划时间内没有用户访问网站,任务就不会被触发
这种机制对于访问量大的网站影响较小,但对于需要准时执行的关键任务来说并不适用。
一个真实的定时任务例子
假设我们需要实现这样一个功能:每小时检查特定目录下的 CSV 文件,如果文件存在则导入到数据库并删除文件。使用普通的 WP-Cron 可能会导致任务无法按时执行。
优化方案:结合系统 Cron 触发 WP Cron
我们知道,操作系统的计划任务,只要设置好了,到了时间就会自动执行,没有其他的附加条件。所以要解决这个问题,我们需要设置一个操作系统级别的任务计划,模拟用户定时访问站点。
为了避免操作系统的任务计划和 WordPress 的任务计划起冲突,造成重复执行的问题,我们先禁用 WordPress 的任务计划系统,然后使用 wp_schedule_event
安排我们的任务计划操作。
1. 禁用 WP Cron 定时任务系统
在 wp-config.php 中, 添加下面的定义代码:
define('DISABLE_WP_CRON', true);
2. 添加事项操作
首先,定义一个每小时指定的动作,指定一个需要执行的函数名称,在下面的例子中,就是 update_db_hourly。
add_action( 'my_hourly_event', 'update_db_hourly' );
3. 添加定时任务函数
现在,定义 update_db_hourly 函数使用 WordPress 调度事项。如果是在插件中,我们可以在插件激活时,调度任务, (同时,不要忘了在插件禁用时移除调度):
public static function activate() {
wp_schedule_event( time(), 'hourly', 'my_hourly_event' );
}
public static function deactivate() {
wp_clear_scheduled_hook('my_hourly_event');
}
最后,定义执行实际的操作函数,也就是第一步指定的 update_db_hourly。
public function update_db_hourly() {
// 1. 检查是否有文件
// 2. 如果有、导入,然后删除
// 3. 如果没有,不执行任何操作
}
4. 设置计划任务
基于 cPanel 或其他面板的主机一般都有自定义计划任务的界面,我们可以通过 Web 界面非常方便的设置计划任务,有些服务器没有在图形界面,只能通过访问命令行,通过命令来设置计划任务。Linux 系统可以通过 crontab -e
来编辑计划任务,加入以下指令到计划任务文件、然后保存即可。
*/15 * * * * wget -q -O - http://yourdomain.com/wp-cron.php?doing_wp_cron
或者使用 curl 也可以达到同样的目的。
*/15 * * * * curl --silent "https://yourdomain.com/wp-cron.php?doing_wp_cron" > /dev/null 2>&1
上面的设置将每 15 分钟执行一次,向 WordPress 站点发出请求,从而启动我们设置好的计划任务。
设置计划任务并不是一个非常复杂的过程,但是除非您熟悉 WordPress 定时任务系统的工作原理,使用的时候就会遇到我们上面提到的问题。希望本文能够帮助你了解 WordPress 是如何处理计划任务的,并在需要的时候正确设置 WordPress 的任务计划。
除了常见的定时操作,我们还可以在 WordPress 计划任务系统的基础上实现异步 PHP 和定时任务队列,有需要的朋友可以点击链接了解详情。