Skip to content

Instantly share code, notes, and snippets.

@ryansechrest
Created December 23, 2013 07:40
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ryansechrest/8093056 to your computer and use it in GitHub Desktop.
Save ryansechrest/8093056 to your computer and use it in GitHub Desktop.
Bash script to synchronize website directory and database between server and localhost or server and server.
#!/bin/bash
# Created on 10/8/13 by Ryan Sechrest
# site (localhost edition)
# Program to mirror a directory and database of a website between two servers.
### Program meta data
# Program name
NAME='site'
# Program version
VERSION='1.0.0'
# Today's date
DATE=$(date +'%x %r %Z')
# Program header title
TITLE="Site v$VERSION on $HOSTNAME"
# Program header information
STATUS="$DATE by $USER"
# Program usage help
USAGE="Usage: $NAME [sync|update] [sitename]"
### Production database server
# Hostname or IP address
MYSQL_PRD_HOSTNAME='hostname'
# Username
MYSQL_PRD_USERNAME='username'
### Localhost database server
# Username
MYSQL_LOCAL_USERNAME='hostname'
# Password
MYSQL_LOCAL_PASSWORD='username'
### Production web server
# Hostname or IP address
SSH_PRD_HOSTNAME='hostname'
# Username
SSH_PRD_USERNAME='username'
### Local server paths
# Absolute path to local sites directory
# Ex: /Users/$USER/Sites
LOCAL_SITES_PATH="/Users/$USER/Sites"
# Absolute path to production sites directory
# Ex: /var/www/domains
PRD_SITES_PATH='/var/www/domains'
# Absolute path to local temporary sites directory
# Ex: /Volumes/Shared
TEMP_SITES_PATH='/Volumes/Shared'
### Executable shortcuts
# Path to various executables
# Ex: /Applications/MAMP/Library/bin
BIN_PATH='/Applications/MAMP/Library/bin'
# Path to 'mysql' executable
# Ex: $BIN_PATH/mysql
MYSQL="$BIN_PATH/mysql"
# Path to 'mysqldump' executable
# Ex: $BIN_PATH/mysqldump
MYSQLDUMP="$BIN_PATH/mysqldump"
### Save program arguments
arg1=$1
arg2=$2
### Display functions
# Display divider
function display_divider {
echo '------------------------------------------------------------'
}
# Display new line
function display_newline {
echo
}
# Display output start
function display_output_start {
echo '> Starting...'
}
# Display output end
function display_output_end {
echo '> Done.'
}
# Display program header
function display_header {
display_newline
display_divider
echo " $TITLE"
echo " $STATUS"
echo " $ $NAME $arg1 $arg2"
display_divider
display_newline
}
# Display usage help
function display_usage {
echo $USAGE
display_newline
}
### MySQL functions
# Update imported database to match local environment
# $1 mysql hostname
# $2 mysql username
# $3 mysql password
# $4 mydql database
# $5 domain name
function wp_mu_db_update {
user=$1
pass=$2
db=$3
query="$MYSQL --user=$user --password=$pass $db -e"
echo "> Setting 'domain' field in 'wp_blogs' table to 'localhost'..."
$query "UPDATE wp_blogs SET domain = 'localhost' WHERE blog_id = 1 AND site_id = 1";
echo "> Setting 'site_url' field in 'wp_options' table to 'http://localhost/wordpress'..."
$query "UPDATE wp_options SET option_value = 'http://localhost/wordpress' WHERE option_name = 'siteurl'";
echo "> Setting 'home' field in 'wp_options' to 'http://localhost'..."
$query "UPDATE wp_options SET option_value = 'http://localhost/' WHERE option_name = 'home'";
echo "> Setting 'domain' field in 'wp_site' to 'localhost'..."
$query "UPDATE wp_site SET domain = 'localhost' WHERE id = 1";
echo "> Setting 'site_url' field in 'wp_sitemeta' table to 'http://localhost/'..."
$query "UPDATE wp_sitemeta SET meta_value = 'http://localhost/' WHERE meta_key = 'siteurl' AND site_id = 1";
}
### Main Functions
# rsync
# -a, --archive archive mode; same as -rlptgoD
# -r, --recursive recurse into directories
# -l, --links copy symlinks as symlinks
# -p, --perms preserve permissions
# -t, --times preserve times
# -g, --group preserve group
# -o, --owner preserve owner (super-user only)
# -D same as --devices --specials
# --devices preserve device files (super-user only)
# --specials preserve special files
# -v, --verbose increase verbosity
# --exclude=PATTERN exclude files matching PATTERN
# --delete delete files that don’t exist on sender
# --delete-excluded also delete excluded files on receiver
# Copy files from production web server to temporary directory
# $1 path to files on production server
# $2 path to files on local server
# $3 rsync exclude option(s)
function download_files {
src=$1
dst=$2
ex=$3
if [ ! -d "$dst" ]; then
echo "> Creating temporary directory..."
echo " $dst"
mkdir -p "$dst"
fi
if [ -d "$dst" ]; then
echo "> Synchronizing production files with temporary directory..."
echo " Source : $src"
echo " Destination : $dst"
rsync --archive --verbose $ex --delete --delete-excluded "$src" "$dst"
else
echo "> Temporary directory does not exist"
echo " $dst"
fi
}
# Export database from production database server to temporary directory
# $1 database hostname
# $2 database username
# $3 database name
# $4 path to save mysql export
# $5 mysqldump ignore-table option(s)
function export_database {
host=$1
user=$2
db=$3
dst=$4
ignore=$5
if [ ! -d "$dst" ]; then
echo "> Creating temporary directory..."
echo " $dst"
mkdir -p "$dst"
fi
if [ -d "$dst" ]; then
echo "> Exporting production database to temporary directory..."
echo " Database : $db"
echo " Destination : $dst"
echo " Filename : $db.sql"
$MYSQLDUMP --verbose --host=$host --user=$user --password $db $ignore > "$dst/$db.sql"
else
echo "> Temporary directory does not exist"
echo " $dst"
fi
}
# Copy files from temporary directory to local site
# $1 path to temporary files on local server
# $2 path to real files on local server
function upload_files {
src=$1
dst=$2
if [[ (-d "$src") && (-d "$dst") ]]; then
echo "> Synchronizing temporary files with local site directory..."
echo " Source : $src"
echo " Destination : $dst"
rsync --archive --delete --delete-excluded "$src" "$dst"
else
echo "> Temporary or local site directory does not exist"
echo " Source : $src"
echo " Destination : $dst"
fi
}
# Import production database from temporary directory to local database
# $1 database hostname
# $2 database username
# $3 database password
# $4 database name
# $5 path to mysql export
function import_database {
user=$1
pass=$2
db=$3
src=$4
if [ -f "$src/$db.sql" ]; then
echo "> Importing temporary database export into local database..."
echo " Filename : $db.sql"
echo " Source : $src"
echo " Database : $db"
$MYSQL --user=$user --password=$pass $db < "$src/$db.sql"
else
echo "> Temporary database export does not exist"
echo " Filename : $db.sql"
echo " Source : $src"
fi
}
### Run Functions
# Run sync component
function run_sync {
case $arg2 in
sitename)
display_output_start
copy_from="$SSH_PRD_USERNAME@$SSH_PRD_HOSTNAME:$PRD_SITES_PATH/domain.com/www/htdocs/wp-content/uploads/"
copy_to="$TEMP_SITES_PATH/$arg2/uploads/"
exclude='--exclude=temp --exclude=wpcf7_uploads'
download_files "$copy_from" "$copy_to" "$exclude"
display_newline
mysql_hostname=$MYSQL_PRD_HOSTNAME
mysql_username=$MYSQL_PRD_USERNAME
mysql_database='domain_com'
export_to="$TEMP_SITES_PATH/$arg2"
ignore="--ignore-table=$mysql_database.wp_w3tc_cdn_queue"
export_database $mysql_hostname $mysql_username $mysql_database "$export_to" "$ignore"
display_output_end
;;
*)
display_usage
;;
esac
}
# Run update component
function run_update {
case $arg2 in
sitename)
display_output_start
copy_from="$TEMP_SITES_PATH/$arg2/uploads/"
copy_to="$LOCAL_SITES_PATH/domain.com/www/htdocs/wp-content/uploads/"
upload_files "$copy_from" "$copy_to"
mysql_username=$MYSQL_LOCAL_USERNAME
mysql_password=$MYSQL_LOCAL_PASSWORD
mysql_database='domain_com'
import_from="$TEMP_SITES_PATH/$arg2"
import_database $mysql_username $mysql_password $mysql_database "$import_from"
wp_mu_db_update $mysql_username $mysql_password $mysql_database
display_output_end
;;
*)
display_usage
;;
esac
}
# Run main component
function run {
case $arg1 in
sync)
run_sync
display_newline
;;
update)
run_update
display_newline
;;
*)
display_usage
;;
esac
}
### Run Program
display_header
run
exit 0
#!/bin/bash
# Created on 10/2/13 by Ryan Sechrest
# site (server edition)
# Program to mirror a directory and database of a website between two servers.
### Program meta data
# Program name
NAME='site'
# Program version
VERSION='1.0.0'
# Today's date
DATE=$(date +'%x %r %Z')
# Program header title
TITLE="Site v$VERSION on $HOSTNAME"
# Program header information
STATUS="$DATE by $USER"
# Program usage help
USAGE="Usage: $NAME [sync|update] [sitename]"
### Server environment
ENV=''
case $HOSTNAME in
DEV01.DOMAIN.COM)
ENV='DEV'
;;
STG01.DOMAIN.COM)
ENV='STG'
;;
esac
### Production database server
# Hostname or IP address
MYSQL_PRD_HOSTNAME='hostname'
# Username
MYSQL_PRD_USERNAME='username'
### Production web server
# Hostname or IP address
SSH_PRD_HOSTNAME='hostname'
# Username
SSH_PRD_USERNAME='username'
### Local server paths
# Absolute path to local sites directory
# Ex: /var/www/domains
LOCAL_SITES_PATH='/var/www/domains'
# Absolute path to production sites directory
# Ex: /var/www/domains
PRD_SITES_PATH='/var/www/domains'
# Absolute path to local temporary sites directory
# Ex: /opt/sites
TEMP_SITES_PATH='/opt/sites'
### Save program arguments
arg1=$1
arg2=$2
### Display functions
# Display divider
function display_divider {
echo '------------------------------------------------------------'
}
# Display new line
function display_newline {
echo
}
# Display output start
function display_output_start {
echo '> Starting...'
}
# Display output end
function display_output_end {
echo '> Done.'
}
# Display program header
function display_header {
display_newline
display_divider
echo " $TITLE"
echo " $STATUS"
echo " $ $NAME $arg1 $arg2"
display_divider
display_newline
}
# Display usage help
function display_usage {
echo $USAGE
display_newline
}
### MySQL functions
# Update imported database to match local environment
# $1 mysql hostname
# $2 mysql username
# $3 mysql password
# $4 mydql database
# $5 domain name
function wp_mu_db_update {
host=$1
user=$2
pass=$3
db=$4
domain=$5
query="mysql --host=$host --user=$user --password=$pass $db -e"
echo "> Setting 'domain' field in 'wp_blogs' table to '$domain'..."
$query "UPDATE wp_blogs SET domain = '$domain' WHERE blog_id = 1 AND site_id = 1";
echo "> Setting 'site_url' field in 'wp_options' table to 'http://$domain/wordpress'..."
$query "UPDATE wp_options SET option_value = 'http://$domain/wordpress' WHERE option_name = 'siteurl'";
echo "> Setting 'home' field in 'wp_options' to 'http://$domain'..."
$query "UPDATE wp_options SET option_value = 'http://$domain/' WHERE option_name = 'home'";
echo "> Setting 'domain' field in 'wp_site' to '$domain'..."
$query "UPDATE wp_site SET domain = '$domain' WHERE id = 1";
echo "> Setting 'site_url' field in 'wp_sitemeta' table to 'http://$domain/'..."
$query "UPDATE wp_sitemeta SET meta_value = 'http://$domain/' WHERE meta_key = 'siteurl' AND site_id = 1";
}
### Main functions
# rsync
# -a, --archive archive mode; same as -rlptgoD
# -r, --recursive recurse into directories
# -l, --links copy symlinks as symlinks
# -p, --perms preserve permissions
# -t, --times preserve times
# -g, --group preserve group
# -o, --owner preserve owner (super-user only)
# -D same as --devices --specials
# --devices preserve device files (super-user only)
# --specials preserve special files
# -v, --verbose increase verbosity
# --exclude=PATTERN exclude files matching PATTERN
# --delete delete files that don’t exist on sender
# --delete-excluded also delete excluded files on receiver
# Copy files from production web server to temporary directory
# $1 path to files on production server
# $2 path to files on local server
# $3 rsync exclude option(s)
function download_files {
src=$1
dst=$2
ex=$3
if [ ! -d "$dst" ]; then
echo "> Creating temporary directory..."
echo " $dst"
mkdir -p "$dst"
fi
if [ -d "$dst" ]; then
echo "> Synchronizing production files with temporary directory..."
echo " Source : $src"
echo " Destination : $dst"
rsync --archive --verbose $ex --delete --delete-excluded "$src" "$dst"
else
echo "> Temporary directory does not exist"
echo " $dst"
fi
}
# Export database from production database server to temporary directory
# $1 database hostname
# $2 database username
# $3 database name
# $4 path to save mysql export
# $5 mysqldump ignore-table option(s)
function export_database {
host=$1
user=$2
db=$3
dst=$4
ignore=$5
if [ ! -d "$dst" ]; then
echo "> Creating temporary directory..."
echo " $dst"
mkdir -p "$dst"
fi
if [ -d "$dst" ]; then
echo "> Exporting production database to temporary directory..."
echo " Database : $db"
echo " Destination : $dst"
echo " Filename : $db.sql"
mysqldump --verbose --host=$host --user=$user --password $db $ignore > "$dst/$db.sql"
else
echo "> Temporary directory does not exist"
echo " $dst"
fi
}
# Copy files from temporary directory to local site
# $1 path to temporary files on local server
# $2 path to real files on local server
function upload_files {
src=$1
dst=$2
if [[ (-d "$src") && (-d "$dst") ]]; then
echo "> Synchronizing temporary files with local site directory..."
echo " Source : $src"
echo " Destination : $dst"
rsync --archive --delete --delete-excluded "$src" "$dst"
else
echo "> Temporary or local site directory does not exist"
echo " Source : $src"
echo " Destination : $dst"
fi
}
# Import production database from temporary directory to local database
# $1 database hostname
# $2 database username
# $3 database password
# $4 database name
# $5 path to mysql export
function import_database {
host=$1
user=$2
pass=$3
db=$4
src=$5
if [ -f "$src/$db.sql" ]; then
echo "> Importing temporary database export into local database..."
echo " Filename : $db.sql"
echo " Source : $src"
echo " Database : $db"
mysql --host=$host --user=$user --password=$pass $db < "$src/$db.sql"
else
echo "> Temporary database export does not exist"
echo " Filename : $db.sql"
echo " Source : $src"
fi
}
### Run functions
# Run sync component
function run_sync {
case $arg2 in
sitename)
display_output_start
copy_from="$SSH_PRD_USERNAME@$SSH_PRD_HOSTNAME:$PRD_SITES_PATH/domain.com/www/htdocs/wp-content/uploads/"
copy_to="$TEMP_SITES_PATH/$arg2/uploads/"
exclude='--exclude=temp --exclude=wpcf7_uploads'
download_files "$copy_from" "$copy_to" "$exclude"
display_newline
mysql_hostname=$MYSQL_PRD_HOSTNAME
mysql_username=$MYSQL_PRD_USERNAME
mysql_database='domain_com'
export_to="$TEMP_SITES_PATH/$arg2"
ignore="--ignore-table=$mysql_database.wp_w3tc_cdn_queue"
export_database $mysql_hostname $mysql_username $mysql_database "$export_to" "$ignore"
display_output_end
;;
*)
display_usage
;;
esac
}
# Run update component
function run_update {
case $arg2 in
sitename)
display_output_start
copy_from="$TEMP_SITES_PATH/$arg2/uploads/"
copy_to="$LOCAL_SITES_PATH/domain.com/www/htdocs/wp-content/uploads/"
upload_files "$copy_from" "$copy_to"
mysql_username=''
mysql_password=''
domain_name=''
case $ENV in
DEV)
mysql_username='username'
mysql_password='password'
domain_name='dev01.domain.com'
;;
STG)
mysql_username='username'
mysql_password='password'
domain_name='stg01.domain.com'
;;
esac
if [[ (-n $mysql_username) && (-n $mysql_password) && (-n $domain_name) ]]; then
mysql_hostname='localhost'
mysql_database='domain_com'
import_from="$TEMP_SITES_PATH/$arg2"
import_database $mysql_hostname $mysql_username $mysql_password $mysql_database "$import_from"
wp_mu_db_update $mysql_hostname $mysql_username $mysql_password $mysql_database $domain_name
else
echo "> Unable to obtain MySQL credentials for $ENV server"
fi
display_output_end
;;
*)
display_usage
;;
esac
}
# Run main component
function run {
case $arg1 in
sync)
run_sync
display_newline
;;
update)
run_update
display_newline
;;
*)
display_usage
;;
esac
}
### Run Program
display_header
run
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment