Automatic WordPress updates with wp-cli and cron

In this post, I provide instructions on setting up automatic WordPress security updates for multiple sites on UNIX-based servers.

Keeping WordPress up to date is critical for site security, but it can be time consuming if you manage many WordPress sites. There are modules such as Easy Updates Manager to automate the process, but they aren’t always reliable - for example, Easy Updates Manager doesn’t work on sites that also have Wordfence installed. Additionally, Easy Updates Manager needs to be installed and activated on every site.

However, thanks to the magic of wp-cli, it’s possible to update WordPress installations quickly and easily from the command line. Combining this with a cron job, you can set up automatic updates for all of the sites on a server fairly quickly.

First, you will need to install wp-cli. There are fairly comprehensive instructions at https://make.wordpress.org/cli/handbook/installing/. Pick the method most appropriate to your server environment. Bear in mind that if you have multiple sites running as different users, the wp-cli script needs to be accessible to all of them. For this reason, on Debian systems I prefer to use the .deb installation method as it makes the wp-cli executable available to all users at /usr/bin/wp.

Next, I recommend setting up a wrapper script. There are two reasons for this: first, the path to each WordPress install has to be passed to the wp-cli script; second, there are multiple update commands for WordPress core, plugins, themes and languages. This gets quite long-winded in cron format, so I use the wrapper script below. It only requires the path to each install to be passed in, and then it carries out all of the updates. This script is the public domain, so feel free to use it and adapt it to your needs.

#!/bin/sh
# Simple script to update a WordPress install (core, plugins, themes and languages) using wp-cli.
# Usually we expect to run this from cron.
# Written by Kitson Consulting and released into the public domain.

if [ $# -ne 1 ]
then
    echo "Usage: $0 </path/to/wordpress/install>" >&2
    exit 1
fi
if [ ! -d "$1" ]
then
    echo "$1 does not appear to be a directory. Exiting." >&2
    exit 2
fi
if [ ! -f "$1"/wp-config.php ]
then
    echo "$1/wp-config.php does not exist. Did you specify the path to a WordPress install?" >&2
    exit 3
fi
wp core update --path="$1" --quiet
wp plugin update --all --path="$1" --quiet
wp theme update --all --path="$1" --quiet
wp language core update --path="$1"  --quiet
wp language plugin update --all --path="$1" --quiet
wp language theme update --all --path="$1" --quiet

Once you have the wrapper script copied into a suitable location on the server (I recommend /usr/local/bin/wp-update), you are ready to set up the cron jobs. Each cron job uses the following simple command:

/usr/local/bin/wp-update /path/to/wordpress/site

Notes:

  • The cron job should run as the user that owns the website. On many Debian and Ubuntu systems this will be www-data.
  • Make sure that the script wp-update is executable and readable by the cron user.
  • Use the correct full path to the script (/usr/local/bin/wp-update in this example) and the website (frequently /var/www/html).
  • It’s also good practice to make sure that you receive emails from cron, to make sure that you get any notifications about errors. The script is designed to produce no output when it runs successfully, and therefore cron will only send email notifications when an error occurs.

If you have any questions about how to set this up on your own servers, or want to share information about how to use it on different environments, please post in the comments below!

Add new comment