【原创】一个shell脚本记录(实现rsync生产文件批量迁移功能)

#!/bin/bash
#Date:2018-01-08
#Author:xxxxxx
#Function:xxxxxx
#Change:2018-01-17
#

#设置忽略CTRL+C信号
trap 'my_exit;exit' SIGINT SIGTERM SIGQUIT

#开启DEBUG模式
#set -x

#如果有命令执行返回值为非0,那么脚本将结束,不再继续执行
# set -e

#导入rsync使用的密码
export RSYNC_PASSWORD='xxxxxx'

#设置脚本涉及的目录变量
pathdir=$(cd $(dirname $0);pwd)
#源主机同步到本机的临时目录
tmpdir='/data/migrate_tmp'
# tmpdir='/data/migrate_tmp/tmp'		#测试用
#管理机
domain_m=("cms.domain.com" "pic.domain.com")
youxi_m=("/data1/www/abc.test.com" "/data1/www/pic.domain.com")
# youxi_m=("/data/migrate_tmp/abc.test.com" "/data/migrate_tmp/pic.domain.com")	#测试用
#模板机
domain_t='cms.domain.com'
youxi_t='/data2/www/abc.test.com'
#web机
domain_web=''
youxi_web='/data/webapps'
#youxi_web='/data/migrate_tmp/webapps'	#测试用
#图片机
domain_pic='pic.domain.com'
youxi_pic='/data/webapps/pic.domain.com'

