Skip to content

Instantly share code, notes, and snippets.

@ehowe
Created July 10, 2012 13:14
Show Gist options
  • Save ehowe/3083162 to your computer and use it in GitHub Desktop.
Save ehowe/3083162 to your computer and use it in GitHub Desktop.
automigrate
#!/bin/bash
clear
unalias ls 2> /dev/null
#
# The next section is only functions that are called in other parts of the script
#
# THIS FUNCTION IS CURRENTLY BROKEN!
#errorcheck () {
# This function checks the exit status of every other command run in the script
#`$@`
#if [[ $? != 0 ]];
#then
#SUBLOOP=0
#while [ $SUBLOOP -eq 0 ];
#do
#echo -n "$1 had an error. Would you like to continue? "
#read ERRORCHECK
#case $ERRORCHECK in
#yes)
#SUBLOOP=1
#;;
#no)
#exit 1;
#;;
#*)
#echo "Please enter 'yes' or 'no'"
#SUBLOOP=0
#;;
#esac
#done
#fi
#}
scripthelp () {
echo -e "Automigrate.sh Help: \n"
echo "This script can only be run on the server you are migrating from."
echo -e "Its goal is to make migrations as automated as possible. \n"
echo -e "Usage: \n"
echo "sh automigrate.sh [-o [1-9]] [-p PORT] [-i IP] [-u USER] [-h]"
echo "Choose the appropriate option from the menu."
echo "In most cases this will be option 1, unless "
echo "there are already accounts on the server you"
echo "are migrating to. If this is the case, "
echo "option 2 is for you. You can also choose one "
echo -e "of the specialized options if you would like. \n"
echo "Options:"
echo -e "-h\t\tDisplay this help message"
echo -e "-o\t\tWhich option in the menu you would like"
echo -e "-i\t\tIP you are migrating to"
echo -e "-u\t\tUser on the remote server"
echo -e "-p\t\tPort for SSH"
echo -e "-P\t\tPassword for Destination"
echo -e "-v\t\tView available menu options"
exit 0
}
serverinfo () {
# Read Server Information
SUBLOOP=0
while [ $SUBLOOP -eq 0 ];
do
if [ -z $IP ]; then
echo -n "Remote server IP address: "
read IP
fi
SUBLOOP=1
# IP is required
if [ -z $IP ]; then
echo "IP is required!"
sleep 1
SUBLOOP=0
else
validip
fi
#Find User
if [ -z $RUSER ]; then
echo -n "Remote User [root]: "
read RUSER
fi
#Get SSH Port
if [ -z $PORT ]; then
echo -n "SSH Port [22]: "
read PORT
fi
#Get Server password
if [ -z $RPASS ]; then
echo -n "Destination Server Password: "
read RPASS
SUBLOOP=1
fi
#Password is required
if [ -z $RPASS ]; then
echo "Destination Password Required!"
SUBLOOP=0
fi
# Assign port 22 if no value was assigned
if [ -z $PORT ]; then
echo "No port given, assuming 22"
sleep 1
PORT=22
fi
# Assume root user if none was given
if [ -z $RUSER ]; then
echo "No user given, assuming root"
sleep 1
RUSER=root
fi
done
}
passwordlogin () {
KEY=`cat /root/.ssh/id_rsa.pub`
expect_output=$(expect -c "
send_user \"connecting to $IP\n\"
spawn ssh -o StrictHostKeyChecking=no $RUSER@$IP
#login handles cases:
# login with keys (no user/pass)
# user/pass
# login with keys (first time verification)
expect {
\"> \" { }
\"$ \" { }
\"assword: \" {
send \"$RPASS\n\"
expect {
\"> \" { }
\"$ \" { }
\"# \" { }
}
}
default {
send_user \"Login failed\n\"
exit
}
}
send \"mkdir -p ~/.ssh\n\"
expect {
\"> \" {}
\"# \" {}
default {}
}
send \"echo $KEY >> ~/.ssh/authorized_keys\n\"
expect {
\"> \" {}
\"# \" {}
default {}
}
send \"exit\n\"
expect {
\"> \" {}
\"# \" {}
default {}
}
send_user \"finished\n\"
")
echo "$expect_output"
}
validip () {
valid=1
count=0
for field in $(echo "$IP" | cut -d. --output-delimiter=$'\012' -f1-); do
count=$[count+1]
if [ "$field" -eq $[field+0] -a "$field" -le 256 -a "$field" -ge 0 ]; then
: yay
else
valid=0
fi
done
if [ "$valid" -a "$count" -eq 4 ]; then
echo "Valid IP address!"
else
echo "Invalid IP address!"
SUBLOOP=0
fi
}
sshkeys () {
# Generate SSH keys
if ! [ -f ~/.ssh/id_rsa ]
then ssh-keygen -t rsa -q -N "" -f ~/.ssh/id_rsa
fi
}
matchsoftware () {
# Matches easyapache config and grabs customer package and feature lists
REMOTECPANEL=`ssh -p $PORT $RUSER@$IP 'cat /var/cpanel/cpanelsync/repoversions/cpanel | cut -d "." -f1,2'`
NEEDEDCPANEL=11.25
if [[ $REMOTECPANEL < $NEEDEDCPANEL ]]; then
ssh -p$PORT $RUSER@$IP 'sed -i -e "s/CPANEL=.*/CPANEL=current/g" /etc/cpupdate.conf; /scripts/upcp --force'
fi
rsync -avHle "ssh -p$PORT" /var/cpanel/easy/apache/ $RUSER@$IP:/var/cpanel/easy/apache/
rsync -avHle "ssh -p$PORT" /var/cpanel/packages/ $RUSER@$IP:/var/cpanel/packages/
rsync -avHle "ssh -p$PORT" /var/cpanel/features/ $RUSER@$IP:/var/cpanel/features
}
mysqlversions () {
# Downgrades mysql
REMOTEMYSQL=`ssh -p$PORT $RUSER@$IP 'mysql --version'|grep mysql|cut -d ' ' -f6|cut -d ',' -f1|cut -d 'a' -f1|awk -F"." '{print $1"."$2}'`
LOCALMYSQL=`mysql --version|grep mysql|cut -d ' ' -f6|cut -d ',' -f1|cut -d 'a' -f1|awk -F"." '{print $1"."$2}'`
# if [[ $REMOTEMYSQL != $LOCALMYSQL ]]; then
# ssh -p$PORT $RUSER@$IP "for each in cphulkd eximstats horde leechprotect modsec roundcube; do mysqldump --compatible=mysql40 $each > $each.sql; done"
# ssh -p$PORT $RUSER@$IP "mysql -e 'drop database horde'; mysql -e 'drop database roundcube'"
# ssh -p$PORT $RUSER@$IP "perl -pi -e 's/mysql-version=.*/mysql-version=$LOCALMYSQL/' /var/cpanel/cpanel.config"
# ssh -p$PORT $RUSER@$IP '/scripts/mysqlup --force'
# ssh -p$PORT $RUSER@$IP 'for each in horde roundcube; do mysql -e "create database $each"; done'
# ssh -p$PORT $RUSER@$IP 'for each in horde roundcube cphulkd eximstats leechprotect modsec; do mysql $each < $each.sql; done'
# fi
if [[ $REMOTEMYSQL > $LOCALMYSQL ]]; then
echo "The versions of MySQL do not match"
echo "Please correct this and run the script again"
exit 1
fi
}
easyapache () {
#Runs easyapache
ssh -p$PORT $RUSER@$IP '/scripts/easyapache --build'
}
skiphomedir () {
#Checks to see if skiphomedir is valid switch to pkgacct
SKIPHOMEDIR=`cat /scripts/pkgacct|grep 'skiphomedir'`
if [[ -z $SKIPHOMEDIR ]]; then
echo "/scripts/pkgacct does not accept --skiphomedir"
echo "You must update cpanel to use this script"
exit 1
fi
}
pkgacctloop () {
# Packages accounts --skiphomedir and scps the results to the remote server
mysql -e 'show databases;'
if [[ $? != 0 ]];
then
SUBLOOP=0
while [ $SUBLOOP -eq 0 ];
do
echo "MySQL is not functioning correctly"
echo -n "Would you like to continue? "
read SQLERR
case $SQLERR in
yes)
SUBLOOP=1;
;;
no)
exit 1;
;;
*)
echo "You must enter 'yes' or 'no'"
SUBLOOP=0
;;
esac
done
fi
> /home/dedips.txt
> /home/didnotrestore.txt
MAINIP=`cat /etc/wwwacct.conf|grep ADDR|awk '{print $2}'`
for DEDIPACCT in `ls -A /var/cpanel/users/`; do if [[ $MAINIP != `grep IP /var/cpanel/users/$DEDIPACCT|cut -d '=' -f2` ]]; then if [[ $DEDIPACCT != system ]]; then echo $DEDIPACCT >> /home/dedips.txt; fi; fi; done
for RUSERS in `ls -A /var/cpanel/users | grep -vf /home/dedips.txt`; do echo $RUSERS >> /home/sharedips.txt; done
for RUSERS in `ls -A /var/cpanel/users`; do /scripts/pkgacct --skiphomedir $RUSERS /home cpmove nocompress; done
ls -A /var/cpanel/users > /home/users.txt
scp -P$PORT /home/cpmove-*.tar $RUSER@$IP:/home
scp -P$PORT /home/dedips.txt $RUSER@$IP:/home
scp -P$PORT /home/sharedips.txt $RUSER@$IP:/home
ssh -p$PORT $RUSER@$IP '> /home/didnotrestore.txt; mkdir /home/cprestoretemp; for RUSERS in `cat /home/dedips.txt`; do mv /home/cpmove-$RUSERS.tar /home/cprestoretemp; /scripts/restorepkg --ip=y /home/cprestoretemp/cpmove-$RUSERS.tar; mv /home/cprestoretemp/cpmove-$RUSERS.tar /home; if ! [ -f /var/cpanel/users/$RUSERS ]; then echo $RUSERS >> /home/didnotrestore.txt; fi; done'
ssh -p$PORT $RUSER@$IP 'cat /home/didnotrestore.txt' >> /home/didnotrestore.txt
if [ ! -s /home/didnotrestore.txt ]; then
echo "All users restored successfully"
RESTORED=1
else
echo "The following users did not restore"
cat /home/didnotrestore.txt
RESTORED=0
fi
if [ $RESTORED == 0 ]; then
echo -n "Would you like to continue? (Failed accounts will not rsync data) (y/n) "
read CONTINUE
case $CONTINUE in
y) ;;
n) exit ;;
*) echo "Invalid input. Not continuing."; exit ;;
esac
fi
ssh -p$PORT $RUSER@$IP 'for RUSERS in `cat /home/sharedips.txt`; do if [ ! -d "/home/cprestoretemp" ]; then mkdir /home/cprestoretemp; fi; mv /home/cpmove-$RUSERS.tar /home/cprestoretemp; /scripts/restorepkg /home/cprestoretemp/cpmove-$RUSERS.tar; mv /home/cprestoretemp/cpmove-$RUSERS.tar /home; done'
for SYNC in `cat /home/dedips.txt | grep -vf /home/didnotrestore.txt`; do rsync -avHle "ssh -p$PORT" /home/$SYNC/ $RUSER@$IP:/home/$SYNC/ --progress; done
for SYNC in `cat /home/sharedips.txt`; do rsync -avHle "ssh -p$PORT" /home/$SYNC/ $RUSER@$IP:/home/$SYNC/ --progress; done
ssh -p$PORT $RUSER@$IP 'cp /usr/local/apache/conf/httpd.conf /usr/local/apache/conf/httpd.conf.bak`date +%Y%m%d`; /scripts/rebuildhttpdconf; /etc/init.d/httpd stop; sleep 2; /etc/init.d/httpd startssl;'
}
nolocaldns () {
# Checks for list of domains that are using external nameservers
counter=1
for ns in `cat /etc/nameserverips | cut -d '=' -f2`; do
nsarray[$counter]=`echo $ns | tr "[:upper:]" "[:lower:]"`
counter=`expr $counter + 1`
done
for domain in `cat /etc/userdomains | grep -v \* | cut -d ':' -f1 | egrep "^[a-zA-Z0-9]([-]?[a-zA-Z0-9])+\.[a-z]{2,9}$"`; do
nameserver=`dig NS $domain | sed -r -n "/IN\sNS/p" | grep -v "^;" | head -1 | awk '{print $5}' | sed 's/.$//' | tr "[:upper:]" "[:lower:]"`
for (( i=1; i <= ${#nsarray[@]}; i++ )); do
if [[ ${nsarray[$i]} == $nameserver ]]; then
hasnameserver=1
fi
done
if [[ $hasnameserver -ne 1 ]]; then
echo $domain >> /root/not_local_dns.txt
fi
hasnameserver=0
done
echo "Please check /root/not_local_dns.txt for list of domains not using local DNS"
sleep 2
}
premigrate () {
sed -i.lwbak -e 's/14400/300/g' -e 's/86400/300/g' -e "s/[0-9]\{10\}/`date +%Y%m%d%H`/g" /var/named/*.db
}
rsyncupgrade () {
#Optional function to upgrade rsync to V 3.0
LOCALCENT=`cat /etc/redhat-release |awk '{print $3}'|cut -d '.' -f1`
REMOTECENT=`ssh -p$PORT $USER@$IP "cat /etc/redhat-release" |awk '{print $3}'|cut -d '.' -f1`
LOCALARCH=`uname -i`
REMOTEARCH=`ssh -p$PORT $USER@$IP "uname -i"`
rpm -Uvh http://migration.sysres.liquidweb.com//rsync/rsync-3.0.0-1.el$LOCALCENT.rf.$LOCALARCH.rpm
ssh -p$PORT $USER@$IP "rpm -Uvh http://migration.sysres.liquidweb.com/rsync/rsync-3.0.0-1.el$REMOTECENT.rf.$REMOTEARCH.rpm"
}
menuoptions () {
echo "This should ONLY be run on the server you are migrating FROM!"
echo ""
echo "Please select the type of migration from the list below"
echo "1) Full Initial Migration"
echo "2) Initial Migration (No Software Version Matching)"
echo "3) Single account migration (Shared to VPS/Dedicated)"
echo "4) Match software versions only"
echo "5) Upgrade rsync"
echo "0) Exit"
}
#
# Take care of some options before starting script
#
# o=Option for Loop
# h=server you are migrating to
# u=user for remote server
# p=port
# v=view options
optstr=o:i:u:p:P:hv
while getopts $optstr var
do
case $var in
o) STATUS=$OPTARG ;;
i) IP=$OPTARG ;;
u) RUSER=$OPTARG ;;
p) PORT=$OPTARG ;;
P) RPASS="$OPTARG" ;;
h) scripthelp ;;
v) menuoptions; exit ;;
esac
done
#
# Start script
#
# Start while loop for fault tolerance
LOOP=0
while [ $LOOP == 0 ] ;
do
# Prompt the admin with some choices for the appropriate stage
# of the migration.
if [ -z $STATUS ]; then
menuoptions
echo -n "Please enter your choice: "
read STATUS
fi
case $STATUS in
1) # This executes the initial Migration
source ~/.bash_profile
skiphomedir
serverinfo
sshkeys
passwordlogin
rsyncupgrade
sed -i -e 's/export\ RPASS.*//' ~/.bash_profile
premigrate
nolocaldns
matchsoftware
mysqlversions
easyapache
pkgacctloop
echo "Domains not using Local Nameservers"
cat /root/not_local_dns.txt
echo "Migration Complete"
LOOP=1
;;
2) #Initial migration with no software version matching
source ~/.bash_profile
skiphomedir
serverinfo
sshkeys
passwordlogin
rsyncupgrade
premigrate
sed -i -e 's/export\ RPASS.*//' ~/.bash_profile
nolocaldns
pkgacctloop
echo "Domains not using Local Nameservers"
cat /root/not_local_dns.txt
echo "Migration Complete"
LOOP=1
;;
3) #Shared to VPS/Dedicated
skiphomedir
serverinfo
sshkeys
passwordlogin
SUBLOOP=0
while [ $SUBLOOP -eq 0 ];
do
echo -n "Domain name to be migrated (without www): "
read DOMAIN
echo "DNS will need to be updated for $DOMAIN at the nameservers!"
SHARED=`cat /etc/trueuserdomains|grep ^$DOMAIN|cut -d ' ' -f2|uniq`
SUBLOOP=1
if [ -z $SHARED ]
then
echo "That domain does not exist on the server"
sleep 2
clear
SUBLOOP=0
fi
done
echo "The account has the following subdomains/addon\n domains configured that should be accounted for as well:\n"
echo "Outputting addon domains to /root/addon_domains.txt"
cat /etc/userdomains|grep $SHARED|cut -d ':' -f1|grep -v $DOMAIN > /root/addon_domains.txt
cat /root/addon_domains.txt
# Sleep for a few
NAP=10
while [ $NAP -eq 10 ] ;
do
echo -n "Continuing in 10..."
let NAP=$NAP-1
sleep 1
done
while [ $NAP -gt 1 ] ;
do
echo -n "$NAP..."
let NAP=$NAP-1
sleep 1
done
while [ $NAP -eq 1 ] ;
do
echo "$NAP"
sleep 1
let NAP=$NAP-1
done
/scripts/pkgacct --skiphomedir $SHARED
scp -P$PORT /home/cpmove-$SHARED.tar.gz $RUSER@$IP:/home/
scp -P$PORT /home{1..9}/cpmove-$SHARED.tar.gz $RUSER@$IP:/home/
ssh -p$PORT $RUSER@$IP "/scripts/restorepkg $SHARED"
rsync -avHle "ssh -p$PORT" /home/$SHARED/ $RUSER@$IP:/home/$SHARED --progress --exclude=mail/new --exclude=mail/cur
LOOP=1
;;
4) #Match software versions
#Runs the 4 functions to gather info, set up ssh keys, rsync software, and run easyapache
serverinfo
sshkeys
passwordlogin
matchsoftware
easyapache
LOOP=1
;;
5)
serverinfo
sshkeys
passwordlogin
rsyncupgrade
LOOP=1
;;
0) #Exit Gracefully
exit 0;
;;
*) # Default
echo "Not a valid choice"
sleep 1
clear
esac
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment