代码分发脚本
kevin.Zhu 发布于:2013-3-5 12:25 分类:小喇叭 有 20 人浏览,获得评论 0 条
#!/bin/bash
# Version: 1.1.0
# 代码分发:将测试机上待更新的代码分发到指定的生产节点中 zkf 2016-2-16
# version:1.0.1 2016-2-18 , 完善对备份操作的文件检测 增加帮助选项 版本列表选项
# version:1.0.2 2016-2-19 , 增加备份、分发的提示信息
# version:1.1.0 2016-2-19 19:24:19 , 合并了多个项目,使脚本可以完成多项目的分发任务
# 代码分发前会对需要更新的代码先做备份
# 每次分发会产生一个版本号,版本号从 1开始
# 版本号和对应的分发时间会生成日志文件
# 备份的代码会自动保存到 版本号-1的目录中(如当前版本号为1,则备份目录为 v0)
# ***************** 配置项,这里不需要定义 下方集中定义****************
#项目名称
proj_name=''
#需要分发的节点
hosts=('172.16.7.213' '172.16.18.237')
#hosts=('172.16.9.151')
#备份文件源(使用哪个节点的文件做备份)
bak_source_host='172.16.7.213'
#分发路径前缀,如果不为数组 则所有节点相同; 否则必须定义为数组且和节点数组一一对应
#2个及2个以上才定义成数组 (暂未实现)
#file_path_pre=('/mydata1/www/' '/mydata1/www/')
file_path_pre='/mydata1/www/app186.sunyoupai.com/'
#分发文件列表
up_lst_file="/root/tool/publish_laba.lst"
#备份路径
bak_path="/root/tool/publish_bak/"
#版本记录文件 - 记录格式:版本号 分发时间
#如: 1 2016-2-17 ,表示: 版本为1 分发时间为2016-2-17
ver_file="/root/tool/publish.version"
#回退版本号, 只能回退到当前版本以前的版本
back_version=''
#v回退版本号 back_version
opt_version=''
lst_version=''
while getopts "v:t:hl" arg ; do
case $arg in
v)
opt_version=$OPTARG
;;
t)
proj_name=$OPTARG
;;
h)
echo "=================================== 帮助信息 ==================================="
echo "v:指定回退版本号,t:项目名称,l:列出版本号列表"
exit
;;
l)
lst_version='ok'
;;
?)
echo "存在未知参数, 有效参数为 v t hl" ; exit;
;;
esac
done
if [ -z "$proj_name" ]; then
echo "请指定项目名称" ; exit;
fi
# ************************** 此处集中定义所有配置 ********************
if [ "$proj_name" = "laba" ]; then
hosts=('172.16.7.213' '172.16.18.237')
bak_source_host='172.16.7.213'
file_path_pre='/mydata1/www/app186.sunyoupai.com/'
up_lst_file="/root/tool/publish_laba.lst"
bak_path="/root/tool/publish_bak/"
ver_file="/root/tool/publish.version"
elif [ "$proj_name" = "laba" ]; then
hosts=('172.16.7.213' '172.16.18.237')
bak_source_host='172.16.7.213'
file_path_pre='/mydata1/www/app186.sunyoupai.com/'
up_lst_file="/root/tool/publish_laba.lst"
bak_path="/root/tool/publish_bak/"
ver_file="/root/tool/publish.version"
else
echo "未定义的项目名" ; exit;
fi
#回退版本文件路径, 默认设置为当前备份路径
back_version_path="$bak_path"
back_version="$opt_version"
# ************************** 此处集中定义所有配置 end ********************
if [ -n "$lst_version" ]; then
echo "版本记录:$ver_file"
cat "$ver_file"
echo
echo "备份目录:$bak_path"
ls -l "$bak_path" ; exit ;
fi
# ************************************************ 函数 ******************************************
#记录更新版本号
function fun_log_version() {
ver_file=$1
back_ver=$2
hosts=$3
back_mark=''
v_info=$(tail -n 1 "$ver_file" | awk '{print $1;}')
if [ "$v_info" = "" ]; then v_info=1 ; else let "v_info = v_info + 1"; fi
tm=$(date +%Y-%m-%d_%H:%M)
if [ -n "$back_ver" ]; then
back_mark="b${back_ver}"
fi
echo "$v_info $tm \"${hosts[@]}\" $back_mark" >> $ver_file
}
# 分发指定列表中的文件
function publish_lst() {
uplst_file=$1
target_host=$2
path_pre=$3
ver_file=$4
if [ ! -f "$uplst_file" ]; then
echo "列表文件不存在"; exit;
fi
up_lst=$(cat "$uplst_file")
if [ -z "$up_lst" ]; then
echo "更新文件列表为空" ; exit;
fi
if [ -z "$target_host" ]; then
echo "目标主机不能为空"; exit;
fi
echo "$up_lst" | while read fl; do
if [ ! -d "${path_pre}${fl}" ]; then
if [ -f "${path_pre}${fl}" ]; then
rsync -aRzv ${path_pre}${fl} root@$target_host:${path_pre}${fl}
else
echo "文件不存在: ${path_pre}${fl}"
fi
fi
done
}
# 备份指定列表中的文件到本地
function bak_lst() {
uplst_file=$1
bak_path=$2
path_pre=$3
host=$4
if [ ! -f "$uplst_file" ]; then
echo "列表文件不存在,无法备份"; exit;
fi
lst=$(cat "$uplst_file")
if [ -z "$lst" ]; then
echo "文件列表为空, 程序退出" ; exit;
fi
#创建备份目录
if [ ! -d "$bak_path" ]; then
mkdir -p "$bak_path"
fi
echo "===================================== 开始备份,备份源为:$host ======================================"
echo "$lst" | while read fl; do
local_path=$(dirname ${bak_path}${path_pre}${fl})
if [ ! -d "$local_path" ]; then
mkdir -p "$local_path"
fi
if [ ! -d "${path_pre}${fl}" ]; then
rsync -aRzv root@$host:${path_pre}${fl} ${bak_path}${path_pre}${fl}
fi
done
}
# **************************************************** 主程序 **********************************************
notice='';
#设置了back_version 则为回退操作 ,否则为分发
if [ -n "$back_version" ];then
notice="回退至版本: $back_version"
if [ -n "$back_version_path" ];then
notice=${notice}", 回退路径设置为: $back_version_path"
fi
else
notice="更新列表文件设置为: $up_lst_file"
fi
echo '======================================='
echo $notice
echo '======================================='
echo
echo '是否开始操作?(y/n)'
read doit
if [ "$doit" != 'y' ] ; then
echo '已取消' ; exit ;
fi
#检查版本文件是否存在
if [ ! -f "$ver_file" ]; then
echo "找不到版本记录文件 $ver_file"; exit;
fi
#当前版本
v_info=$(tail -n 1 "$ver_file" | awk '{print $1;}')
#版本回退操作(将备份的版本文件分发)
if [ -n "$back_version" ];then
if [ -z "$v_info" ]; then
echo "没有可以回退的版本"; exit;
else
if [ "$back_version" -gt "$v_info" ] || [ "$back_version" -eq "$v_info" ]; then
echo "回退版本只能小于当前版本, 当前版本号:$v_info" ; exit;
fi
fi
back=${back_version_path}${back_version}'/'
if [ ! -d "$back" ]; then
echo "版本目录 $back 不存在" ; exit;
fi
#回退
echo '============= 开始回退 =============='
echo "回退文件在:$back "
for host in ${hosts[@]} ; do
rsync -aRzv "$back" root@$host:/
done
echo "============= 完成 =================="
fun_log_version $ver_file $back_version "${hosts[@]}"
#分发操作(将线上测试机的文件分发)
else
if [ ! -d "$bak_path" ] ; then
mkdir -p "$bak_path"
fi
for host in ${hosts[@]} ; do
#备份原文件
if [ "$host" = "$bak_source_host" ]; then
if [ "$v_info" = "" ]; then
v_info=1 ;
let "bak_v = v_info -1" ;
else
let "bak_v = v_info"
fi
#由版本号产生备份目录
bak_dir="${bak_path}${bak_v}"
#备份
bak_lst $up_lst_file $bak_dir $file_path_pre $host
fi
#更新文件
echo "=========================== 开始分发至: $host ========================="
publish_lst $up_lst_file $host $file_path_pre $ver_file
done
#记录版本号
fun_log_version $ver_file -1 "${hosts[@]}"
fi
# Version: 1.1.0
# 代码分发:将测试机上待更新的代码分发到指定的生产节点中 zkf 2016-2-16
# version:1.0.1 2016-2-18 , 完善对备份操作的文件检测 增加帮助选项 版本列表选项
# version:1.0.2 2016-2-19 , 增加备份、分发的提示信息
# version:1.1.0 2016-2-19 19:24:19 , 合并了多个项目,使脚本可以完成多项目的分发任务
# 代码分发前会对需要更新的代码先做备份
# 每次分发会产生一个版本号,版本号从 1开始
# 版本号和对应的分发时间会生成日志文件
# 备份的代码会自动保存到 版本号-1的目录中(如当前版本号为1,则备份目录为 v0)
# ***************** 配置项,这里不需要定义 下方集中定义****************
#项目名称
proj_name=''
#需要分发的节点
hosts=('172.16.7.213' '172.16.18.237')
#hosts=('172.16.9.151')
#备份文件源(使用哪个节点的文件做备份)
bak_source_host='172.16.7.213'
#分发路径前缀,如果不为数组 则所有节点相同; 否则必须定义为数组且和节点数组一一对应
#2个及2个以上才定义成数组 (暂未实现)
#file_path_pre=('/mydata1/www/' '/mydata1/www/')
file_path_pre='/mydata1/www/app186.sunyoupai.com/'
#分发文件列表
up_lst_file="/root/tool/publish_laba.lst"
#备份路径
bak_path="/root/tool/publish_bak/"
#版本记录文件 - 记录格式:版本号 分发时间
#如: 1 2016-2-17 ,表示: 版本为1 分发时间为2016-2-17
ver_file="/root/tool/publish.version"
#回退版本号, 只能回退到当前版本以前的版本
back_version=''
#v回退版本号 back_version
opt_version=''
lst_version=''
while getopts "v:t:hl" arg ; do
case $arg in
v)
opt_version=$OPTARG
;;
t)
proj_name=$OPTARG
;;
h)
echo "=================================== 帮助信息 ==================================="
echo "v:指定回退版本号,t:项目名称,l:列出版本号列表"
exit
;;
l)
lst_version='ok'
;;
?)
echo "存在未知参数, 有效参数为 v t hl" ; exit;
;;
esac
done
if [ -z "$proj_name" ]; then
echo "请指定项目名称" ; exit;
fi
# ************************** 此处集中定义所有配置 ********************
if [ "$proj_name" = "laba" ]; then
hosts=('172.16.7.213' '172.16.18.237')
bak_source_host='172.16.7.213'
file_path_pre='/mydata1/www/app186.sunyoupai.com/'
up_lst_file="/root/tool/publish_laba.lst"
bak_path="/root/tool/publish_bak/"
ver_file="/root/tool/publish.version"
elif [ "$proj_name" = "laba" ]; then
hosts=('172.16.7.213' '172.16.18.237')
bak_source_host='172.16.7.213'
file_path_pre='/mydata1/www/app186.sunyoupai.com/'
up_lst_file="/root/tool/publish_laba.lst"
bak_path="/root/tool/publish_bak/"
ver_file="/root/tool/publish.version"
else
echo "未定义的项目名" ; exit;
fi
#回退版本文件路径, 默认设置为当前备份路径
back_version_path="$bak_path"
back_version="$opt_version"
# ************************** 此处集中定义所有配置 end ********************
if [ -n "$lst_version" ]; then
echo "版本记录:$ver_file"
cat "$ver_file"
echo
echo "备份目录:$bak_path"
ls -l "$bak_path" ; exit ;
fi
# ************************************************ 函数 ******************************************
#记录更新版本号
function fun_log_version() {
ver_file=$1
back_ver=$2
hosts=$3
back_mark=''
v_info=$(tail -n 1 "$ver_file" | awk '{print $1;}')
if [ "$v_info" = "" ]; then v_info=1 ; else let "v_info = v_info + 1"; fi
tm=$(date +%Y-%m-%d_%H:%M)
if [ -n "$back_ver" ]; then
back_mark="b${back_ver}"
fi
echo "$v_info $tm \"${hosts[@]}\" $back_mark" >> $ver_file
}
# 分发指定列表中的文件
function publish_lst() {
uplst_file=$1
target_host=$2
path_pre=$3
ver_file=$4
if [ ! -f "$uplst_file" ]; then
echo "列表文件不存在"; exit;
fi
up_lst=$(cat "$uplst_file")
if [ -z "$up_lst" ]; then
echo "更新文件列表为空" ; exit;
fi
if [ -z "$target_host" ]; then
echo "目标主机不能为空"; exit;
fi
echo "$up_lst" | while read fl; do
if [ ! -d "${path_pre}${fl}" ]; then
if [ -f "${path_pre}${fl}" ]; then
rsync -aRzv ${path_pre}${fl} root@$target_host:${path_pre}${fl}
else
echo "文件不存在: ${path_pre}${fl}"
fi
fi
done
}
# 备份指定列表中的文件到本地
function bak_lst() {
uplst_file=$1
bak_path=$2
path_pre=$3
host=$4
if [ ! -f "$uplst_file" ]; then
echo "列表文件不存在,无法备份"; exit;
fi
lst=$(cat "$uplst_file")
if [ -z "$lst" ]; then
echo "文件列表为空, 程序退出" ; exit;
fi
#创建备份目录
if [ ! -d "$bak_path" ]; then
mkdir -p "$bak_path"
fi
echo "===================================== 开始备份,备份源为:$host ======================================"
echo "$lst" | while read fl; do
local_path=$(dirname ${bak_path}${path_pre}${fl})
if [ ! -d "$local_path" ]; then
mkdir -p "$local_path"
fi
if [ ! -d "${path_pre}${fl}" ]; then
rsync -aRzv root@$host:${path_pre}${fl} ${bak_path}${path_pre}${fl}
fi
done
}
# **************************************************** 主程序 **********************************************
notice='';
#设置了back_version 则为回退操作 ,否则为分发
if [ -n "$back_version" ];then
notice="回退至版本: $back_version"
if [ -n "$back_version_path" ];then
notice=${notice}", 回退路径设置为: $back_version_path"
fi
else
notice="更新列表文件设置为: $up_lst_file"
fi
echo '======================================='
echo $notice
echo '======================================='
echo
echo '是否开始操作?(y/n)'
read doit
if [ "$doit" != 'y' ] ; then
echo '已取消' ; exit ;
fi
#检查版本文件是否存在
if [ ! -f "$ver_file" ]; then
echo "找不到版本记录文件 $ver_file"; exit;
fi
#当前版本
v_info=$(tail -n 1 "$ver_file" | awk '{print $1;}')
#版本回退操作(将备份的版本文件分发)
if [ -n "$back_version" ];then
if [ -z "$v_info" ]; then
echo "没有可以回退的版本"; exit;
else
if [ "$back_version" -gt "$v_info" ] || [ "$back_version" -eq "$v_info" ]; then
echo "回退版本只能小于当前版本, 当前版本号:$v_info" ; exit;
fi
fi
back=${back_version_path}${back_version}'/'
if [ ! -d "$back" ]; then
echo "版本目录 $back 不存在" ; exit;
fi
#回退
echo '============= 开始回退 =============='
echo "回退文件在:$back "
for host in ${hosts[@]} ; do
rsync -aRzv "$back" root@$host:/
done
echo "============= 完成 =================="
fun_log_version $ver_file $back_version "${hosts[@]}"
#分发操作(将线上测试机的文件分发)
else
if [ ! -d "$bak_path" ] ; then
mkdir -p "$bak_path"
fi
for host in ${hosts[@]} ; do
#备份原文件
if [ "$host" = "$bak_source_host" ]; then
if [ "$v_info" = "" ]; then
v_info=1 ;
let "bak_v = v_info -1" ;
else
let "bak_v = v_info"
fi
#由版本号产生备份目录
bak_dir="${bak_path}${bak_v}"
#备份
bak_lst $up_lst_file $bak_dir $file_path_pre $host
fi
#更新文件
echo "=========================== 开始分发至: $host ========================="
publish_lst $up_lst_file $host $file_path_pre $ver_file
done
#记录版本号
fun_log_version $ver_file -1 "${hosts[@]}"
fi