By Jeff Cleverley, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
This is the second part in our 3-part deep dive into the advanced WordPress management abilities provided by WP-CLI.
In the previous tutorial we looked at installing WP-CLI on your ECS instance, preparing the correct permissions and user roles for it to work properly, and using it to manage your WordPress content.
In this tutorial we are going to dive deeper into more advanced functionality. We will be managing your media, users and performing database operations. Configuring default parameters Globally and Locally, and showing you how it can be used to manage many sites on a server with each command.
In the final tutorial, I will show you how this functionality can be leveraged to manage hundreds of sites across all of your Instances from your local machine, demonstrate commands that can be used to speed up development of feature plugins and themes, before finally extending WP-CLI to provide custom functionality via custom commands. Through effective use of WP-CLI you will see how you can even reduce bloat of your WordPress sites through the removal of the need for several widely used plugins.
As ever, this tutorial assumes you already have an Alibaba Cloud ECS Instance provisioned and with one (or several) WordPress sites running on it.
Throughout the series, I will be using my superuser 'new_user' and will be issuing 'root' commands using the sudo command. When you follow the commands please remember to replace my user with your own.
I will also be using my test domains 'an-example-domain.com' and 'another-example-domain.com' in the code examples, remember to replace my site domains with your own when you issue the commands.
1. Manage Plugins & Themes with WP-CLI
WP-CLI contains a wealth of commands to manage the plugins and themes on your site. If you manage many sites, these can be provide a real boost to your productivity.
To manage plugins we use the 'wp plugin' command, to manage themes, the 'wp theme' commands.
WordPress Plugin Commands
As usual there is the 'list' subcommand:
$ wp plugin list
<View the plugins and their status in a table with the list command>
We can also use the 'status' subcommand to display our plugins and their status:
$ wp plugin status
If any plugins need updating we can do that too, using the 'slug' of the plugin as listed in the WordPress.org plugin repository:
$ wp plugin update akismet
When you have successfully listed and updated a plugin your terminal will look like this:
<Check the status of plugins and update them>
We can also activate plugins individually or by listing them:
$ wp plugin activate akismet nginx-helper
Or using the '--all' parameter:
$ wp plugin activate --all
Or deactivate and delete plugins:
$ wp plugin deactivate akismet && wp plugin delete akismet
We can easily search the WordPress.org repository for plugins, it is much faster than using a browser, but doesn't return as much information. It is much more useful if you know what you are looking for and just require the 'slug' for installation.:
$ wp plugin search nginx
Install them, and '--activate' them with one command:
$ wp plugin install regenerate-thumbnails --activate
Of course we can update plugins, but just like core, we can also revert plugins back to any previous version if we have problems.
This is one of those tasks that is so much easier with WP-CLI. Using the WordPress admin requires you to deactivate the plugin, then delete it, then search for the older version of the plugin in your browser, download it to your machine and then upload it to your site to install it.
Now we just:
$ wp plugin update regenerate-thumbnails --version=3.0.0
Update all plugins at once:
$ wp plugin update --all
WordPress Theme Commands
As with other commands, we can list our themes using the 'list' subcommand:
$ wp theme list
<View the Themes and their status in a table with the list command>
We can also use the 'status' subcommand to display our themes and their status:
$ wp theme status
If any theme needs updating, in my case Twentyseventeen does, we can do that too:
$ wp theme update twentyseventeen
As 'wp theme' has all the same subcommands as 'wp plugin', we can manage them in much the same way:
$ wp theme search <word to search by>
$ wp theme install <theme>
$ wp theme activate <theme>
$ wp theme deactivate <theme>
$ wp theme delete <theme>
$ wp theme update --all
2. Perform Database operations
As mentioned previously, WP-CLI allows us to perform operations on our WordPress database from the command line.
Exporting and importing your WordPress database, either for backups, or reverting to backup after a problem, or creating staging sites, or migrating a site, is incredibly easy now:
$ wp db export backup.sql
$ wp db import backup.sql
Optimizing or repairing your database your database:
$ wp db optimize
$ wp db repair
Often we use plugins to automate the tasks of backing or optimizing our database, but we can create a BASH script using these 'wp db' commands, and run it with a cron job to negate the need for another plugin. This is another example of WP-CLI reducing WordPress site bloat and optimizing workloads.
At the end of this tutorial we will create script as an example of WP-CLI task automation.
Search and Replace
In another tutorial we used WP-CLI to migrate a site to a staging and local development environment, this was made easy with one of WP-CLI's most powerful commands, 'search-replace':
Let's perform a search and replace on my test site:
$ wp search-replace “WP-CLI” “WP-CLI Awesome Sauce”
<Search and Replace in your WordPress database>
Now on my on my site, we can see “WP-CLI is Awesome Sauce” because…. well it is isn't it?
<WP-CLI Awesome Sauce>
Dumping a Database – Proceed with Caution!
There is also the 'dump' command to delete your entire database:
$ wp db dump
This is obviously a very risky command to have accessible at your fingertips, though it does require a confirmation. In any case, I recommend disabling this command by setting a parameter in your WP-CLI global configuration file. We will do that in a later section.
Database Queries
We can use the 'query' subcommand to query our database with any standard MySQL command.
Let's query our database for the list of all Post IDs:
$ wp db query “SELECT id FROM wp_posts;”
And we get a table showing all the Post IDs:
<Query your database with WP-CLI>
3. Manage your WordPress Media
I don't think I've every heard any WordPress developer profess their love for the WordPress media manager. In general, the administrative tasks involving images and media are considered the least efficient, and the Media Manager is generally regarded as poorly devised.
Import Images
WP-CLI can help with this, especially when it comes to importing of images.
Let's look in my example site's media manager:
<Example site's empty media manager>
And the post we created earlier:
<Post 7 with no featured image>
The 'wp media import' combination of commands is especially powerful. It has a range of parameters we can set.
First we need to give it a location to import from, this can either be on your server or it can pull images directly from a link. We can set title '--title=', caption '--caption=', alt text '--alt=', attach it to a post '--post_id=' and set it as the featured image '--featured_image':
$ media import https://a-website.com/some-image.png --title=“Image Title” --caption=“Image Caption” --alt=“Image alt text” --post_id=7 --featured_image
Your terminal will let you know if the import is successful:
Now we can see I have successfully managed to import a Kung Fu Cat image into my media library:
<Kung Fu Cat is in the media library>
The image has it's title, caption, and alt text set:
<Kung Fu Cat image details - Title, Alt, Caption all set>
And it has been attached to a post as the featured image with one command:
<Kung Fu Cat is Post 7 Featured image - WP Admin>
<Kung Fu Cat is Post 7 Featured image - Front End>
If you have been working in WordPress for long, you will understand how useful this is, but it get's better still…
Bulk Import Images
One of the biggest pains as a WordPress developer is when a client provides a huge set of images that they wish to be used in their site. Using the Media Manager in the WP Admin to do this can be, for want of a better word, torture.
You can't just upload them to a directory and then have WordPress scan the directory, they all need to be imported into a directory using the Media Manager interface otherwise your WordPress site will not have access to them. In principle, WP-CLI doesn't actually change this process, it just streamlines and improves its reliability.
So here I have my collection of Kung Fu Cat images on my desktop:
<Kung Fu Cats - the Collection>
After using an SFTP program to upload those images to a directory in my user's home directory on the server, we can see them when the directory contents are listed out:
Now all we need to do is use the 'import' command to import them from that directory:
$ wp media import ~/kung_fu_cats/*
And we have successfully imported an entire directory of images into the Media Manager without any of the slowness or potential failures of the browser based tool:
<Media Library full of Kung Fu Cats>
Regenerate Media
Another one of those tools that most developers use on their sites is some form of 'Regenerate Thumbnails' Plugins. Not usually a large plugin, but why bloat your website with any unnecessary plugins?
We can simply use:
$ wp media regenerate
We can improve this further…
4. Use WP Eval to combine WP-CLI with PHP
The real power of WP-CLI comes in when you combine commands together. An example of this is using the 'wp media regenerate' command in combination with the 'wp eval' command. WP eval allows us to run any PHP code within our WP-CLI commands, that means we can combine WP-CLI commands with WordPress and other PHP functions.
So, we can use the 'media regenerate' command in combination with some WordPress PHP that will only regenerate the featured images for published posts:
$ wp media regenerate $(wp eval 'foreach( get_posts( array( "post_status" => "publish" ) ) as $id ) { echo get_post_thumbnail_id( $id ) . " "; }' )
As we can see only one of our posts is published, and only the Featured image for this post is regenerated:
<List of published posts>
Combining WP-CLI commands together like this provides almost unlimited flexibility when managing your WordPress installations.
5. Manage WordPress Users & Roles
Manage WordPress Users
Using 'wp user' we can create, delete, update and manage our users and their information easily.
List your site users:
$ wp user list
As you can see, we only have one user. Let's create another user, and give him the roie of 'author':
<List your WordPress site users>
$ wp user create john john@an-example-domain.com --role=author --user_pass=johnsgreatpassword
Now if we list out the users again, we can see John has been added.
<Add a new user>
<Our new user John has been added>
Using WP-CLI is really quite a handy way to access your site easily if you ever get locked out. (Not that it has ever happened to me, nope, never)
6. Manage User Roles and Capabilities
Why don't we create a new Teacher role? That is also very easy, but first it's a good idea to check to make sure the Role doesn't already exist.
We can do that by either:
$ wp role list --fields=role
or
$ wp role exists teacher
As you can see, there is no role of 'teacher':
<No Teacher role exists>
So now we can create it, and give it the same capabilities as the editor role:
$ wp role create teacher “Teacher” --clone=“editor”
Afterwards, we can see our new role in the role list:
<Teacher role has been created>
And then it's easy to give our new user, John, the role of teacher:
$ wp user add-role john teacher
When we list out the users again, we can see 'teacher' has been added to John's roles:
<John is now a teacher>
7. The WP-CLI Configuration File
WP-CLI allows you to set configure default parameters either on a global level or on a per project directory level.
By default, the Global configuration file is looked for in a hidden directory within your user home directory '~/.wp-cli/config.yml'.
The location of it can be seen when you execute the 'wp --info' command on your instance:
$ wp --info
However, this file is not automatically created. From your home directory issue the following command:
$ touch ~/.wp-cli/config.yml
Now when you run the 'wp --info' command, the configuration file should have registered with WP-CLI and be listed. Confirm that now:
<Global configuration file is now listed>
Let's open this file for editing and add some default configuration parameters:
$ nano ~/.wp-cli/config.yml
In this file, you can set defaults for your WP-CLI Global parameters, defaults for Subcommands, create Aliases for connecting to other WordPress installations, and much more.
For now, enter the following into the configuration file:
# Global Parameter Defaults
disabled_commands:
- db drop
# Subcommand Defaults
config create:
dbuser: new_user
dbprefix: nu_
Firstly, in the '# Global Parameter Defaults', we disabled the ability to delete any WordPress sites database, this is especially important when WP-CLI makes database operations so easy.
Then, in the '# Subcommand Defaults', I have set my user as the default database user when creating 'wp-config.php' files using the WP-CLI 'wp config create' command, along with a default table prefix.
One of the other great things you can do with the config file, is create Aliases for connecting to remote servers more easily. We will be looking into that in the next section.
WP-CLI also allows you to set a configuration file in any working directory, but this should be named 'wp-cli.yml' or 'wp-cli.local.yml'.
For example:
/var/www/an-example-domain.com/htdocs/wp-cli.yml
Arguments in configuration files are interpreted in precedence from highest to lowest to in the following order:
1.Command Line arguments
2.wp-cli.local.yml file inside local directory
3.wp-cli.yml file inside local directory
4.~/.wp-cli.config.yml file
5.WP-CLI defaults
8. Using Aliases for convenience
At the moment, when we want to work on a WordPress site on our instance, we need to login to the server and change into the site's root directory to issue the WP-CLI commands. This process severely lessens any efficiencies gained from using WP-CLI.
We can use Aliases to solve this problem, making it possible to work on our sites from anywhere within the server.
Open your WP-CLI configuration file for editing again:
$ nano ~/.wp-cli/config.yml
At the bottom, below your # Subcommand Defaults', add the following lines:
# Aliases
@example:
path: /var/www/an-example-domain.com/htdocs/
@another:
path: /var/www/another-example-domain.com/htdocs/
And save and close the file.
Your 'config.yml' file should now look like this:
<WP-CLI configuration file with Aliases>
Now we can issue WP-CLI commands to each of our sites, using their Aliases, from anywhere on the server.
For example, change directory to your home directory and issue the following commands:
$ cd ~
$ wp @example plugin list
$ wp @another plugin list
And we will see the plugin lists for both of our sites:
<Use Aliases to easily issue WP-CLI commands from anywhere on your server>
9. Automate tasks with WP-CLI & Cron Jobs
When managing WordPress sites, there are often tasks which need to be schedule to run regularly. One such task, mentioned earlier, is the automated backup of your WordPress database on a schedule.
We can schedule our system to run WP-CLI commands using Cron jobs.
I will not be using the WP-CLI Cron commands, as that uses the WordPress 'WP-Cron', which is not a true Cron job, as it relies on feedback from the WP Admin to run and is therefore unreliable.
In most cases it is advisable to disable 'WP-Cron' and run 'wp-cron.php' as a Linux System Cron job, these are rock solid. Since that is advisable, why don't we do that now anyway:
On your sites, open your 'wp-config.php' file and add the following line:
define('DISABLE_WP_CRON', true)
Now open your system's crontab, for editing:
$ crontab -e
And add the following line within, using your own site domain:
0 1 * * * wget https://an-example-domain.com/wp-cron.php
The wget command is used for retrieving content from the web from the command line. Since it is non-interactive, it's perfect for command line use.
Your system cron job will now run the WordPress 'WP-Cron' tasks at 1am every morning.
In the same manner, let's use the system Cron to run our scheduled backups using WP-CLI commands. We manage system Cron jobs using the 'crontab'.
Reopen your system 'crontab' for editing:
$ crontab -e
You will need to add the full path to your WP-CLI, in our case we moved it to ' /usr/local/bin' at the very beginning of this tutorial, and then the path to the WordPress site you wish to enact the command upon.
If you haven't set up an Alias, you will need to use the WP-CLI Global '--path=' parameter:
0 0 * * * /usr/local/bin/wp --path=/var/www/an-example-domain.com/htdocs db export
If you have set up an alias just add:
0 0 * * * /usr/local/bin/wp @example db export
Now your site will schedule a daily backup at midnight - 0 0 *
Your 'crontab' should now look like similar to this:
<Schedule Jobs reliable with Linux Cron>
We have reached the end of Part 2 of this series. In the Final tutorial in the series we are going to use the commands and configurations we have already learned to allow us to manage hundreds of WordPress sites across any number of Alibaba instances, all with a few commands on our local machine. We will also learn how to use WP-CLI in our WordPress development and deployment workflow to speed development, before we finally extend it with Custom Commands.