WordPress and the “A scheduled event has failed” error

Wordpress blad wp cron

Every WordPress site administrator knows that feeling. You log into the dashboard, and there’s a message waiting for you: “A scheduled event has failed”. Your heart stops for a moment. Is the site down? Is it a serious crash?

Calm down! Before you start to panic, take a deep breath. This error, although it sounds serious, rarely means disaster. Most often, it’s simply a signal that the internal task scheduling mechanism in WordPress isn’t working optimally.

In this article, we’ll explain what this error is, why it appears, and how to fix it professionally in various server configurations.

What is WP-Cron?

WordPress needs to perform cyclical background tasks: publishing scheduled posts, creating backups, or scanning the site for viruses (as in the case of the wf_scan_monitor error from the Wordfence plugin). To handle these operations, it uses a built-in mechanism called WP-Cron.

The problem is that WP-Cron is not a real cron daemon known from Unix systems. It’s a “pseudo-cron” that has a fundamental flaw: it only runs when someone visits your website.

  • On sites with low traffic: If no one visits the site, tasks aren’t performed on time, which leads to errors.
  • On sites with high traffic: WP-Cron is called on every page load, which generates unnecessary server load.

In both cases, the solution is the same: disable the built-in WP-Cron and replace it with a stable, system-level cron job.

Scenario 1: A Single WordPress Site

This is the most basic and common configuration. The solution is simple and comes down to two steps.

Step 1: Disable the built-in WP-Cron mechanism

Edit the wp-config.php file in your site’s main directory and add the following line:

define(‘DISABLE_WP_CRON’, true);

Step 2: Configure a system cron

Log into your server via SSH and type crontab -e to edit the list of system tasks. Then, add one of the following lines, which will properly call the WordPress cron mechanism every 5 minutes.

  • wget method: */5 * * * * wget -q -O – https://yourdomain.co.uk/wp-cron.php?doing_wp_cron >/dev/null 2>&1
  • curl method: */5 * * * * curl https://yourdomain.co.uk/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Remember to replace yourdomain.co.uk with your actual address. From now on, tasks will be executed regularly, regardless of site traffic.

Scenario 2: Multiple Sites on a Standard Server

If you manage multiple sites, adding a separate line in crontab for each one is impractical and difficult to maintain. A better solution is to create a single script that will automatically find all WordPress installations and run their tasks.

Step 1: Create the script file

Create a file, e.g., /usr/local/bin/run_all_wp_crons.sh, and paste the following content into it. The script searches the /var/www/ directory for wp-config.php files.

#!/bin/bash
#
# Script to run cron jobs for all WordPress sites
# Optimised for ISPConfig directory structure
# The main directory where the ACTUAL site files are located in ISPConfig
SITES_ROOT=”/var/www/clients/”

# Path to the PHP interpreter (may need to be adjusted)
PHP_EXECUTABLE=”/usr/bin/php”

# Logging (optional, but useful for debugging)
LOG_FILE=”/var/log/wp_cron_runner.log”

echo “Starting cron jobs (ISPConfig): $(date)” >> $LOG_FILE

# Find all wp-config.php files and run wp-cron.php for them
find “$SITES_ROOT” -name “wp-config.php” -print | while IFS= read -r -d ” config_file; do

    # Extract the directory where WordPress is located
    WP_DIR=$(dirname “$config_file”)

    # Extract the user name (e.g., web4) from the path
    # It’s the sixth element in the path /var/www/clients/client4/web4/web/
    WP_USER=$(echo “$WP_DIR” | awk -F’/’ ‘{print $6}’)

    if [ -z “$WP_USER” ]; then
        echo “-> WARNING: Failed to determine user for: $WP_DIR” >> $LOG_FILE
        continue
    fi

    # Check if the wp-cron.php file exists in this directory
    if [ -f “$WP_DIR/wp-cron.php” ]; then
        echo “-> Running cron for: $WP_DIR as user: $WP_USER” >> $LOG_FILE
        # Run wp-cron.php using PHP CLI, switching to the correct user
        su -s /bin/sh “$WP_USER” -c “(cd ‘$WP_DIR’ && ‘$PHP_EXECUTABLE’ wp-cron.php)”
    else
        echo “-> WARNING: Found wp-config, but no wp-cron.php in: $WP_DIR” >> $LOG_FILE
    fi
done

echo “Finished: $(date)” >> $LOG_FILE
echo “—” >> $LOG_FILE

Step 2: Grant the script execution permissions

chmod +x /usr/local/bin/run_all_wp_crons.sh

Step 3: Create a single cron job to manage everything

Now your crontab can contain just one line:

*/5 * * * * /usr/local/bin/run_all_wp_crons.sh >/dev/null 2>&1

Scenario 3: Multiple Sites with ISPConfig Panel

The ISPConfig panel uses a specific directory structure with symlinks, e.g., /var/www/yourdomain.co.uk points to /var/www/clients/client1/web1/. Using the script above could cause tasks to be executed twice.

To avoid this, you need to modify the script to search only the target clients directory.

Step 1: Create a script optimised for ISPConfig

Create the file /usr/local/bin/run_ispconfig_crons.sh. Note the change in the SITES_ROOT variable.

#!/bin/bash
# Script to run cron jobs for all WordPress sites
# Optimised for ISPConfig directory structure
# We only search the directory with the actual site files
SITES_ROOT=”/var/www/clients/”

# Path to the PHP interpreter
PHP_EXECUTABLE=”/usr/bin/php”

# Optional log file to track progress
LOG_FILE=”/var/log/wp_cron_runner.log”

echo “Starting cron jobs (ISPConfig): $(date)” >> $LOG_FILE

find “$SITES_ROOT” -name “wp-config.php” -print0 | while IFS= read -r -d $’\0′ config_file; do
    WP_DIR=$(dirname “$config_file”)
    if [ -f “$WP_DIR/wp-cron.php” ]; then
        echo “-> Running cron for: $WP_DIR” >> $LOG_FILE
        (cd “$WP_DIR” && “$PHP_EXECUTABLE” wp-cron.php)
    fi
done

echo “Finished: $(date)” >> $LOG_FILE
echo “—” >> $LOG_FILE

Steps 2 and 3 are analogous to Scenario 2: give the script execution permissions (chmod +x) and add a single line to crontab -e, pointing to the new script file.

Summary

The “A scheduled event has failed” error is not a reason to panic, but rather an invitation to improve your infrastructure. It’s a chance to move from the unreliable, built-in WordPress mechanism to a solid, professional system solution that guarantees stability and performance.

Regardless of your server configuration, you now have the tools to sleep soundly, knowing that your scheduled tasks are running like clockwork.

Komentarze

Leave a Reply

Your email address will not be published. Required fields are marked *