This weekend at WordCamp Minneapolis I presented an introduction to the power of WP-CLI, a tool that allows you to manage your WordPress website from the command line. I’ve given this talk several times now, but am always looking for cool new features to include.
This weekend’s addition to my talk was the ability to run WP-CLI commands from my local machine against a remote site…. which is very cool, and saves even more time.
The Old Way
- SSH into Remote Server
- Change Directory to where my WordPress Site is installed
- Execute WP-CLI command.
The New Way
- Execute WP-CLI Command
Step 1: Setting It Up
- In order to run commands remotely, you need to install WP-CLI on both the computer you want to run the command from and the server on which your site is located.
- I would also recommend setting up passwordless-ssh on your server so that you don’t need to enter your password every time you run a WP-CLI command.
Step 2: Execute the Remote Command
The trick to running commands on a remote server is the –ssh option. Adding this option to any command will tell it to SSH into the remote server and execute the command there. For example, running
wp [email protected]/var/www/html/ plugin list
would be the same as connecting to example.com via SSH using the username shawn, changing directories to /var/www/html/ and then running the wp plugin list command.
Optional: Aliases
Adding that SSH flag to every command does seem a little tedious though. “There has to be a better way!” you demand. Well, there is: aliases. WP-CLI allows you to configure some global parameters in a file called wp-cli.yml. Aliases are one of these features – they allow you to setup friendly names that represent your remote environments. Here’s an example of the wp-cli.yml file I use.
wp-cli.yml (placed in the root of my site, in the same location as the wp-config.php file)
@test:
ssh: [email protected]/var/www/html/
@staging:
ssh: [email protected]/var/www/html/
@production:
ssh: [email protected]/var/www/html/
With this file in place, I can now execute commands using the alias. If I wanted to get the list of plugins on my staging server, I can now type:
wp @staging plugin list
Much nicer, right?!
Even More Power: Multiple Aliases at Once!
You can also configure groups of aliases in your wp-cli.yml file.
wp-cli.yml (placed in the root of my site, in the same location as the wp-config.php file)
@test:
ssh: [email protected]/var/www/html/
@staging:
ssh: [email protected]/var/www/html/
@production:
ssh: [email protected]/var/www/html/
@prerelease:
- @test
- @staging
In the above file, I’ve now stated that the alias @prerelease is a group that contains both of our previously defined @staging and @test aliases. So I can execute a command like this:
wp @prerelease core update
and update the version of the WordPress Core on both staging and test servers in one command.
There is also a built in @all alias. Executing:
wp @all core update
would execute this command on all defined aliases (in the example above: test, staging and production).
The Database Migration Example
The example of using this command that I demoed at WordCamp Minneapolis this weekend was the ability to update the database on my staging server with the data from my production server, using WP-CLI. Using the above configuration, and a little knowledge of piping commands together in bash, we can execute a command like this:
wp @production search-replace example.com staging.example.com --export | wp @staging db import -
(you might need to scroll to read the entire command)
In one line of code, this command:
- Connects to production (using an alias)
- Does a search and replace on my production domain name, replacing it with the staging domain name
- Exports those results to STDOUT (instead of to a file)
- Connects to staging (using an alias)
- Imports the production data using input from STDIN ( the hyphen after import ), using the data from the production export.
Cool, right?
Now, as I pointed out in the session, this command only moves the database, and not any of the media library, plugins, etc. In my particular use case, where my assets are stored in Amazon S3 buckets with Delicious Brains’ S3 Offload Plugin, this solution is all I needed.
Hey Shawn!
Great article. Very nice database transfer example. Just to be clear – STDOUT will be on the local computer where the command is originally executed, right? So production transfers the db to STDOUT locally and then uploads back to staging where it’s imported? So good for smaller websites but for larger databases it would be very bandwidth intensive?
Absolutely Phill. For a large database, I would run this command from the staging server (or whichever environment was the “destination”) in order to avoid the doubling of the bandwidth. This would mean setting up the wp-cli.yml file on either the source or destination server.
Doh. Of course! That makes much more sense than running the wp-cli command in a local dev environment and doubling the bandwidth 🙂
Thanks for this article. We are looking for a replacement for WordShell. We used to use a script WordShell that would let us use something like @all and then loop thru multiple (25+ in our case) WordPress accounts and update each up. Very powerful . I am not familiar with WP-Cli but now that WordShell is coming to its end of life could something like WP-Cli and @all be used to go thru each site, upload and active a plugin?
I’m not familiar with WordShell, so I can’t comment specifically on it. But you could definitely setup a script with WP-CLI that would connect to all your client sites and install/update a plugin! Take a look at the command: wp plugin install –activate . The can be a slug from a plugin in the WordPress.org repo, a zip file path on the site’s server, or a URL to a plugin zip file anywhere on the web.
Thank you for this tutorial. I’m new to WP-CLI and wonder what else is possible to do with it? Can you move WordPress files from your localhost WP installation to a live website using it, too?
Hi Andrej,
WP-CLI can do all sorts of things! I’ve spoken about this at WordCamps, you can find the slides I use in that presentation here: https://speakerdeck.com/shawnhooper/wp-cli-save-time-by-managing-wordpress-from-the-command-line. There’s also video of the presentation available here: https://wordpress.tv/2016/06/24/shawn-hooper-wp-cli-save-time-by-managing-wordpress-from-the-command-line-2/.
There may be an package you can add to WP-CLI that would assist in doing a full site move, but I’m not aware of one at this time. In order to move your site from local to live, you’re probably best to use a combination of WP-CLI (for the database) and the rsync or scp commands to move the files. Here’s an article that describes what that process could look like: How to Migrate a WordPress Site with WP-CLI and rsync.
Cheers.
Thanks for the article. I don’t think it’s necessary to define the @all alias, it’s available by default: https://developer.wordpress.org/cli/commands/cli/alias/#examples
Hey Gavin,
You’re right! I’ve updated the post to reflect this. Thanks.
Good article. Followed the steps, but the only annoying thing is that I keep getting the error “Cannot connect over SSH using provided configuration”. The first time I got this: “The authenticity of host … … Are you sure you want to continue connecting(yes/no)?” I opted for yes, of course. Then it was just the “Cannot”-error.
When I login manually I need to type in the passphrase. Where do I put this in the wp-cli.yml file? In the section Aliases there is only place for user, url, path, ssh, http.
I don’t believe you can place your password in the wp-cli.yaml file, which would be extremely insecure anyway. The best bet is to configure passwordless SSH from your computer to your server. Here’s a good article from DigitalOcean explaining how to set that up: https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys–2
I believe that’s the cause of the “Cannot connect” error you’re receiving.
Thanks Shawn I’ll check that article asap. The first time I started using ssh with this provider I created a passphrase so that’s probably the culprit.
wow cool, it’s really a new way for running wp cli!
remote export import db really great trick!
thanks Shawn
Couple things I’m wondering if are possible.
I would like to be able to define aliases on my local machine like @client1, @client2 that can be referenced regardless of where I’m running the wp command from on my machine. eg ~/Desktop
Is this possible and where would I place the wp-cli.yml file in order to do that?
Goal:
Desktop$ wp @client1 plugin list
Would also be nice if I could maybe do something like:
Desktop$ wp @client1, @client2, @client3 user list –role=administrator > clients/client-admins-list.txt
Hi Jay,
Not a problem at all. Just create a file called: ~/.wp-cli/config.yml
In this file, put:
@client1:
ssh: [email protected]/var/www/client1/
@client2:
ssh: [email protected]/var/www/client2/
etc. etc.
And the you’ll be able to issue wp @client1 commands without a problem from anywhere on your local machine, including folders that have their own local wp-cli.yml config files.
As for being able to run the same command against multiple sites. By default running:
wp @all user list --role=administrator >> client-admins.txt
works.
You can also create a group of clients in your .yml file, and then reference that group name. Unfortunately referencing a comma separated list of remote aliases as in your example doesn’t work.
I hope that helps.
Thanks for that.
I created “config.yml” in ~/.wp-cli
Then I created an alias
@client1:
ssh: [email protected]/srv/users/ftpsshusername/apps/websitename/public
From my machine I ran
wp @client1 plugin list
But I got:
Error: This does not seem to be a WordPress install.
Hi,
i got en error after executing the command wp @prod plugin list
shell: wp: command not found.
But on the remote server i can execute wp –info if i connect via terminal ans ssh.
Hi Alex,
I’m thinking the issue you’re running into might be the WP-CLI binary not being in the path when connecting over SSH. See this blog post from Daniel Bachhuber showing a solution: https://danielbachhuber.com/tip/wp-ssh-custom-path/
When I run a command against multiple aliases using the group alias @clients, I get the following error:
ssh is not recognized as an internal or external command, operable program or batch file.
The weird thing though is that when I run a command with just an regular alias, like wp @client_name core update, everything works fine. Besides, everything is just set up accordingly to the documentation in the config.yml file.
Do you know why I get this SSH error only when running a command against an alias group?
Hi Pieter,
Hmmm, off the top of my head, no. I haven’t seen that particular behavior yet. I’m guessing based on the error you received that you’re on a Windows machine (locally), right? What version of WP-CLI are you running?
The version is 2.4.0
Indeed, I’m on Windows (locally).
Please see https://github.com/wp-cli/wp-cli/issues/5334
for more information.
Glad to see you reported the issue. Unfortunately I don’t have a Windows machine up and running to provide you any additional help. The only thing I can think of is that there is no “ssh” command available on the Windows command line. But that wouldn’t explain why it works with a single @alias.