18

From my understanding of how WordPress updates core and plugins is that every 12 hours it goes out and looks for updates. When does that time get set? 12 hours from initial installation? I ask this because using the plugin auto-update filter add_filter( 'auto_update_plugin' ); you could theoretically only allow plugins to update between certain times but if that certain time does not fall into that 12 hour window then plugins will never be updated.

Thus leaving the question in my title which is How would one go about altering how often WordPress looks for updates or how to specify a specific time when to auto-update?

For those interested, here's the filter I've been messing with, checks to see IF it's Monday - Friday 8am - 5pm:

function maybe_update_plugins(){
    date_default_timezone_set('Your Timezone Here');
    $localAssoc = localtime(time(), true);
    $update = false;

    /***
    /* tm_wday[0] = Sunday
    /* tm_wday[6] = Saturday
    ***/
    if(
      $localAssoc['tm_wday'] > 0 && $localAssoc['tm_wday'] < 6 &&
      $localAssoc['tm_hour'] > 7 && $localAssoc['tm_hour'] < 17
    ){
        $update = true;
    }

    return $update;
}
add_filter( 'auto_update_plugin', 'maybe_update_plugins' );

Edit As a neat sidenote, it does look like this filter is run each time a plugin updates, multiple plugin updates, multiple runs of the filter

3 Answers 3

13

You are correct, Wordpress checks for updates to core and plugins every 12 hours, but a better way to word it would be: it checks updates if last update was more than 12 hours ago.

The 12 hour setting is hard codded in wp-includes/update.php

The last updated dates are stored in wp_options table and the options are:

_site_transient_update_core
_site_transient_update_plugins
_site_transient_update_themes

Because this check does not happen precisely after 12 hours, but rather next time the condition is met (at least 12 hours has passed) then you will not miss the update.

1
  • Ok, so putting your answer and @Rarst together, every time a condition is met (sounds like every time a page or certain page is viewed) triggers a test to see when updates were checked last, if the check was >= 12 hours then run the auto update. So using the filter, there isn't really a window of opportunity.
    – Howdy_McGee
    Commented Aug 12, 2014 at 21:01
5

The relevant functions wp_update_plugins() and wp_maybe_auto_update() are hooked to the wp-cron events of same name, running on twice daily schedule.

Logically the initial schedule will start to tick from the time of first run. Due to wp-cron implementation (not being real cron and trigered by site visits rather than server clock) it will also "drift" whenever actual wp-cron fires past the time it's due at.

Plugin update checks are also triggered more often in certain admin areas, like plugin list (so that you are less likely to be looking at stale information).

On top of my head I don't quite see elegant way to put it into specific time corridor. Changing schedules are pretty easy, account for drift is not quite.

If this is in any way misison–critical requirement then it might better be handled with real server cron and external tool for actual update, such as wp-cli update functionality or managing plugins via Composer.

2
  • It is not mission critical but is wp-cron only triggered certain admin page views or also normal pageviews? Thanks!
    – Howdy_McGee
    Commented Aug 12, 2014 at 21:05
  • 1
    @Howdy_McGee wp-cron is triggered by pretty much anything (init hook firing)
    – Rarst
    Commented Aug 12, 2014 at 21:18
2

Currently (in 6.4.2), WordPress schedules the checks to occur every 12 hours from the first time a page load results in calling this function from wp-includes/update.php:

function wp_schedule_update_checks() {
        if ( ! wp_next_scheduled( 'wp_version_check' ) && ! wp_installing() ) {
                wp_schedule_event( time(), 'twicedaily', 'wp_version_check' );
        }

        if ( ! wp_next_scheduled( 'wp_update_plugins' ) && ! wp_installing() ) {
                wp_schedule_event( time(), 'twicedaily', 'wp_update_plugins' );
        }

        if ( ! wp_next_scheduled( 'wp_update_themes' ) && ! wp_installing() ) {
                wp_schedule_event( time(), 'twicedaily', 'wp_update_themes' );
        }
}

Subsequent occurrences get scheduled by wp-cron.php calling wp_reschedule_event, which adds another 12 hours (or several multiples of 12 hours if necessary) to the existing timestamp and then calls wp_schedule_event again.

Partially inspired by your question, I am using this filter to restrict the time range during which updates may occur:

// Only allow auto-updates during Mon-Thu mornings so we'll have time during business hours to fix any problems that arise.
// See also wp-admin/includes/class-wp-automatic-updater.php
function my_auto_update( $update, $item ) {
        $tz = new DateTimeZone('America/Chicago');
        $now = new DateTimeImmutable('now', $tz);

        if ($now < new DateTimeImmutable('07:50', $tz)) $update = false;
        if ($now > new DateTimeImmutable('12:00', $tz)) $update = false;
        // https://www.php.net/manual/en/datetime.format.php
        // 1 (for Monday) through 7 (for Sunday)
        if ($now->format('N') >= 5) $update = false;
        // otherwise, use the normal API response to decide whether to update or not

        return $update;
}

add_filter( 'auto_update_core',        'my_auto_update', 10, 2 );
add_filter( 'auto_update_plugin',      'my_auto_update', 10, 2 );
add_filter( 'auto_update_theme',       'my_auto_update', 10, 2 );
add_filter( 'auto_update_translation', 'my_auto_update', 10, 2 );

but have also added a second filter to adjust the scheduled times to my liking:

// Override default arbitrary twicedaily timing of wp_schedule_update_checks (in wp-includes/update.php) to choose a specific time that potentially satisfies the above filter, so we won't continually miss our window by sheer bad luck.
// Note that we still need a page load at an acceptable time to actually trigger the task; see also https://developer.wordpress.org/plugins/cron/
function my_schedule_autoupdate($event) {
        switch ($event->hook) {
                case 'wp_version_check':
                case 'wp_update_plugins':
                case 'wp_update_themes':
                        $desired_time = new DateTime('07:50', new DateTimeZone('America/Chicago'));
                        if ($desired_time->getTimestamp() < time()) $desired_time->modify('+1 day');
                        $event->timestamp = $desired_time->getTimestamp();
                        $event->schedule = "daily";
        }
        return $event;
}

add_filter( 'schedule_event', 'my_schedule_autoupdate' );

That still doesn't guarantee success, because WP-Cron is only triggered on page load; what if nobody browses the site during the acceptable update window? This final piece of the puzzle is solved by using system cron to run WP-Cron at a desirable time, in my case:

# min hr dom mon dow    command
55 7 * * 1-4    curl --no-progress-meter --insecure https://localhost/wp-cron.php

note: a side effect of my_auto_update is that the Plugins > Installed Plugins page shows "Auto-updates disabled" for every plugin, unless you visit it during the acceptable hours. I haven't spent any time trying to code around this; when I need to enable auto-update for new plugins, I can either remember to do it during the morning or I can temporarily disable the filter first. (Of course, I wouldn't need to manually enable auto-update for new plugins at all if my filter explicitly returned true during the acceptable time window, but that would also make it harder to exclude a particular plugin from auto-updating.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.