Skip to content

Instantly share code, notes, and snippets.

@pfrenssen
Last active May 21, 2019 09:29
Show Gist options
  • Save pfrenssen/a672bf18b26e1ccbb74e to your computer and use it in GitHub Desktop.
Save pfrenssen/a672bf18b26e1ccbb74e to your computer and use it in GitHub Desktop.
#!/bin/bash -e
#
# Syncs a local Drupal dev site with the production server:
# - pulls latest code from the git repo on the server
# - downloads database from production and restores it locally
# - syncs the sites/default/files folder
#
# Required software packages: git, mysql, openssh, rsync, sudo
# Drush has to be installed on the server.
#
# This script will happily overwrite all your local changes and will throw away
# your database. Make sure everything important is committed or backed up.
#
# A list of the configuration variables.
CONFIG_VARIABLES=( "PROJECT" "SSH_USER" "SSH_SERVER" "REMOTE_TMP" "REMOTE_WEBROOT" "GIT_REPO" "LOCAL_BACKUP" "LOCAL_WEBROOT" "LOCAL_USER" "LOCAL_APACHE_USER" "LOCAL_MYSQL_USER" "LOCAL_MYSQL_PASS" "LOCAL_DRUSH" "REMOTE_DRUSH" )
# Load config file if it exists.
if [ -f sync.config ]; then
. sync.config
fi
# Get user input for missing parameters.
until [[ "$PROJECT" =~ ^[_0-9a-z]+$ ]] ; do
echo "Enter a name for the project. Lowercase characters and underscores only."
read -p "Project name: " PROJECT
done
while [ -z "$SSH_USER" ] ; do
read -e -p "Remote user name: " -i "$PROJECT" SSH_USER
done
while [ -z "$SSH_SERVER" ] ; do
read -e -p "Remote domain name: " -i "srv1.pocomas.be" SSH_SERVER
done
while [ -z "$REMOTE_TMP" ] ; do
read -e -p "Remote temporary folder: " -i "/home/${SSH_USER}/backups" REMOTE_TMP
if ! ssh $SSH_USER@$SSH_SERVER test -d "$REMOTE_TMP" ; then
echo 'Error, folder does not exist. Please try again.'
REMOTE_TMP=
fi
done
while [ -z "$REMOTE_WEBROOT" ] ; do
read -e -p "Remote Drupal root folder: " -i "/home/${SSH_USER}/public_html" REMOTE_WEBROOT
if ! ssh $SSH_USER@$SSH_SERVER test -d "$REMOTE_WEBROOT" ; then
echo 'Error, folder does not exist. Please try again.'
REMOTE_WEBROOT=
fi
done
while [ -z "$GIT_REPO" ] ; do
read -e -p "URI of the master bare git repo: " -i "$SSH_USER@$SSH_SERVER:/home/${SSH_USER}/git" GIT_REPO
if ! git ls-remote $GIT_REPO &> /dev/null ; then
echo 'Error, no git repository found at this location. Please try again.'
GIT_REPO=
fi
done
while [ -z "$LOCAL_BACKUP" ] ; do
read -e -p "Local database backup folder: " -i "`pwd`/database" LOCAL_BACKUP
done
while [ -z "$LOCAL_WEBROOT" ] ; do
read -e -p "Local Drupal root folder: " -i "`pwd`/drupal" LOCAL_WEBROOT
done
while [ -z "$LOCAL_USER" ] ; do
read -e -p "Local user name: " -i "`whoami`" LOCAL_USER
done
while [ -z "$LOCAL_APACHE_USER" ] ; do
read -e -p "Local Apache user name: " -i "`whoami`" LOCAL_APACHE_USER
done
while [ -z "$LOCAL_MYSQL_USER" ] ; do
read -e -p "Local MySQL user name: " -i "root" LOCAL_MYSQL_USER
read -e -p "Local MySQL password: " LOCAL_MYSQL_PASS
done
while [ -z "$LOCAL_DRUSH" ] ; do
read -e -p "Local Drush installation: " -i "$LOCAL_WEBROOT/vendor/bin/drush" LOCAL_DRUSH
done
while [ -z "$REMOTE_DRUSH" ] ; do
read -e -p "Remote Drush installation: " -i "$REMOTE_WEBROOT/vendor/bin/drush" REMOTE_DRUSH
done
if [ ! -f sync.config ]; then
read -e -p "Do you want to save these settings (y/n)? " -i "y" SAVE_CONFIG
if [ "$SAVE_CONFIG" == "y" ] ; then
for CONFIG_VARIABLE in ${CONFIG_VARIABLES[@]} ; do
echo "$CONFIG_VARIABLE=\"${!CONFIG_VARIABLE}\"" >> sync.config
done
fi
fi
# First check if the code is already present. If not, download a fresh copy from
# the server and prepare everything for the installation of Drupal.
if [ ! -d "$LOCAL_WEBROOT" ]; then
# Clone the remote repo into $LOCAL_WEBROOT.
git clone $GIT_REPO $LOCAL_WEBROOT
fi
# Install Composer dependencies.
if [ -f $LOCAL_WEBROOT/composer.json ]; then
composer install --working-dir=$LOCAL_WEBROOT
fi
# Make sure the sites/default folder is writable.
sudo chmod u+w $LOCAL_WEBROOT/sites/default
# Create the sites/default/files/-folder and set permissions.
mkdir -p $LOCAL_WEBROOT/sites/default/files
sudo chown $LOCAL_USER:$LOCAL_APACHE_USER $LOCAL_WEBROOT/sites/default/files
sudo chmod 775 $LOCAL_WEBROOT/sites/default/files
# If the site is not yet installed, do so.
if [ ! -f "${LOCAL_WEBROOT}/sites/default/settings.php" ]; then
# @todo: ask the user for a database name and credentials before creating the
# database.
# Create a new database.
mysql -e "DROP DATABASE IF EXISTS \`$PROJECT\`;"
mysql -e "CREATE DATABASE \`$PROJECT\`;"
# Install Drupal.
$LOCAL_DRUSH site-install minimal install_configure_form.update_status_module='array(FALSE,FALSE)' --root="${LOCAL_WEBROOT}" --db-url=mysql://${LOCAL_MYSQL_USER}:${LOCAL_MYSQL_PASS}@localhost/${PROJECT} --account-name=${PROJECT} --account-pass=${PROJECT} --yes
else
# Pull latest code from the repository.
cd $LOCAL_WEBROOT
git checkout master
if [ -n "$(git log origin/master..master)" ] ; then
echo "Please make sure all local commits have been pushed to origin, or discard them before continuing."
exit 1
fi
git reset --hard origin/master
git pull origin master --no-edit
fi
# Make a gzipped backup of the production database and save it on the server.
SUFFIX=$(date +"%Y%m%d")-$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 6 | head -n 1)
ssh -l $SSH_USER $SSH_SERVER "$REMOTE_DRUSH --root=\"$REMOTE_WEBROOT\" sql-dump | gzip -9 > $REMOTE_TMP/${PROJECT}-${SUFFIX}.sql.gz"
# Check to see if database backup folder exists. If not create it.
if [ ! -d "$LOCAL_BACKUP" ]; then
mkdir -p $LOCAL_BACKUP
fi
# Transfer database backup.
scp $SSH_USER@$SSH_SERVER:$REMOTE_TMP/${PROJECT}-${SUFFIX}.sql.gz $LOCAL_BACKUP
# @todo
# Backup local database before restoring.
# Restore database backup.
gunzip $LOCAL_BACKUP/${PROJECT}-${SUFFIX}.sql.gz --stdout | $LOCAL_DRUSH --root=$LOCAL_WEBROOT sql-cli
# Delete backup from server
ssh -l $SSH_USER $SSH_SERVER "rm $REMOTE_TMP/${PROJECT}-${SUFFIX}.sql.gz"
# Make sure the files folder is writable by the current user. Execute these
# commands in batches of 100 to avoid "Argument list too long" errors.
while [[ $(find $LOCAL_WEBROOT/sites/default/files/ ! -user $LOCAL_USER -printf '.' | wc -c) != 0 ]]; do
find $LOCAL_WEBROOT/sites/default/files/ ! -user $LOCAL_USER -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chown $LOCAL_USER
done
while [[ $(find $LOCAL_WEBROOT/sites/default/files/ ! -perm -u+w -printf '.' | wc -c) != 0 ]]; do
find $LOCAL_WEBROOT/sites/default/files/ ! -perm -u+w -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chmod u+w
done
# Synchronize the files folder.
rsync -rltDvz --delete --no-perms $SSH_USER@$SSH_SERVER:$REMOTE_WEBROOT/sites/default/files/ $LOCAL_WEBROOT/sites/default/files/
# Set permissions.
sudo chown -R $LOCAL_USER:$LOCAL_APACHE_USER $LOCAL_WEBROOT/sites/default/files
while [[ $(find $LOCAL_WEBROOT/sites/default/files -type d ! -perm -775 -printf '.' | wc -c) != 0 ]]; do
find $LOCAL_WEBROOT/sites/default/files -type d ! -perm -775 -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chmod 775
done
while [[ $(find $LOCAL_WEBROOT/sites/default/files -type f ! -perm -664 -printf '.' | wc -c) != 0 ]]; do
find $LOCAL_WEBROOT/sites/default/files -type f ! -perm -664 -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chmod 664
done
# Clear Drupal cache.
$LOCAL_DRUSH --root="${LOCAL_WEBROOT}" cc all
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment