I’ve been doing a lot of bash scripting with WordPress, especially with WP CLI. Here are some snippets I found useful.
All my scripts assume a standard wp-config.php
with DEFINE()
statements and no unusual logic structures. A rogue constant with the name DB_NAME
may throw things off without some modification.
Getting the Database table prefix
If you need to make any SQL queries using WP CLI, you will need the database prefix for table names
cat wp-config.php | grep "\$table_prefix" | cut -d \' -f 2
Getting WP Config Database user and password
If you’ve just downloaded an install of WordPress, these will give you the details to retrieve the database
WPDBNAME=`cat wp-config.php | grep DB_NAME | cut -d \' -f 4` WPDBUSER=`cat wp-config.php | grep DB_USER | cut -d \' -f 4` WPDBPASS=`cat wp-config.php | grep DB_PASSWORD | cut -d \' -f 4`
Setting WP Config database user and password
If you download a copy of an install, you may have to modify the DB details, this will do that automatically
sed -i "/DB_HOST/s/'[^']*'/'localhost'/2" wp-config.php sed -i "/DB_NAME/s/'[^']*'/'databasename'/2" wp-config.php sed -i "/DB_USER/s/'[^']*'/'user'/2" wp-config.php sed -i "/DB_PASSWORD/s/'[^']*'/'password'/2" wp-config.php
Adding SUNRISE to wp-config.php
Modifying wp-config.php
to add new items isn’t as simple as appending to the end.
sed -i "/define('BLOG_ID_CURRENT_SITE', 1);/ a\ DEFINE( 'SUNRISE', true );\ " wp-config.php
Getting a list of active plugins and looping over them
Here I export the active plugin list as a CSV with a single column and ignore the name entry, letting me iterate through active plugins
active=$(wp plugin list --status=active --format=csv --fields=name) for plugin in $active
do if [ ! "${plugin}" = 'name' ]; then echo "${plugin}" fi done
Vagrant Guest Additions
While using VVV with VirtualBox, I regularly get told I’m using out of date guest host additions. Theres a vagrant plugin that auto-updates those
vagrant plugin install vagrant-vbguest
List all blogs via WP CLI
Listing and processing all blogs and sites on a multisite network isn’t as trivial as it’s made out to be, here is how you get the site id, URL, and blog id individually
blogs=$(wp site list --fields="site_id,blog_id,url" --format="csv") for entry in $blogs do site_id=$(echo $entry |cut -d ',' -f1 ) blog_id=$(echo $entry |cut -d ',' -f2 ) blog_url=$(echo $entry |cut -d ',' -f3 ) echo "$blog_id: $blog_url in $site_id" done
Installing Domain mapping via WP CLI
Simply installing and activating domain mapping isn’t enough, you need to move sunrise.php
and setup the necessary DEFINE
in wp-config.php
wp plugin install wordpress-mu-domain-mapping cp wp-content/plugins/wordpress-mu-domain-mapping/sunrise.php wp-content/sunrise.php sed -i "/define('BLOG_ID_CURRENT_SITE', 1);/ a\ DEFINE( 'SUNRISE', true );\ " wp-config.php wp plugin activate wordpress-mu-domain-mapping
Getting the domain name of a WP site via WP CLI
If I’m in an install and want a clean URL such as tomjn.com without the trailing slash and protocol identifier, I would do this:
siteurl=$(wp option get siteurl) url=$(echo $siteurl | awk -F/ '{print $3}') echo $url
Get the blog ID of a blog given a URL
WP CLI can list all sites for you, but sometimes you only have a URL to go by and need to find its blog ID
dbprefix=$(cat wp-config.php | grep "\$table_prefix" | cut -d \' -f 2) query1=$(wp db query "SELECT blog_id FROM ${dbprefix}blogs b WHERE b.domain LIKE \"%${fromdomain}%\" LIMIT 1") blog_id=$(echo $query1 |cut -d ' ' -f2) echo $blog_id
Setting Up Domain Mapping via WP CLI
A manual SQL query is needed for this, followed by the setting of some options.
NOTE: Domain mapping only generates the table when you visit the domain mapping admin page, so if you setup a site and run the query it will fail if nobody has logged into the site and visited the network admin panel.
fromdomain='...' todomain='...' dbprefix=$(cat wp-config.php | grep "\$table_prefix" | cut -d \' -f 2) query1=$(wp db query "SELECT blog_id FROM ${dbprefix}blogs b WHERE b.domain LIKE \"%${fromdomain}%\" LIMIT 1") blog_id=$(echo $query1 |cut -d ' ' -f2) echo $blog_id wp db query "INSERT INTO ${dbprefix}domain_mapping ( blog_id, domain, active ) VALUES ( $blog_id, \"${todomain}\", 1 )" wp option update home "http://${todomain}" --url="${todomain}" wp option update siteurl "http://${todomain}" --url="${todomain}"
Pulling Down a Remote site Copy Into a Vagrant VM
I use something similar to this to pull down this website into a Virtual machine automatically. If you use password authentication to log into your server rather than SSH Keys, or your using SFTP details, you’ll be prompted for it. If you use public/private key authentication this script will run uninterrupted.
#!/bin/sh ### SSH Info ### SUSER="serverusername"; SHOST="example.com"; SDIR="/srv/www/example.com"; echo 'starting rsync' rsync -e "/usr/bin/ssh" --compress --stats -rlDHS $SUSER@$SHOST:$SDIR /srv/www/example.com WPDBHOST=`cat /srv/www/example.com/wp-config.php | grep DB_HOST | cut -d \' -f 4`; WPDBNAME=`cat /srv/www/tomjn.com/wp-config.php | grep DB_NAME | cut -d \' -f 4`; WPDBUSER=`cat /srv/www/tomjn.com/wp-config.php | grep DB_USER | cut -d \' -f 4`; WPDBPASS=`cat /srv/www/tomjn.com/wp-config.php | grep DB_PASSWORD | cut -d \' -f 4`; echo 'finished rsync, grabbing database' FILE=$SDIR/mysql-$WPDBNAME.sql.gz; # Set the backup filename #echo "mysqldump -q -u $WPDBUSER -h $WPDBHOST -p$WPDBPASS $WPDBNAME | gzip -9 > $FILE"; ssh $SUSER@$SHOST "mysqldump -q -u $WPDBUSER -h $WPDBHOST -p$WPDBPASS $WPDBNAME | gzip -9 > backup.sql.gz" scp $SUSER@$SHOST:./backup.sql.gz . # copy all the files to backup server ssh $SUSER@$SHOST rm ./backup.sql.gz # delete files on db server gunzip -d backup.sql.gz mysql -u root -e "CREATE DATABASE IF NOT EXISTS $WPDBNAME" mysql -u root -e "GRANT ALL PRIVILEGES ON $WPDBNAME.* To 'wp'@'localhost'" mysql -u wp -pwp $WPDBNAME < backup.sql sed -i "/DB_HOST/s/'[^']*'/'localhost'/2" wp-config.php sed -i "/DB_USER/s/'[^']*'/'wp'/2" wp-config.php sed -i "/DB_PASSWORD/s/'[^']*'/'wp'/2" wp-config.php
Useful bunch of bash scripts for WordPress from Tom Nowell. http://t.co/Su5vZpec65
RT @philipjohn: Useful bunch of bash scripts for WordPress from Tom Nowell. http://t.co/Su5vZpec65
RT @Tarendai: WordPress Bash Magic http://t.co/aotNd34du4 #wordpress #bash #wpcli
RT @Tarendai: WordPress Bash Magic http://t.co/aotNd34du4 #wordpress #bash #wpcli
RT @Tarendai: WordPress Bash Magic http://t.co/aotNd34du4 #wordpress #bash #wpcli
> NOTE: Domain mapping only generates the table when you visit the domain mapping admin page, so if you setup a site and run the query it will fail if nobody has logged into the site and visited the network admin panel.
I stumbled onto you page while trying to figure this out, but I think I have a solution 🙂
`wp eval “maybe_create_db();” –user=super_admin_username`
You can actually do the database transfer in one command, with no intermediate files, which gives me the shivers … Something like
mysql -u $NEWDBUSER -p$NEWDBPASS $NEWDBNAME < <(ssh -p 22 user@server.com "mysqldump -u $OLDDBUSER -p$OLDDBPASS $OLDDBNAME")
True, but that does a database only copy and won’t fire any of the hooks that happen on post creation, such as sending the images to the CDN, notifying other posts, or firing actions the theme might rely on to do extra operations such as creating terms and updating secondary tables
Thank you so very much specifically for the sed lines the replace the values of the various wp-config keys. Thank you thank you!
I ran in to a bit of an issue with your method for getting existing configuration keys because I had some older keys in my wp-config.php that were commented-out. This is obviously fine for PHP, but caused sed to return a much different string than I wanted. It’d be nice if there was a concise way to update the getting of the keys to ignore lines that start with a comment “#”
it sounds like you need a PHP parser, it’d be easier to delete the commented out values and back that information up elsewhere
If you’re only reading and not writing, you could always start with
grep -v ‘^\#’ wp-config.php |
That should give you the uncommented lines only.
Pingback: Bash new line feed in results