Originally published at: https://roots.io/leveraging-wp-cli-aliases-in-your-wordpress-development-workflow/
Not to be confused with the hit TV series starring Jennifer Garner, alias support was added to WP-CLI from an update in July, 2016. If you aren’t familiar, WP-CLI is a tool for interacting with WordPress via the command line. It allows you to perform many admin actions such as activating plugins or users and…
If you’re looking for an example script that does the opposite of what’s in the post, going from development to production (useful during initial solo-dev), here’s sync-dev-to-prod-FOR-REAL.sh
:
read -r -p "Would you really like to reset THE PRODUCTION DATABASE and send up the latest from dev? [y/N] " response
if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]
then
wp @development db export - > sql-dump-development.sql
scp sql-dump-development.sql web@example.com:/srv/www/example.com/current
wp @production db export just-in-case.sql
wp @production db reset --yes
wp @production db import sql-dump-development.sql
wp @production search-replace https://example.dev http://example.com
scp -r web/app/uploads/ web@example.com:/srv/www/example.com/shared
else
exit 0
fi
This looks really cool, but I just started using wp-cli and I don’t quite get it. As I understand it, you’d normally need to ssh into a server and go into the web woot where WordPress resides and run “wp” commands there. I was able to ssh into vagrant and run “wp --info” and “which wp”. If I try to run “wp” commands from my command line I get “wp not found”.
So how is this supposed to work?
- Normally “wp” needs to be run on the server from within the folder where WordPress lives? Requires ssh-ing into a server?
- However, now with aliases you can run “wp” commands without ssh-ing into other servers?
- Am I supposed to be able to run “wp” commands from my computer’s command line?
wp-cli tips for newbies (also some questions, someone knowledgeable please verify this is correct)
-
You may need to install wp-cli on your system, it’s not listed as a requirement, so I didn’t have it installed. (follow the instructions at http://wp-cli.org/).
-
Trellis does install wp-cli on vagrant and other servers.
-
Even if you haven’t installed wp-cli on your system, you can run “wp” commands when you ssh into vagrant or other environments.
-
The aliases look like this. Add them to an existing file (wp-cli.yml) in the “site” folder. (aliases were appended after “path: web/wp” which was alrealy in the file)
path: web/wp
@development:
ssh: vagrant@example.dev/srv/www/example.com/current
@staging:
ssh: admin@staging.example.com/srv/www/example.com/current
@production:
ssh: admin@example.com/srv/www/example.com/current -
The whole point of aliases is so that you can run “wp” commpands on your system that will run on vagrant or remote servers without having to ssh in.
-
You need to run your aliases from the same folder that has the wp-cli.yml file (sites) or it won’t find your alias. (If you’re running other “wp” commands that don’t require an alias, you should be able to run “wp” commands globally if you installed it globally.)
-
The example in the tutorial (
wp @production plugin activate soil
) (https://roots.io/leveraging-wp-cli-aliases-in-your-wordpress-development-workflow/) may not work if you don’t have soil installed. You can try a different plugin. Here I’m installing wp-migrate-db with composer and then activating it with wp-cli. (very very cool!)
composer require wpackagist-plugin/wp-migrate-db
wp @development plugin activate wp-migrate-db
Ben Word’s database syncing shell script above works great! And it copies over the media also!! Awesome!
My questions:
- I have a permissions problem. Any idea how to fix this?
mysqldump: Can't create/write to file 'just-in-case.sql' (Errcode: 13 "Permission denied")
- what’s the best practice for where to store this script in “trellis/bin”?
- it leaves a copy of sql-dump-development.sql (in “sites”). Guessing that would be easy to change in the script unless it’s good to keep.
- you say this is good for “initial solo dev”. What do you see as the limitations of this as compared to the wp-migrate-db plugin?
Thanks for trying out aliases!
This should probably be moved to a support thread rather than discussion of the post.
You can include your questions there, and additionally please include information about where you are running the script to provide more context.
Consider separating out #4 as another thread as it’s own can of worms.
Nice post Raquelle! Aliases are awesome.
I found you can remove the need for the sql-dump-development.sql
file and run it in one go like this from the environment you want to run the import on:
wp @remote db export - | wp db import -
This won’t be as practical for large databases where you might need to compress it to get a reasonable transfer time, but it makes for a nice one-liner
Hold on … you’re telling me we can duplicate WP Migrate DB Pro with just a shell script?
Just getting round to trying this now and I can certainly see a lot of value in this.
On a Trellis + Bedrock set up, I can get staging and prod aliases working fine but I’m having trouble with development.
@development:
ssh: vagrant@example.dev/srv/www/example.com/current
Fairly new to Trellis but this gives me:
Error: Cannot connect over SSH using provided configuration.
And if I manually try:
vagrant@example.dev
I get:
Permission denied (publickey).
Maybe I’m totally missing something or maybe the Trellis setup has changed since this post?
Edit
OK, got it figured out. I wasn’t sure as the post referenced Trellis and Vagrant separately, so I tried the Vagrant part of the post, running the following in the Trellis directory:
$ vagrant ssh-config --host example.dev >> ~/.ssh/config
This then let the SSH connection work. Probably my bad for not realising this needed to be done first.
I made a script to auto-update my local SSH config on vagrant up
to make sure that the port always works. I noticed that after rebooting or having different Vagrant boxes running that my SSH attempts would fail.
Add the following to your Vagrantfile
within the VM provisioner (config.vm.provision provisioner do |ansible|
)
# Run script to update local SSH config for .dev hostname after `vagrant up`
if Vagrant.has_plugin?('vagrant-triggers')
config.trigger.after :up do
run "./bin/ssh-config-development.sh"
end
else
fail_with_message "vagrant-triggers missing, please install the plugin with this command:\nvagrant plugin install vagrant-triggers"
end
Then create bin/ssh-config-development.sh
with the following:
host="example.dev"
sed "/^$/d;s/Host /$NL&/" ~/.ssh/config | sed '/^Host '"$host"'$/,/^$/d;' > config &&
cat config > ~/.ssh/config &&
rm config &&
vagrant ssh-config --host example.dev >> ~/.ssh/config
Also, here’s the latest version of the sync script I’ve been using that lives at site/scripts/sync.sh
#!/bin/sh
DEVDIR="web/app/uploads/"
DEVSITE="https://example.dev"
PRODDIR="web@example.com:/srv/www/example.com/shared/uploads/"
PRODSITE="https://example.com"
STAGDIR="web@staging.example.com:/srv/www/example.com/shared/uploads/"
STAGSITE="https://staging.example.com"
FROM=$1
TO=$2
case "$1-$2" in
development-production) DIR="up"; FROMSITE=$DEVSITE; FROMDIR=$DEVDIR; TOSITE=$PRODSITE; TODIR=$PRODDIR; ;;
development-staging) DIR="up" FROMSITE=$DEVSITE; FROMDIR=$DEVDIR; TOSITE=$STAGSITE; TODIR=$STAGDIR; ;;
production-development) DIR="down" FROMSITE=$PRODSITE; FROMDIR=$PRODDIR; TOSITE=$DEVSITE; TODIR=$DEVDIR; ;;
staging-development) DIR="down" FROMSITE=$STAGSITE; FROMDIR=$STAGDIR; TOSITE=$DEVSITE; TODIR=$DEVDIR; ;;
*) echo "usage: $0 development production | development staging | production development | production staging" && exit 1 ;;
esac
read -r -p "Would you really like to reset the $TO database and sync $DIR from $FROM? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cd ../ &&
wp "@$TO" db export &&
wp "@$FROM" db export - | wp "@$TO" db import - &&
wp "@$TO" search-replace "$FROMSITE" "$TOSITE" &&
rsync -az --progress "$FROMDIR" "$TODIR"
fi
Usage:
$ ./sync.sh
usage: ./sync.sh development production | development staging | production development | production staging
eg.
$ ./sync.sh development production
$ ./sync.sh production development
@ben that looks great. I had already tweaked around with your last script but that’s a whole let better than what I had put together. Just gave this a test run and worked perfectly.
Question: I had added to mine the removal of the resulting .sql files. It looks like in this script we get left with a single .sql file on the remote server. Should this be removed after import?
I left it as a way of leaving a backup incase you didn’t mean to push up a new DB, but have considered moving that to a more temporary area. Feel free to remove/tweak
Makes sense, appreciate the reply
WP-CLI supports a global config file! Per the docs you can have a global config in ~/.wp-cli/config.yml
- I just set it up with aliases, and now I can use my aliases from any folder
I just noticed the last case doesn’t match up with the last usage example - I added in production <> staging
and updated the usage text. I also made the site URLs root relative, just for compatibility reasons.
The first case also has ;
after DIR="up"
whereas the others don’t; I added to make consistent though I’m not sure it actually matters since each statement is just a variable declaration.
#!/bin/sh
DEVDIR="web/app/uploads/"
DEVSITE="//example.dev"
PRODDIR="web@example.com:/srv/www/example.com/shared/uploads/"
PRODSITE="//example.com"
STAGDIR="web@staging.example.com:/srv/www/example.com/shared/uploads/"
STAGSITE="//staging.example.com"
FROM=$1
TO=$2
case "$1-$2" in
development-production) DIR="up"; FROMSITE=$DEVSITE; FROMDIR=$DEVDIR; TOSITE=$PRODSITE; TODIR=$PRODDIR; ;;
development-staging) DIR="up"; FROMSITE=$DEVSITE; FROMDIR=$DEVDIR; TOSITE=$STAGSITE; TODIR=$STAGDIR; ;;
production-development) DIR="down"; FROMSITE=$PRODSITE; FROMDIR=$PRODDIR; TOSITE=$DEVSITE; TODIR=$DEVDIR; ;;
production-staging) DIR="horizontally"; FROMSITE=$PRODSITE; FROMDIR=$PRODDIR; TOSITE=$STAGSITE; TODIR=$STAGDIR; ;;
staging-development) DIR="down"; FROMSITE=$STAGSITE; FROMDIR=$STAGDIR; TOSITE=$DEVSITE; TODIR=$DEVDIR; ;;
*) echo "usage: $0 development production | development staging | production development | production staging | staging development" && exit 1 ;;
esac
read -r -p "Would you really like to reset the $TO database and sync $DIR from $FROM? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cd ../ &&
wp "@$TO" db export &&
wp "@$FROM" db export - | wp "@$TO" db import - &&
wp "@$TO" search-replace "$FROMSITE" "$TOSITE" &&
rsync -az --progress "$FROMDIR" "$TODIR"
fi
Edit: though I’m still using WP Migrate DB, I figured I’d add in the option to skip syncing uploads, so after the case block I changed to the following:
read -r -p "Would you like to sync the uploads folder as well? [y/N] " uploads
read -r -p "Would you really like to reset the $TO database and sync $DIR from $FROM? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cd ../ &&
wp "@$TO" db export &&
wp "@$FROM" db export - | wp "@$TO" db import - &&
if [[ "$uploads" =~ ^([yY][eE][sS]|[yY])$ ]]; then
wp "@$TO" search-replace "$FROMSITE" "$TOSITE" &&
rsync -az --progress "$FROMDIR" "$TODIR"
else
wp "@$TO" search-replace "$FROMSITE" "$TOSITE"
fi
fi
Wouldn’t this be a great candidate for a GitHub repository?
–skip-columns=guid should be used when replacing, see
https://codex.wordpress.org/Changing_The_Site_URL#Important_GUID_Note
I am working on a repo here. Raquelle as author (@cedarstay ) as well as @ben have been mentioned for the script they made and I added there. Thanks so much for sharing this and teaching me more about aliases and shell scripts! README is not quite done yet and tweaks me be needed. Feel free to submit pull requests or clone it.
Also a plain backup option would be nice that dumps the database and uploads/ folder to a specific local path (for remote regular backups).