随着时间的流逝,WP Cron无法执行


16

目标

我想用来wp_schedule_single_event( )执行一个事件,该事件在用户提交表单8分钟后向我发送了一封电子邮件。

问题

以下代码在my中functions.php

function nkapi_send_to_system( $args ) {
  wp_mail( 'xxx', 'xxx', $args );
}

add_action( 'nkapi_send', 'nkapi_send_to_system' );

function schedule_event( $id ) {
  wp_schedule_single_event( current_time( 'timestamp' ) + 480, 'nkapi_send', array( $id ) );
}

下面的代码用于调用schedule-event

schedule_event( $_SESSION['insert_id'] ); // the $_SESSION var contains an INT

等待了8分钟以上后,我的收件箱中没有电子邮件。

我尝试了什么

使用插件Core Control,可以看到计划的Cron作业。

核心控制屏幕

经过几次更改后,我设法使它们非常正确,并且更好,当我单击“立即运行”时,实际上在收件箱中收到一封电子邮件。

但是为什么八分钟后我访问我的网站时cron无法执行。此代码可能有什么问题?我不得不说这是我第一次使用WP Cron。

我尝试了更多

在对vancoder id 进行评论后,决定测试以下代码是否可以正常工作,如果我将以下代码直接放在functions.php

function schedule_event( $id ) {
  wp_schedule_single_event( time(), 'nkapi_send', array( $id ) );
}

if ( isset( $_SESSION['insert_id'] ) ) {
  if ( ! array_key_exists( 'insert_scheduled', $_SESSION ) || $_SESSION['insert_scheduled'] != $_SESSION['insert_id'] ) {
    schedule_event( $_SESSION['insert_id'] );
    $_SESSION['insert_scheduled'] = $_SESSION['insert_id'];
  }
}

该代码的缺点是,用户必须在执行此代码之前转到另一页。但另一方面,这也不起作用,所以这不是我的第一个问题...


1
在哪里以及如何被schedule_event( $_SESSION['insert_id'] );解雇?
Vancoder 2013年

简码在页面中包含一个单独的文件(其中包含表单),当该表单发布时,页面将重新加载,然后,该文件将执行schedule_event( ),让我们在由简码加载的包含文件的顶部说。
Mike Madern

任何 crons工作?wp_version_check等?
vancoder 2013年

我没有得到任何 crons工作。这可能是什么问题?
Mike Madern 2013年

要确认-甚至核心cron作业也会失败?
vancoder

Answers:


8

首先,您可以确认没有启用任何缓存插件吗?缓存插件可能会干扰cron作业,因为访问者无法获得的是实时页面,而是页面的缓存版本。

如果启用了缓存插件,则可以选择一个页面,并在该页面的缓存插件设置中添加专有内容,这样就永远不会对其进行缓存。

然后,您将必须手动创建一个cron作业(如果您是在共享托管环境中,则使用cpanel;如果是VPS /专用服务器,则是从终端使用),每隔几分钟就会访问该页面。

希望对您有所帮助!


我启用了缓存插件!W3的总缓存非常准确
Mike Madern

14

首先,定义您的自定义cron作业计划。

add_filter('cron_schedules', array($this, 'cron_schedules'));

public function cron_schedules($schedules){
    $prefix = 'cron_';// Avoid conflict with other crons. Example Reference: cron_30_mins
    $schedule_options = array(
        '30_mins' => array(
            'display' => '30 Minutes',
            'interval' => '1800'
        ),
        '1_hours' => array(
            'display' => 'Hour',
            'interval' => '3600'
        ),
        '2_hours' => array(
            'display' => '2 Hours',
            'interval' => '7200'
        )
    );
    /* Add each custom schedule into the cron job system. */
    foreach($schedule_options as $schedule_key => $schedule){
        $schedules[$prefix.$schedule_key] = array(
            'interval' => $schedule['interval'],
            'display' => __('Every '.$schedule['display'])
        );
     }
     return $schedules;
}

您需要确定实际在何时何地安排活动。

这只是一个示例代码片段,它调用自定义类方法:

$schedule = $this->schedule_task(array(
    'timestamp' => current_time('timestamp'), // Determine when to schedule the task.
    'recurrence' => 'cron_30_mins',// Pick one of the schedules set earlier.
    'hook' => 'custom_imap_import'// Set the name of your cron task.
));

这是实际安排事件的代码:

private function schedule_task($task){
    /* Must have task information. */
    if(!$task){
        return false;
    }
    /* Set list of required task keys. */
    $required_keys = array(
        'timestamp',
        'recurrence',
        'hook'
    );
    /* Verify the necessary task information exists. */
    $missing_keys = array();
    foreach($required_keys as $key){
        if(!array_key_exists($key, $task)){
            $missing_keys[] = $key;
        }
    }
    /* Check for missing keys. */
    if(!empty($missing_keys)){
        return false;
    }
    /* Task must not already be scheduled. */
    if(wp_next_scheduled($task['hook'])){
        wp_clear_scheduled_hook($task['hook']);
    }
    /* Schedule the task to run. */
    wp_schedule_event($task['timestamp'], $task['recurrence'], $task['hook']);
    return true;
}

