#!/bin/bash # This script copies a site onto another domain name # and into another database. # This facilitates testing something on the original site # without screwing that site up. # # The script can take db connection information for the target db to use. # If not supplied, then it is reused from an already present target install. # The db host is not changed -- it is assumed to be the same. # # TODO D-7 The 'fix up' queries in this script aren't valid for Drupal-7 # include library file . "`dirname ${0}`/drupalLibrary.sh" printUsage() { echo -e " " echo -e "Copies a site from one domain to another, duplicating the source site." echo -e " " echo -e "Usage:" echo -e "$0 [ ] [install group root dir]" echo -e "where:" echo -e " " echo -e " can be any/all/none of:" echo -e "-targetRootDir " echo -e "\tUses the alternitive (fully qualified) root dir when creating target site." echo -e "-notest" echo -e "\tDoes not perform connection test of the db connection information for the target install." echo -e "-nomunge" echo -e "\tDoes not update the target node_revision table changing references from the source domain to the target domain. " echo -e "-noreset" echo -e "\tDoes not attempt to hit the target site\'s modules and themes page to perform necessary content resets." echo -e "-noconfirm Supresses the confirmation request." echo -e " " echo -e "" echo -e "\tThe installation site to copy." echo -e "" echo -e "\tThe installation site to copy." echo -e " " echo -e "\tIf supplied, the database connection parameters with which to connect to the database for the target site." echo -e "\tIf not supplied, this info will be gathered from an already existing target site." echo -e " " outputGroupRootDirUsage echo -e " " } ######### # Param handling if [ $# -eq 0 ]; then printUsage exit 0 fi echo " " # Handle flags while (true); do case "${1}" in -targetRootDir ) pTargetRootDir="${2}" shift; shift # Validate target root dir errorStr="`validateGroupRootDir "${pTargetRootDir}"`" if [ -n "${errorStr}" ]; then echo -e "Error with specified target root dir '${pTargetRootDir}'" echo -e "${errorStr}\n" printUsage exit 1 fi ;; -notest ) pNotest="-notest" shift ;; -nomunge ) pNomunge="-nomunge" shift ;; -noreset ) pNoreset="-noreset" shift ;; -noconfirm ) pNoConfirm="-noconfirm"; shift ;; * ) break ;; esac done # Save source/target install sourceInstall="${1}" targetInstall="${2}" if [ -z "${sourceInstall}" -o -z "${targetInstall}" ]; then echo -e "** Source/target install must be specified. Aborting.\n" printUsage exit 1 fi shift; shift # Get target db connection info, if provided if [ $# -ge 4 ]; then targetDbHost="${1}" targetDbName="${2}" targetDbUsername="${3}" targetDbPassword="${4}" shift; shift; shift; shift fi if [ $# -gt 1 ]; then echo -e "** Invalid number of parameters supplied. Aborting\n" printUsage exit 1 fi # process Group Root Dir pRootDir="`getGroupRootDir "${1}"`" errorStr="`validateGroupRootDir "${pRootDir}"`" if [ -n "${errorStr}" ]; then echo -e "${errorStr}\n" printUsage exit 1 fi if [ -z "${pTargetRootDir}" ]; then pTargetRootDir="${pRootDir}" fi # Validate the source installation errorStr="`validateSite "${sourceInstall}" "${pRootDir}"`" if [ -n "${errorStr}" ]; then echo -e "** Error with specified source install: ${errorStr}. Aborting.\n" exit 1 fi ######### if [ -z "${pNoConfirm}" ]; then echo "Duplicating site '${sourceInstall}' on '${targetInstall}'." echo "This will clobber the site currently installed on '${targetInstall}'." echo "Press to continue, or ^C to quit..." read fi # Get the db connection info from the target installation if not provided. if [ -z "${targetDbHost}" -o -z "${targetDbName}" -o -z "${targetDbUsername}" -o -z "${targetDbPassword}" ]; then echo -n "Extracting db connection information from (existing) target site.... " # Validate the target installation errorStr="`validateSite "${targetInstall}" "${pTargetRootDir}"`" if [ -n "${errorStr}" ]; then echo -e "\n** Attempting to get db connection info from target installation; but encountered error: ${errorStr}. Aborting.\n" exit 1 fi targetDbHost="`getDBHost "${targetInstall}" "${pTargetRootDir}"`" targetDbName="`getDBName "${targetInstall}" "${pTargetRootDir}"`" targetDbUsername="`getDBUsername "${targetInstall}" "${pTargetRootDir}"`" targetDbPassword="`getDBPassword "${targetInstall}" "${pTargetRootDir}"`" # Check it if [ -z "${targetDbHost}" -o -z "${targetDbName}" -o -z "${targetDbUsername}" -o -z "${targetDbPassword}" ]; then echo -e "\n** Could not get complete db connection info from target installation. Aborting.\n" exit 1 fi echo "done." fi # test db connection if requested if [ -z "${pNotest}" ]; then echo -n "Testing target site db connection information.... " errorStr="`testDBConnectionForParameters "${targetDbHost}" "${targetDbName}" "${targetDbUsername}" "${targetDbPassword}"`" if [ -n "${errorStr}" ]; then echo -e "\n** Unable to connect to configured target database: ${errorStr}. Aborting.\n" exit 1 fi echo "done." fi # test source db host/name against target db host/name -- they can't be the same sDBHost="`getDBHost "${sourceInstall}" "${pRootDir}"`" sDbName="`getDBName "${sourceInstall}" "${pRootDir}"`" if [ "${sDBHost}/${sDbName}" == "${targetDbHost}/${targetDbName}" ]; then echo -e "\n** Source and target DB host/DB name equal. Aborting.\n" exit 1 fi # A bit of setup cd "${pTargetRootDir}" targetBaseName="`basename "${targetInstall}"`" # should be the same as the targetInstall... just being careful # Reset permissions on target install beforehand # to prevent any problems with removing of that site. cd "${pTargetRootDir}" if [ -d "./${targetBaseName}" ]; then echo -n "Initial reset of target install permissions.... " "`dirname $0`/drupalSetPerms.sh" -quiet "${targetInstall}" "${pTargetRootDir}" echo "done." fi # remove old site. Be extra, extra careful. cd "${pTargetRootDir}" if [ -d "./${targetBaseName}" ]; then echo -n "Removing existing target site installation.... " /bin/rm -rf "${targetBaseName}" if [ -d "./${targetBaseName}" ]; then echo -e "\n** Unable to remove target install directory. Aborting.\n" exit 1 fi echo "done." fi # copy site echo -n "Copying source site files to target.... " cd "${pTargetRootDir}" /bin/cp -r "${pRootDir}/${sourceInstall}" "./${targetBaseName}" echo "done." # rename sites dir # also must check for presence of symlink # matching the target base name symlink in target install # this can be an artifact of a previous site copy echo -n "Renaming sites directory in target.... " cd "${pTargetRootDir}/${targetBaseName}/sites" if [ -L "${targetBaseName}" ]; then rm -f "${targetBaseName}" fi mv "${sourceInstall}" "${targetBaseName}" echo "done." # Create symbolic link echo -n "Creating symbolic links in target sites dir.... " cd "${pTargetRootDir}/${targetBaseName}/sites" ln -s "${targetBaseName}" "${sourceInstall}" echo "done." # Munging db connection info echo -n "Setting db connection info into target site settings file.... " setDBHost "${targetInstall}" "${pTargetRootDir}" "${targetDbHost}" setDBName "${targetInstall}" "${pTargetRootDir}" "${targetDbName}" setDBUsername "${targetInstall}" "${pTargetRootDir}" "${targetDbUsername}" setDBPassword "${targetInstall}" "${pTargetRootDir}" "${targetDbPassword}" echo "done." # Clobber target database echo -n "Clobbering target database.... " tDbConnection="`getDBConnectionString "${targetInstall}" "${pTargetRootDir}"`" dropAllTables "${tDbConnection}" echo "done." # Sync database echo -n "Syncing database from source to target.... " sDbAuth="`getDBAuthString "${sourceInstall}" "${pRootDir}"`" sDbName="`getDBName "${sourceInstall}" "${pRootDir}"`" ${MYSQLDUMP} ${sDbAuth} ${sDbName} | ${MYSQL} ${tDbConnection} echo "done." # Munge the system and files table on the target. # This is similar to the 'drupalDBQuery.sh fixfiles' command; # but that won't work because the new name is not a proper alias. echo -n "Updating target 'system' and 'files' tables.... " query="" query="${query} UPDATE system SET filename = replace(filename, 'sites/${sourceInstall}/modules/', 'sites/${targetInstall}/modules/');" query="${query} UPDATE files SET filepath = replace(filepath, 'sites/${sourceInstall}/files/', 'sites/${targetInstall}/files/');" runSQL "${targetInstall}" "${pTargetRootDir}" "${query}" echo "done." # Munge the node_revision table on the target. # We replace specific content path usages of the old site name to the new site name. if [ -z "${pNomunge}" ]; then echo -n "Updating target 'node_revision' table.... " query="" query="${query} UPDATE node_revisions SET body = replace(body, '/sites/${sourceInstall}/files/', '/sites/${targetInstall}/files/');" query="${query} UPDATE node_revisions SET teaser = replace(teaser, '/sites/${sourceInstall}/files/', '/sites/${targetInstall}/files/');" query="${query} UPDATE node_revisions SET body = replace(body, 'http://${sourceInstall}/', 'http://${targetInstall}/');" query="${query} UPDATE node_revisions SET teaser = replace(teaser, 'http://${sourceInstall}/', 'http://${targetInstall}/');" runSQL "${targetInstall}" "${pTargetRootDir}" "${query}" echo "done." fi # Fix file upload path echo -n "Updating file directory path.... " "`dirname $0`/drupalDBQuery.sh" -quiet fileupload "${targetInstall}" "${pTargetRootDir}" echo "done." # Clear cache & session tables echo -n "Clearing target site cache tables.... " "`dirname $0`/drupalDBQuery.sh" -quiet clearcache "${targetInstall}" "${pTargetRootDir}" "`dirname $0`/drupalDBQuery.sh" -quiet clearsessions "${targetInstall}" "${pTargetRootDir}" echo "done." # Reset admin password on target # (until we do this, the admin username is the same as the source site's which is against our convention.) echo -n "Resetting admin password of target install.... " "`dirname $0`/drupalDBQuery.sh" -quiet resetadmin "${targetInstall}" "${pTargetRootDir}" echo "done." # Perform content reset tasks if [ -z "${pNoreset}" ]; then echo -n "Performing content reset tasks.... " cookiesFile="`loginToSiteAsAdmin "${targetInstall}" "${pTargetRootDir}"`" if [ -n "${cookiesFile}" -a -f "${cookiesFile}" ]; then downloadPage "${targetInstall}" "admin/build/themes" "${cookiesFile}" > /dev/null downloadPage "${targetInstall}" "admin/build/modules" "${cookiesFile}" > /dev/null rm -f "${cookiesFile}" echo "done." else echo "** Unable to log into site to perform reset tasks. Continuing." # Set flag as if we didn't want to do this in the first place. pNoreset="-noreset" fi fi # Reset permissions on target install echo -n "Resetting permissions of target install.... " "`dirname $0`/drupalSetPerms.sh" "${targetInstall}" "${pTargetRootDir}" echo "done." # done echo -e "\n** Remember: in addition to possible follow-ups from the permissions reset, do the following:" if [ -n "${pNoreset}" ]; then echo -e "\n** Perform content reset actions on the target installation:" echo -e "\tFirst, login: http://${targetInstall}/user" "`dirname $0`/drupalReport.sh" admin "${targetInstall}" "${pTargetRootDir}" | while read output; do echo -e "\t\t${output}" done echo -e "\tReset theme by visiting: http://${targetInstall}/admin/build/themes" echo -e "\tRebuild menus by visiting: http://${targetInstall}/admin/build/modules" fi echo -e "\n** After these are complete, perform a database dump and" echo -e "\tsearch for any remaining instances of the old site name, fixing as you go." echo -e "\tWhen this is complete, you can the symbolic link in the target's site directory:" echo -e "\t\trm ${pTargetRootDir}/${targetBaseName}/sites/${sourceInstall}" echo -e "\n** Done."