#判断临时目录是否存在,若不存在则创建
[ -d ${tmpdir} ] && rm -rf ${tmpdir}/* || mkdir -p ${tmpdir}

#备份目录
# [ -d /data/fabuqi_bak ] && mkdir /data/fabuqi_bak

#进入到脚本所在的目录
cd ${pathdir}

#定义grep查找需要替换的文件列表正则
grep_re="img.dwstatic.com|img[1-5].dwstatic.com|pic[1-5].domain.com|pic[0-5]1.domain.com|public.domain.com|pic.domain.(com|cn)"

#trap的执行函数
function my_exit(){
	echo trap_handle_time: $(date "+%Y-%m-%d %H:%M:%S")
	echo "exit"
}

#脚本使用说明函数
function usage(){
	echo "Usage: $0 [OPTIONS]"
	echo "   - Here to display help info ."
	echo "   - The args is only two ."
	echo "   - OPTIONS: [ all | zhuanqu_ID | 专区ID ] ."
	echo "   example: /bin/bash migrate.sh zxyzxy "
	exit 1
}

#logger function
function log_info(){
	DATA_N=$(date "+%Y-%m-%d %H:%M:%S")
	USER_N=$(whoami)
	echo "${DATA_N} ${USER_N} execute $0 [INFO] $@" | tee -a ${pathdir}/migrate.log
}

#配置变量函数,sync_dir是同步的源主机子目录,destdir是新发布器目标目录。
function config_and_rsync_single(){
	#从源主机的哪个机器同步数据
	rsync_from=${2}
	#目标同步的目录
	if [[ "${rsync_from}" == "xxx.xxx.xxx.xxx" ]]; then
		#拉取单个专区文件资源,保留文件时间属性
		for i in `seq 0 $(expr ${#domain_m[*]} - 1)`
		do
			log_info "set the sync_dir and destdir value ..."
			sync_dir=${domain_m[$i]}
			destdir=${youxi_m[$i]}
			#备份目录
			log_info "backup the destdir ..."
			cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

			#将目标目录拷贝到临时目录,如果临时目录已经存在,就直接拷贝文件,如果不存在就创建临时目录在拷贝目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
			log_info "create tmpdir ..."
			[ -d ${tmpdir}/${sync_dir} ] && cp -rpvu ${destdir}/* ${tmpdir}/${sync_dir} 2>>${pathdir}/migrate.log || mkdir -p ${tmpdir}/${sync_dir} && cp -rpvu ${destdir}/* ${tmpdir}/${sync_dir} 2>>${pathdir}/migrate.log

			log_info "Start to get ${1} files ......"
			rsync -avuzt game_test@${rsync_from}::game_test/${sync_dir}/${1} ${tmpdir}/${sync_dir} | tee -a ${pathdir}/migrate.log
			log_info "Start to execute update_single_id function ......"
			update_single_id ${tmpdir}/${sync_dir} ${1} ${destdir}
		done
		log_info "建立专区对应的软连接 ..."
		ln -nfs /data1/www/abc.test.com/${id} /data1/webapps/${id}.domain.com 2>>${pathdir}/migrate.log
		chown -R www-data:www-data /data1/webapps/${id}.domain.com
	elif [[ "${rsync_from}" == "xxx.xxx.xxx.xxx" ]]; then
		log_info "set the sync_dir and destdir value ..."
		sync_dir=${domain_t}
		destdir=${youxi_t}
		#备份目录
		log_info "backup the destdir ..."
		cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

		#将目标目录拷贝到临时目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
		log_info "create tmpdir ..."
		cp -rpvu ${destdir}/* ${tmpdir} 2>>${pathdir}/migrate.log

		log_info "Start to get ${1} files ......"
		rsync -avuzt game_test@${rsync_from}::game_test/${sync_dir}/${1} ${tmpdir}/ | tee -a ${pathdir}/migrate.log
		log_info "Start to execute update_single_id function ......"
		update_single_id ${tmpdir} ${1} ${destdir}
		log_info "建立专区对应的软连接 ..."
		ln -snf ${destdir}/${id} /data/data1/www/abc.test.com/${id}.domain.com 2>>${pathdir}/migrate.log
		chown -R www-data:www-data /data/data1/www/abc.test.com/${id}.domain.com
	elif [[ "${rsync_from}" == "xxx.xxx.xxx.xxx" ]]; then
		log_info "set the sync_dir and destdir value ..."
		sync_dir=${domain_web}
		destdir=${youxi_web}
		#备份目录
		log_info "backup the destdir ..."
		cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

		#将目标目录拷贝到临时目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
		log_info "create tmpdir ..."
		cp -rpvu ${destdir}/* ${tmpdir} 2>>${pathdir}/migrate.log

		log_info "Start to get ${1} files ......"
		rsync -avuzt game_test@${rsync_from}::game_test/${1}.domain.com ${tmpdir}/ | tee -a ${pathdir}/migrate.log
		log_info "Start to execute update_single_id function ......"
		update_single_id ${tmpdir} ${1}.domain.com ${destdir}

		log_info "Start to backup ${1} nginx configure file......"
		[ -d /data/services/nginx_vhost_bak ] || mkdir -p /data/services/nginx_vhost_bak
		cp -pvu /data/services/nginx_vhost/${1}.*.conf /data/services/nginx_vhost_bak/ 2>>${pathdir}/migrate.log
		log_info "Start to rsync ${1} nginx configure file ......"
		rsync -avuzt game_test@${rsync_from}::nginx_test/${1}.*.conf /data/services/nginx_vhost/
		log_info "update the ${1} nginx conf,please to reload nginx service by manual ..."
		# service nginx reload
	else
		log_info "set the sync_dir and destdir value ..."
		sync_dir=${domain_pic}
		destdir=${youxi_pic}
		#备份目录
		log_info "backup the destdir ..."
		cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

		#将目标目录拷贝到临时目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
		log_info "create tmpdir ..."
		cp -rpvu ${destdir}/* ${tmpdir} 2>>${pathdir}/migrate.log

		log_info "Start to get ${1} files ......"
		rsync -avuzt game_test@${rsync_from}::game_test/${sync_dir}/${1} ${tmpdir}/ | tee -a ${pathdir}/migrate.log
		log_info "Start to execute update_single_id function ......"
		update_single_id ${tmpdir} ${1} ${destdir}
	fi
}

#迁移单个专区函数
function update_single_id(){
	_tmpdir=${1}
	id=${2}
	_destdir=${3}
	cd ${_tmpdir}
	log_info "replace contexts in the files that in the ${id} directory ..."
	#判断目录是否为空
	if [ "`ls -A ${_tmpdir}/${id}`" = "" ]; then
		log_info "the ${id} is indeed empty."
	#判断目录及其子目录是否为空
	elif [ "`find ${_tmpdir}/${id}/* -type f`" = "" ]; then
		log_info "the ${id} and subdir are empty."
	#判断是否有文件需要做内容替换
	elif [ "`grep -rEl ${grep_re} ${_tmpdir}/${id}/*`" = "" ]; then
		log_info "the ${id} not files need to replace."
	#不为空时执行修改文件内容操作
	else
		log_info "Start to sed ......"
		sed -i -e 's/img.dwstatic.com/img.game.dwstatic.com/g' 
		-e 's/img(.).dwstatic.com/img1.game.dwstatic.com/g' 
		-e 's/pic(.).domain.com/img1.game.dwstatic.com/g' 
		-e 's/pic01.domain.com/img.game.dwstatic.com/g' 
		-e 's/pic(.)(.).domain.com/img1.game.dwstatic.com/g' 
		-e 's/public.domain.com/publicgame.domain.com/g' 
		-e 's/pic.domain.(com|cn)/img.game.dwstatic.com/g' $(grep -rEl ${grep_re} ${_tmpdir}/${id}/*)
	fi

	if [ -d ${_destdir}/${id} ];then
		log_info "the ${id} is a exist id,backup old ${id} dirs ..."
		[ -d /data/fabuqi_bak/${id}_bak ] && log_info "the ${id}_bak is exist,not need to backup ..." || cp -rfp ${_destdir}/${id} /data/fabuqi_bak/${id}_bak
		log_info "replace old ${id} dirs by new ${id} dirs ..."
		#同步专区目录到新发布器目标目录中,只会在源文件的更改时间较目标文件更新时或是目标文件并不存在时,才复制文件,保留文件时间属性
		cp -rpvu ${_tmpdir}/${id}/* ${_destdir}/${id}/ | tee -a ${pathdir}/migrate.log
		chown -R www-data:www-data ${_destdir}/${id}
	else
		log_info "the ${id} is a new id,not to backup."
		#同步专区目录到新发布器目标目录中
		cp -rpvu ${_tmpdir}/${id} ${_destdir}/${id} | tee -a ${pathdir}/migrate.log
		chown -R www-data:www-data ${_destdir}/${id}
	fi

	log_info "update_single_id task done."
}

#配置变量函数,sync_dir是同步的源主机子目录,destdir是新发布器目标目录。
function config_and_rsync_all(){
	#从源主机的哪个机器同步数据
	rsync_from=${1}
	#目标同步的目录
	if [[ "${rsync_from}" == "xxx.xxx.xxx.xxx" ]]; then
		#拉取所有专区文件资源,保留文件时间属性
		for i in `seq 0 $(expr ${#domain_m[*]} - 1)`
		do
			log_info "set the sync_dir and destdir value ..."
			sync_dir=${domain_m[$i]}
			destdir=${youxi_m[$i]}
			#备份目录
			log_info "backup the destdir ..."
			cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

			#将目标目录拷贝到临时目录,如果临时目录已经存在,就直接拷贝文件,如果不存在就创建临时目录在拷贝目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
			log_info "create tmpdir ..."
			[ -d ${tmpdir}/${sync_dir} ] && cp -rpvu ${destdir}/* ${tmpdir}/${sync_dir} || mkdir -p ${tmpdir}/${sync_dir} && cp -rpvu ${destdir}/* ${tmpdir}/${sync_dir}

			log_info "Start to get ${sync_dir} all files ......"
			rsync -avuzt game_test@${rsync_from}::game_test/${sync_dir}/* ${tmpdir}/${sync_dir} | tee -a ${pathdir}/migrate.log
			log_info "Start to execute update_all_id ${sync_dir} function ......"
			update_all_id ${tmpdir}/${sync_dir} ${destdir}
		done
		for id in $(ls ${tmpdir}/${domain_m[0]})
		do
			log_info "建立专区对应的软连接 ..."
			ln -nfs /data1/www/abc.test.com/${id} /data1/webapps/${id}.domain.com
			chown -R www-data:www-data /data1/webapps/${id}.domain.com
		done
	elif [[ "${rsync_from}" == "xxx.xxx.xxx.xxx" ]]; then
		log_info "set the sync_dir and destdir value ..."
		sync_dir=${domain_t}
		destdir=${youxi_t}
		#备份目录
		log_info "backup the destdir ..."
		cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

		#将目标目录拷贝到临时目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
		log_info "create tmpdir ..."
		cp -rpvu ${destdir}/* ${tmpdir}/

		log_info "Start to get all files ......"
		rsync -avuzt game_test@${rsync_from}::game_test/${sync_dir}/* ${tmpdir}/ | tee -a ${pathdir}/migrate.log
		log_info "Start to execute update_all_id function ......"
		update_all_id ${sync_dir} ${destdir}
		for id in $(ls ${tmpdir}/${sync_dir})
		do
			log_info "建立专区对应的软连接 ..."
			ln -snf ${destdir}/${id} /data/data1/www/abc.test.com/${id}.domain.com
			chown -R www-data:www-data /data/data1/www/abc.test.com/${id}.domain.com
		done
	elif [[ "${rsync_from}" == "xxx.xxx.xxx.xxx" ]]; then
		log_info "set the sync_dir and destdir value ..."
		sync_dir=${domain_web}
		destdir=${youxi_web}
		#备份目录
		log_info "backup the destdir ..."
		cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

		#将目标目录拷贝到临时目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
		log_info "create tmpdir ..."
		cp -rpvu ${destdir}/* ${tmpdir}/

		log_info "Start to get all files ......"
		rsync -avuzt game_test@${rsync_from}::game_test/* ${tmpdir}/ | tee -a ${pathdir}/migrate.log
		log_info "Start to execute update_all_id function ......"
		update_all_id ${sync_dir} ${destdir}

		log_info "Start to backup all nginx configure file......"
		cp -r /data/services/nginx_vhost /data/services/nginx_vhost_bak
		log_info "Start to rsync all nginx configure file ......"
		rsync -avuzt game_test@${rsync_from}::nginx_test/* /data/services/nginx_vhost/
		log_info "update the nginx conf,please to reload nginx service by manual ..."
		# service nginx reload
	else
		log_info "set the sync_dir and destdir value ..."
		sync_dir=${domain_pic}
		destdir=${youxi_pic}
		#备份目录
		log_info "backup the destdir ..."
		cp -rp ${destdir} ${destdir}_`date "+%Y%m%d%H%M%S"`

		#将目标目录拷贝到临时目录,为了保证sed处理之后文件时间改变不影响覆盖目标目录,所以将目标目录拷贝到临时目录处理之后再覆盖到目标目录中。
		log_info "create tmpdir ..."
		cp -rpvu ${destdir}/* ${tmpdir}/

		log_info "Start to get all files ......"
		rsync -avuzt game_test@${rsync_from}::game_test/${sync_dir}/* ${tmpdir}/ | tee -a ${pathdir}/migrate.log
		log_info "Start to execute update_all_id function ......"
		update_all_id ${sync_dir} ${destdir}
	fi
}

#批量迁移所有专区的函数
function update_all_id(){
	_tmpdir=${1}
	_destdir=${2}
	cd ${_tmpdir}
	for id in $(ls ${_tmpdir}/)
	do
		if [[ ${id} == "ssss" || ${id} == "testsslj" ]]; then
			log_info "skip the ${id}."
		elif [[ -f ${_tmpdir}/${id} ]]; then
			log_info "the ${_tmpdir}/${id} is a file,not dir,please check it and sync by manual."
		else
			log_info "migrate ${id} start..."
			cd ${_tmpdir}/${id}
			log_info "replace contexts in the files that in the ${id} directory ..."
			#判断目录是否为空
			if [ "`ls -A ${_tmpdir}/${id}`" = "" ]; then
				log_info "the ${id} is indeed empty."
			#判断目录及其子目录是否为空
			elif [ "`find ${_tmpdir}/${id}/* -type f`" = "" ]; then
				log_info "the ${id} and subdir are empty."
			#判断是否有文件需要做内容替换
			elif [ "`grep -rEl ${grep_re} ${_tmpdir}/${id}/*`" = "" ]; then
				log_info "the ${id} not files need to replace."
			#不为空时执行修改文件内容操作
			else
				log_info "Start to sed ......"
				sed -i -e 's/img.dwstatic.com/img.game.dwstatic.com/g' 
				-e 's/img(.).dwstatic.com/img1.game.dwstatic.com/g' 
				-e 's/pic(.).domain.com/img1.game.dwstatic.com/g' 
				-e 's/pic01.domain.com/img.game.dwstatic.com/g' 
				-e 's/pic(.)(.).domain.com/img1.game.dwstatic.com/g' 
				-e 's/public.domain.com/publicgame.domain.com/g' 
				-e 's/pic.domain.(com|cn)/img.game.dwstatic.com/g' $(grep -rEl ${grep_re} ${_tmpdir}/${id}/*)
			fi

			if [ -d ${_destdir}/${id} ]; then
				log_info "the ${id} is a exist id,backup old ${id} dirs ..."
				[ -d /data/fabuqi_bak/${id}_bak ] && log_info "the ${id}_bak is exist,not need to backup ..." || cp -rfp ${_destdir}/${id} /data/fabuqi_bak/${id}_bak
				log_info "replace old ${id} dirs by new ${id} dirs ..."
				#同步专区目录到新发布器目标目录中,只会在源文件的更改时间较目标文件更新时或是目标文件并不存在时,才复制文件,保留文件时间属性
				cp -rpvu ${tmpdir}/${1}/${id}/* ${_destdir}/${id}/ | tee -a ${pathdir}/migrate.log
				chown -R www-data:www-data ${_destdir}/${id}
			else
				log_info "the ${id} is a new id,not to backup."
				#同步专区目录到新发布器目标目录中
				cp -rpvu ${tmpdir}/${1}/${id} ${_destdir}/${id} | tee -a ${pathdir}/migrate.log
				chown -R www-data:www-data ${_destdir}/${id}
			fi

			log_info "migrate ${id} end..."
		fi
	done
	log_info "update_all_id task done."
}

#主函数
function main(){
	domain_ip=("xxx.xxx.xxx.xxx" "xxx.xxx.xxx.xxx" "xxx.xxx.xxx.xxx" "xxx.xxx.xxx.xxx")
	youxi_ip=("xxx.xxx.xxx.xxx" "xxx.xxx.xxx.xxx" "xxx.xxx.xxx.xxx" "xxx.xxx.xxx.xxx")
	#限制执行脚本的ip,并且制定对应的新管理机从源主机管理机拉取文件,其他类型的机器一样,否则,不执行脚本。
	for index in `seq 0 $(expr ${#domain_ip[*]} - 1)`
	do
		if [ $(ifconfig | grep ${youxi_ip[$index]} | wc -l) -eq 1 ]; then
			ip=${domain_ip[$index]}
			break
		else
			ip="error_x"
			continue
		fi
	done

	if [ $# -ne 1 ]; then
		usage
	# elif [[ ${1} == "all" ]]; then
	# 	config_and_rsync_all ${2}
	elif [[ ${1} == "ssss" || ${1} == "testsslj" ]]; then
		log_info "skip the ${1}."
	else
		if [[ ${ip} == "error_x" ]]; then
			log_info "this host $(ifconfig | grep 'inet addr'|awk '{print $2}'| awk -F: '{print $2}'| grep -vE '^$' | head -1) no exist youxi_ip list,please add this ip to youxi_ip on this scripts."
		else
			config_and_rsync_single ${1} ${ip}
		fi
	fi
}

#执行主函数
main $@
原文地址:https://www.cnblogs.com/wsjhk/p/8260883.html