现在,您需要做的就是调用自定义cron任务的名称。在此示例中,cron任务名称为custom_imap_import

add_action('custom_imap_import', array($this, 'do_imap_import'));

public function do_imap_import(){
    // .... Do stuff when cron is fired ....
}

因此,在此示例中,$this->do_imap_import();每30分钟调用一次(假设您有足够的网站访问量)。


笔记

需要进行页面访问,以便您的cron在正确的时间触发。

示例:如果您以30分钟为间隔安排任务,但是4个小时内没有人访问您的网站,则只有在4小时后该访问者到达您的站点,您的cron作业才会被解雇。如果您确实需要每30分钟执行一次任务,那么建议您通过网络托管提供商设置一个合法的cron作业,以所需的时间间隔访问您的网站。

WordPress cron工作不会使您的网站变慢!

也许您在想,如果cron脚本要花很长时间才能执行,访问者将不得不等待脚本执行完毕。不!那怎么可能呢?如果您查看wp-cron.php文件,将会发现一行

ignore_user_abort(true);

它是 php.ini配置可设置为,如果您停止加载站点/脚本,则脚本不会停止执行。

如果您查看该wp-includes/cron.php文件,则会发现如下一行:

wp_remote_post( $cron_url, 
array('timeout' => 0.01,
 'blocking' => false, 
 'sslverify' => apply_filters('https_local_ssl_verify', true)) );

这意味着WordPress会等待只有0.01秒触发执行那么它将中止,但是因为你已经设置ignore_user_aborttrue该脚本就会被执行。此功能是在WordPress cron作业中执行大型脚本的巨大优势。

可用的辅助功能:


6
这是一个非常全面的响应,据我所知,它无法解决实际问题-这就是为什么所有计划任务(包括核心任务)都失败的原因。
vancoder

此答案是为了引导用户朝正确的方向正确理解和安排WordPress cron任务。
Michael Ecklund

4
这肯定帮助我使用WordPress了解了cron计划
Mike Madern 2013年

2
迈克尔,您应该更经常回答。伟大的+1
kaiser

1
我认为WP_Cron与WP的其余部分一样,在后台使用GMT,因此最好将第一个事件安排在time()而不是current_time()
伊恩·邓恩

3

WordPress Cron允许您安排任务,但是只有在对该站点有请求时,它们才会执行。对于WordPress收到的每个请求,它将检查是否有要处理的cron作业,如果是,则触发一个/wp-cron.php?doing_wp_cron异步处理该作业的请求。如果作业的计划开始没有请求就通过,那么cron进程将不会启动。

由于您能够查看和运行计划的作业,因此可能没有触发cron作业启动的请求,尤其是在使用缓存插件的情况下。将其卸载到更常规的时间表的最佳选择是禁用WordPress中的默认检查并使用crontab

首先禁用默认检查(这可以帮助提高客户端性能),将以下内容添加到wp-config.php

// Disable default check for WordPress cron jobs on page loads
define( 'DISABLE_WP_CRON', true );

接下来,您创建一个任务,wp-cron.php每分钟获取一次页面以处理后端上的所有作业,从命令行输入crontab -e,然后添加如下所示的行:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 

2
如果不给doing_wp_cron一个值,则很有可能导致作业有时执行两次。使用doing_wp_cron=$(date +\%s.\%N)防止。
亚历山大花园

0

检查是否未在配置中设置DISABLE_WP_CRON。

失败的话,请尝试禁用所有插件(核心控件除外-尽管我会使用wp-crontrol),然后查看您的核心作业是否正常运行。如果这样做,则说明您在某处遇到插件干扰。

同样,尝试切换到标准的20多岁主题。

如果这些都不起作用,那么很有可能是托管问题。


我没有DISABLE_WP_CRON参与wp-config.php,我将尝试更多尝试,稍后再回来
Mike Madern 2013年

0

检查任何隐藏Wordpress的插件。

怎么看这是问题所在?

  1. 导航到http(s)://yoursite.com/wp-cron.php您应该看到一个空白页。一个完全空的。
  2. 除此之外,您还必须在cron作业管理器中看到“下一次执行”下的时间:( 已安排Cron作业-如果wp-cron.php正常工作 不仅对于某些条目来说,“文本在队列中”-以及给定的时间-有时“在队列中”是可以的,但是如果唯一的话您看到->您的cron无法正常工作。)

+1。不要相信任何“检查cron是否正常工作”的插件-例如WP Cron status checker插件显示cron是否正常工作。但实际上没有。 无论显示什么,请相信您的眼睛,而不是这个插件!

结论:如果是404错误-请关闭a)不仅像其他人建议的那样缓存插件b)还要隐藏所有隐藏Wordpress的插件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.