632 lines
24 KiB
Bash
632 lines
24 KiB
Bash
#!/bin/bash
|
||
# ---------------------------------------------------------
|
||
# 开发工具脚本
|
||
# @author whjing2012@gmail.com
|
||
# ---------------------------------------------------------
|
||
# set -f
|
||
# 语言版本 zh-CN
|
||
la="zh-CN"
|
||
# 打包目录
|
||
release_dir="/data/yhdl/release"
|
||
# 代码目录
|
||
server_dir="/data/yhdl/server"
|
||
# 控制服数据库
|
||
db_host='10.154.234.243'
|
||
db_port=3306
|
||
db_name="oms"
|
||
db_user='xge'
|
||
db_pass="HrsmjzIhKWff1Iae"
|
||
db_conn="mysql -h$db_host -P$db_port -u$db_user -p$db_pass -D$db_name "
|
||
# 产品ID
|
||
product_id=1
|
||
# 服务器状态[0:正常 1:注销 2:主合服 3:被合服]
|
||
srv_status='0,2'
|
||
# 版本号
|
||
ver="v170929"
|
||
# 是否本地启动节点热更 当hotswap=true | false 时适用
|
||
# true 本地开节点操作
|
||
# false 相应服上开节点操作
|
||
local_node="false"
|
||
# 是否执行热更 true | false | mysql | gen_ctl | update_cfg | check | start | stop
|
||
# true 执行热更操作
|
||
# false 不执行热更操作
|
||
# mysql 执行数据库脚本
|
||
# gen_ctl 重新生成ctl.sh脚本
|
||
# update_cfg 更新配置文件
|
||
# update_cfg_sql 更新配置文件和SQL数据结构
|
||
# check 检查节点是否已停止运行(挂掉了)
|
||
# check_start 检查节点是否完成启动
|
||
# start 启动节点
|
||
# stop 停止节点
|
||
# ver 版本更新
|
||
# open 开入口
|
||
# close 关入口
|
||
# dellog 删除日志
|
||
hotswap="true"
|
||
# 热更新最大重试次数
|
||
hotswap_max=5
|
||
# 最大启动进程数 同时执行多个命令
|
||
pro_max=10
|
||
|
||
# 物理服务器 可指定部分 上传版本至所有物理服务器用 all 或是列举出所有 建议用 all
|
||
mac_list=( 9996 )
|
||
mac_list=( 9996 10001 10002 )
|
||
# mac_list=all
|
||
# mac_list="all" # 上传更新代码到所有物理机
|
||
|
||
# 踢除指定物理服务器 在mac_list="all"时起作用 多个用,分隔 如 kick_mac="'10001','10002'"
|
||
kick_mac="'0'"
|
||
# kick_mac="'9999'"
|
||
|
||
# 操作指定节点 可指定部分 全部为 all 或列举出所有 建议用 all
|
||
# 服务器列表 格式:平台,区号
|
||
zone_list=(
|
||
"release,1"
|
||
"center,0"
|
||
# "sytest,1"
|
||
# "sytest,6"
|
||
# "sytest,2"
|
||
# "sytest,3"
|
||
# "sytest,4"
|
||
# "center,1"
|
||
)
|
||
# zone_list="'fzone','gzone','hzone'" # 更新指定平台,用'单引号包括 多个用;分号分隔 如 zone_list="'4399','37'"
|
||
# zone_list="'sytest'" # 更新所有指定版本${ver}的服
|
||
# zone_list="all" # 更新所有指定版本${ver}的服
|
||
|
||
# 踢除指定平台 在zone_list="all"时起作用 每个平台用'单引号包括 多个用,分隔 如 kick_platform="'4399','37'"
|
||
kick_platform="'verify'"
|
||
# kick_platform="'fsgj_center'"
|
||
|
||
# 踢除服 格式:kick_zone_list=( "4399,1" "4399,2" )
|
||
kick_zone_list=( )
|
||
# kick_zone_list=( "release,1" "center,0" )
|
||
|
||
# 附加选服
|
||
ext_zone_sql=''
|
||
# ext_zone_sql="and c.name='hzone' and zone_id >= 1 and zone_id <= 35"
|
||
|
||
# 需要执行的方法操作 格式:mod:fun:args
|
||
exec_list=(
|
||
# "info:i:[]"
|
||
# "keyword:reload:[]"
|
||
# "holiday_mgr:reload:[]"
|
||
# "holiday_role:reload:[all]"
|
||
# sys_env:del:[rank_match_dynamic_robot]
|
||
# mail:check_gmail:[701]
|
||
# guild_dun:loald:[]
|
||
# holiday_fix:holiday_compensated_mail:[]
|
||
# "say_subtitle:clear:[lists#seq(201,203)]"
|
||
# "say_subtitle:clear:[lists#seq(401,410)]"
|
||
# "dun_trial_mgr:check_replay:[]"
|
||
# 'code_util:eval:["A=5,B=3,A*B."]'
|
||
# "charge_mgr:sync_charge_log:[10]"
|
||
)
|
||
|
||
# 需要额外上传的文件
|
||
ufile_list=(
|
||
# "/data/amp_web.sql:/data/"
|
||
# "/data/yhdl/server/ebin/item_gift_data.beam:/data/huanxiang_code/v150729/server/ebin/"
|
||
)
|
||
|
||
# 需要执行的sql
|
||
exec_sql=(
|
||
# "source /data/huanxiang_code/$ver/server/tpl/ver_db.sql"
|
||
# "select count(*) from role"
|
||
)
|
||
|
||
|
||
# 更新脚本目标
|
||
filepath=$(cd `dirname $0`; pwd)
|
||
|
||
# 执行文件输出文件夹
|
||
code_out_dir=$(pwd)"/out_code_update_tmp"
|
||
mkdir -p ${code_out_dir}
|
||
chmod +x ${code_out_dir}
|
||
|
||
# 执行出错的语句
|
||
exe_err=${code_out_dir}"/err_code_update.log"
|
||
|
||
# 执行出错的服
|
||
exe_err_zone=${code_out_dir}"/tmp_last_err_zone.txt"
|
||
|
||
# 最后一次执行的所有命令
|
||
all_exe_cmd=${code_out_dir}"/all_exe_cmd_tmp.sh"
|
||
|
||
# 执行结果输出
|
||
exe_result_out=${code_out_dir}"/result_out.log"
|
||
|
||
# 缓存脚本目录
|
||
sh_tmp_dir=$filepath/sh/tmp
|
||
|
||
# 命令计数器
|
||
idx=1
|
||
|
||
# 执行相应操作
|
||
fun_exec(){
|
||
if [ "$do" = "fdo" ] && [ "$zone_idx" != "" ] ; then
|
||
shtmp=$sh_tmp_dir/sh_$((zone_idx%pro_max)).sh
|
||
if [ -f $shtmp ]; then
|
||
echo "ret=\$($exestr)" >> $shtmp
|
||
else
|
||
echo "ret=\$($exestr)" > $shtmp
|
||
fi
|
||
echo "echo -e \"${idx}.${exestr}\n$(fun_time)[\e[91m${platform},${zone_id}\e[0;0m]执行结果:==\${ret}\"" >> $shtmp
|
||
return
|
||
fi
|
||
# sleep $((random%10+1))
|
||
echo -e "$idx.$exestr"
|
||
echo -e $exestr >> ${all_exe_cmd}
|
||
exe_cmd=$exestr
|
||
if [ "${do}" = "do" ] || [ "$do" = "fdo" ]; then
|
||
for((i=1; i<=$hotswap_max; i=i+1)); do
|
||
ret=$(eval $exe_cmd)
|
||
echo -e "${idx}.${exestr}\n$(fun_time)[\e[91m${platform},${zone_id}\e[0;0m]执行结果:==${ret}"
|
||
if [ $(echo ${ret} | grep "节点还在正常运行中" | wc -l) -gt 0 ]; then
|
||
echo "${platform},${zone_id}" >> ${exe_err_zone}
|
||
[ "${platform}" != '' -a "${zone_id}" != '' ] && echo "[${platform}_${zone_id}]==error==>[${ret}]" >> ${exe_result_out}
|
||
break
|
||
elif [ $(echo ${ret} | grep "main" | grep -e "(error|terminating|无法访问节点)" | grep "hotswap" | wc -l) -gt 0 ] && [ $(echo ${ret} | grep "return:{badrpc,nodedown}" | wc -l) -gt 0 ]; then
|
||
if [ $hotswap_max -gt $i ]; then
|
||
echo "$(fun_time)[${platform},${zone_id}]服热更和语句执行出错,重新执行"
|
||
elif [ "$hotswap" != "stop" ]; then
|
||
echo "${exestr}" >> ${exe_err}
|
||
echo "\"${platform},${zone_id}\"" >> ${exe_err_zone}
|
||
fi
|
||
elif [ $(echo ${ret} | grep "main" | grep "error|terminating|无法访问节点" | grep "hotswap" | wc -l) -gt 0 ]; then
|
||
if [ $hotswap_max -gt $i ]; then
|
||
exestr=${exestr//ctl.sh exec/ctl.sh nodo} ## 防止重复执行
|
||
echo "$(fun_time)[${platform},${zone_id}]服热更出错,重新执行"
|
||
elif [ "$hotswap" != "stop" ]; then
|
||
echo "${exestr}" >> ${exe_err}
|
||
echo "\"${platform},${zone_id}\"" >> ${exe_err_zone}
|
||
fi
|
||
elif [ $(echo ${ret} | grep "return:{badrpc,nodedown}" | wc -l) -gt 0 ]; then
|
||
if [ $hotswap_max -gt $i ]; then
|
||
exestr=${exestr//ctl.sh hotswap/ctl.sh nodo} ## 防止重复执行
|
||
echo "$(fun_time)[${platform},${zone_id}]服执行语句出错,重新执行"
|
||
elif [ "$hotswap" != "stop" ]; then
|
||
echo "${exestr}" >> ${exe_err}
|
||
echo "\"${platform},${zone_id}\"" >> ${exe_err_zone}
|
||
fi
|
||
elif [ $(echo ${ret} | grep -e "(error|terminating)" | wc -l) -gt 0 ]; then
|
||
if [ $hotswap_max -gt $i ]; then
|
||
echo "$(fun_time)[${platform},${zone_id}]服热更和语句执行出错,重新执行"
|
||
elif [ "$hotswap" != "stop" ]; then
|
||
echo "${exestr}" >> ${exe_err}
|
||
echo "\"${platform},${zone_id}\"" >> ${exe_err_zone}
|
||
fi
|
||
else
|
||
[ "${platform}" != '' -a "${zone_id}" != '' ] && echo "[${platform}_${zone_id}]====>[${ret}]" >> ${exe_result_out}
|
||
break
|
||
fi
|
||
done
|
||
fi
|
||
}
|
||
|
||
# 开启后台执行方式
|
||
fun_exec_pro(){
|
||
if [ ${pro_max} -gt 1 ] && [ "$do" != "sdo" ] ; then
|
||
fun_exec &
|
||
fun_idx
|
||
else
|
||
fun_exec
|
||
fi
|
||
}
|
||
|
||
# 提示是否继续
|
||
fun_alert(){
|
||
echo "是否继续(y/n)"
|
||
read ret
|
||
case $ret in
|
||
y|y|yes|yes) ;;
|
||
*)
|
||
exit 0
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 获取当前最大版本号
|
||
fun_max_ver(){
|
||
cd ${release_dir}
|
||
maxver=""
|
||
for filename in $(ls); do
|
||
if [ -d "${filename}" ] && [ "${filename:0:3}" = "${ver:0:3}" ] && [[ "${filename}" > "${maxver}" ]]; then
|
||
# echo ${filename}
|
||
maxver=${filename}
|
||
fi
|
||
done
|
||
echo "当前最大版本号: ${maxver}"
|
||
if [ "${maxver}" != "${ver}" ]; then
|
||
echo -e "注意===============[当前热更版本( \e[91m${ver}\e[0;0m )与最大版本号( \e[91m${maxver}\e[0;0m )不一致,请确认]==========================="
|
||
fi
|
||
}
|
||
|
||
# 热更操作
|
||
fun_update(){
|
||
do=${1}
|
||
|
||
echo "准备热更版本: ${ver}"
|
||
fun_max_ver
|
||
fun_get_all_machine
|
||
fun_get_all_zone
|
||
|
||
zone_list=( $(echo "==${zone_list[*]}==" | sed 's/\(\s\+\)/==\1==/g') )
|
||
# echo -e "将更新节点[数量:$(fun_color 92 ${#zone_list[@]})]:( ${zone_list[@]} )"
|
||
for s in ${kick_zone_list[@]}; do
|
||
zone_list=( ${zone_list[*]//==${s}==/} ) ## 踢除指定服
|
||
done
|
||
zone_list=( ${zone_list[*]//==/} ) ## 踢除附加符号
|
||
|
||
start_time=$(date +%s)
|
||
echo -e "将更新节点[数量:$(fun_color 92 ${#zone_list[@]})]:( ${zone_list[@]} )"
|
||
echo -e "代码将上传到物理机[数量:$(fun_color 92 ${#mac_list[@]})]:( ${mac_list[@]} )"
|
||
echo "踢除平台信息:${kick_platform}"
|
||
echo -e "踢除节点[数量:$(fun_color 92 ${#kick_zone_list[@]})]:( ${kick_zone_list[@]} )"
|
||
|
||
if [ "${do}" = "do" ] || [ "$do" = "fdo" ]; then
|
||
fun_alert
|
||
fi
|
||
echo "" > ${exe_err}
|
||
echo "" > ${exe_err_zone}
|
||
echo "" > ${all_exe_cmd}
|
||
echo "" > ${exe_result_out}
|
||
rm ${sh_tmp_dir} -rf
|
||
mkdir -p ${sh_tmp_dir}
|
||
chmod +x ${all_exe_cmd}
|
||
|
||
cd ${server_dir}
|
||
echo "$(fun_time)开始上传代码到物理服务器..."
|
||
for m in ${mac_list[@]}; do
|
||
exestr="./srv.sh srv code_update ${m} ${ver}"
|
||
fun_exec_pro
|
||
for f in ${ufile_list[@]}; do
|
||
sfile=$(echo ${f} | cut -d':' -f1)
|
||
tfile=$(echo ${f} | cut -d':' -f2)
|
||
exestr="fun_upload_file ${m} ${sfile} ${tfile}"
|
||
fun_exec_pro
|
||
done
|
||
done
|
||
wait
|
||
do_start_time=$(date +%s)
|
||
idx=1
|
||
|
||
echo "$(fun_time)开始执行更新等脚本操作..."
|
||
init_zone_list=( ${zone_list[@]} )
|
||
for((x=1; x<=$hotswap_max; x=x+1)); do
|
||
fun_update_zone $@
|
||
fail_zone_list=( $(cat $exe_err_zone|grep ",") )
|
||
if [ "$hotswap" = "stop" ] && [ ${#fail_zone_list[@]} -gt 0 ]; then
|
||
echo -e "更新失败需要重新执行节点[数量:$(fun_color 92 ${#fail_zone_list[@]})]:( ${fail_zone_list[@]} )"
|
||
pro_max=1
|
||
zone_list=( ${fail_zone_list[@]} )
|
||
echo "" > ${exe_err_zone}
|
||
fun_alert
|
||
continue
|
||
else
|
||
break
|
||
fi
|
||
done
|
||
|
||
echo -e "代码将上传到物理机[数量:$(fun_color 92 ${#mac_list[@]})]"
|
||
echo -e "更新服务器[数量:$(fun_color 92 ${#init_zone_list[@]})]"
|
||
echo -e "更新失败节点[数量:$(fun_color 92 ${#fail_zone_list[@]})]:( ${fail_zone_list[@]} )"
|
||
echo -e "上传代码到物理机总耗时(秒):\e[91m$(expr $do_start_time - $start_time)"
|
||
echo -e "执行热更命令操作总耗时(秒):\e[91m$(expr `date +%s` - $do_start_time)"
|
||
echo -e "全部操作过程累计总耗时(秒):\e[91m$(expr `date +%s` - $start_time)"
|
||
if [ $( cat ${exe_err} | grep -v '^$' | wc -l) -gt 0 ]; then
|
||
echo -e "$(fun_time)所有执行出错语句===========> $(cat ${exe_err} | grep -v '^$' | wc -l)\n$(cat ${exe_err})"
|
||
fi
|
||
}
|
||
|
||
fun_update_zone(){
|
||
zone_idx=0
|
||
for s in ${zone_list[@]}; do
|
||
let zone_idx=$zone_idx+1
|
||
if [ "${do}" = "show" ] && [ ${zone_idx} -eq 2 ] && [ ${#zone_list[@]} -gt 50 ]; then
|
||
fun_alert
|
||
fi
|
||
platform=$(echo ${s} | cut -d',' -f1)
|
||
zone_id=$(echo ${s} | cut -d',' -f2)
|
||
eval "$(fun_main_srv_info $platform $zone_id)"
|
||
if [ "${hotswap}" != "ver" ] && [ "${ver}" != "${row['ver']}" ]; then
|
||
echo -e "$(fun_color 91 'error>>') [错误]( $(fun_color 91 ${platform},${zone_id}) )服版本号[ $(fun_color 91 ${row['ver']} ) ]对不上热更版本号[ $(fun_color 91 ${ver} ) ], 不进行该操作"
|
||
continue
|
||
fi
|
||
exestr=""
|
||
if [ "${hotswap}" = "update_cfg" ]; then
|
||
exestr="./srv.sh srv gen_ctl ${platform} ${zone_id} && " # 更新指定服的脚本文件
|
||
elif [ "${hotswap}" = "update_cfg_sql" ]; then
|
||
exestr="./srv.sh srv gen_ctl ${platform} ${zone_id} && " # 更新指定服的脚本文件
|
||
elif [ "${hotswap}" = "gen_ctl" ]; then
|
||
exestr="./srv.sh srv gen_ctl ${platform} ${zone_id}" # 更新指定服的脚本文件
|
||
fun_exec_pro
|
||
continue
|
||
elif [ "${hotswap}" = "ver" ]; then
|
||
exestr="$db_conn -e \"update zones set ver='$2', is_maintain=$3 where product_id=$product_id and zone_id=${zone_id} and platform_id in (select platform_id from platforms where product_id=$product_id and name='${platform}')\"" # 更新指定服的脚本文件
|
||
fun_exec_pro
|
||
continue
|
||
elif [ "${hotswap}" = "close" ]; then
|
||
exestr="$db_conn -e \"update zones set is_maintain=1 where product_id=$product_id and zone_id=${zone_id} and platform_id in (select platform_id from platforms where product_id=$product_id and name='${platform}')\"" # 更新指定服的脚本文件
|
||
fun_exec_pro
|
||
continue
|
||
elif [ "${hotswap}" = "open" ]; then
|
||
exestr="$db_conn -e \"update zones set is_maintain=0 where product_id=$product_id and zone_id=${zone_id} and platform_id in (select platform_id from platforms where product_id=$product_id and name='${platform}')\"" # 更新指定服的脚本文件
|
||
fun_exec_pro
|
||
continue
|
||
elif [ "${local_node}" = "true" ]; then
|
||
fun_update_local_node
|
||
continue
|
||
fi
|
||
ssh="ssh -p${row['ssh_port']} ${row['ssh_user']}@${row['ip']}"
|
||
do_sql
|
||
exestr="${exestr}${ssh} 'cd ${row['root']}"
|
||
if [ "${hotswap}" = "true" ]; then
|
||
exestr="${exestr} && ./ctl.sh hotswap 1"
|
||
elif [ "${hotswap}" = "update_cfg" ]; then
|
||
exestr="${exestr} && ./ctl.sh update_cfg"
|
||
elif [ "${hotswap}" = "update_cfg_sql" ]; then
|
||
exestr="${exestr} && ./ctl.sh update_cfg"
|
||
exestr="${exestr} && mysql -uroot -p\$(cat /data/save/mysql_root) -D${row['db_name']} -e \"source /data/huanxiang_code/$ver/server/tpl/ver_db.sql\""
|
||
elif [ "${hotswap}" = "start" ]; then
|
||
exestr="${exestr} && ./ctl.sh start"
|
||
elif [ "${hotswap}" = "dellog" ]; then
|
||
exestr="${exestr} && echo \"\" > screenlog.0"
|
||
elif [ "${hotswap}" = "stop" ]; then
|
||
exestr="${exestr} && ./ctl.sh stop"
|
||
exestr="${exestr} && [ \$(screen -ls|grep \"${row['nodename']}\"|wc -l) -eq 0 ] || echo -e \e[91m服务器[${platform}_${zone_id}]已关服失败\e[0;0m "
|
||
elif [ "${hotswap}" = "check" ]; then
|
||
exestr="${exestr} && [ \$(screen -ls|grep \"${row['nodename']}\"|wc -l) -eq 0 ] && echo 服务器[${platform}_${zone_id}]已停止运行"
|
||
elif [ "${hotswap}" = "check_start" ]; then
|
||
exestr="${exestr} && [ \$(./ctl.sh exec services:check:[]|grep not_start_ok|wc -l) -gt 0 ] && echo 服务器[${platform}_${zone_id}]未完全启动运行"
|
||
elif [ "${hotswap}" = "mysql" ]; then
|
||
continue
|
||
fi
|
||
for fun in ${exec_list[@]}; do
|
||
exestr="${exestr} && ./ctl.sh exec \"${fun//\"/\\\"}\""
|
||
done
|
||
exestr="${exestr}'"
|
||
fun_exec_pro
|
||
done
|
||
|
||
if [ "$do" = "fdo" ]; then
|
||
chmod +x $sh_tmp_dir/*.sh
|
||
for tmpsh in $(ls ${sh_tmp_dir}); do
|
||
echo "exec_sh_file===>$tmpsh"
|
||
$sh_tmp_dir/$tmpsh &
|
||
done
|
||
fi
|
||
|
||
wait
|
||
}
|
||
|
||
# 采用本地节点热更
|
||
fun_update_local_node(){
|
||
nodename=${row['nodename']}
|
||
fun_cmd="io:format(\\\"[\e[92mdev:u()\e[0;0m]return:~w~n\\\", [rpc:call('${nodename}', dev, u, [])])"
|
||
for cmd_line in ${exec_list[@]}; do
|
||
mod=$(echo $cmd_line | cut -d':' -f1)
|
||
fun=$(echo $cmd_line | cut -d':' -f2)
|
||
args=$(echo $cmd_line | cut -d':' -f3)
|
||
if [[ $(echo $mod | grep "^[a-z_]\{1,50\}$") = "" ]]; then
|
||
echo ">> [错误]模块名格式不正常:\e[91m${mod}\e[0;0m"
|
||
exit 1
|
||
fi
|
||
if [[ $(echo $fun | grep "^[a-z_]\{1,50\}$") = "" ]]; then
|
||
echo ">> [错误]方法名格式不正常:\e[91m${fun}\e[0;0m"
|
||
exit 1
|
||
fi
|
||
if [[ $(echo $args | grep "^\[.*\]$") = "" ]]; then
|
||
echo -e ">> [错误]方法参数格式不正常:\e[91m${args}\e[0;0m"
|
||
exit 1
|
||
fi
|
||
fun_cmd="${fun_cmd}, io:format(\\\"\e[92mapply(${mod}, ${fun}, ${args//\"/\\\\\\\"})\e[0;0mreturn:~w~n\\\", [rpc:call('${nodename}', ${mod}, ${fun}, ${args//\"/\\\"})])"
|
||
done
|
||
|
||
exestr="erl -noshell -kernel inet_dist_listen_min 40100 -kernel inet_dist_listen_max 44000 -hidden -pa ${server_dir}/ebin -name update_${nodename} -setcookie ${row['cookie']} -eval \"io:setopts([{encoding,unicode}]), ${fun_cmd}\" -s c q"
|
||
fun_exec_pro
|
||
}
|
||
|
||
# 数据库执行
|
||
do_sql(){
|
||
IFS=$'\n'
|
||
exestr_bak=$exestr
|
||
for sql in ${exec_sql[@]}; do
|
||
sql=${sql//\'/\\\"}
|
||
exestr="${ssh} 'mysql -uroot -p\$(cat /data/save/mysql_root) -D${row['db_name']} -e \"${sql}\"'"
|
||
fun_exec_pro
|
||
done
|
||
exestr=$exestr_bak
|
||
}
|
||
|
||
# 获取服务器安装信息
|
||
fun_srv_info(){
|
||
platform=$1
|
||
zone_id=$2
|
||
if [ "" = "${platform}" ] || [ "" = "${zone_id}" ]; then
|
||
echo "error>> [错误]没有输入有效的平台标识和区号"
|
||
exit 1
|
||
fi
|
||
eval "$(mysql_get_row "select a.name product_name, b.name platform, c.is_maintain, c.ver, d.cookie, d.db_name, d.root, d.zone_id, e.name machine, e.code_path, e.ip, e.ssh_port, e.ssh_user from products a, platforms b, zones c, nodes d, machines e where a.product_id = $product_id and a.product_id = b.product_id and b.platform_id = c.platform_id and b.platform_id = d.platform_id and c.zone_id = d.zone_id and d.machine_id = e.machine_id and b.name='${platform}' and c.zone_id=${zone_id}")"
|
||
declare -p row
|
||
}
|
||
|
||
# 获取合服主服务器安装信息
|
||
fun_main_srv_info(){
|
||
platform=$1
|
||
zone_id=$2
|
||
if [ "" = "${platform}" ] || [ "" = "${zone_id}" ]; then
|
||
echo "error>> [错误]没有输入有效的平台标识和区号"
|
||
exit 1
|
||
fi
|
||
eval "$(mysql_get_row "select a.name product_name, b.name platform, c.ver, c.is_maintain, d.cookie, d.db_name, d.root, d.zone_id, e.name machine, e.code_path, e.ip, e.ssh_port, e.ssh_user from products a, platforms b, zones c, nodes d, machines e where a.product_id = $product_id and a.product_id = b.product_id and b.platform_id = c.platform_id and b.platform_id = d.platform_id and c.zone_id = d.zone_id and d.machine_id = e.machine_id and c.installed=1 and c.srv_status in ($srv_status) and ((b.name='${platform}' and c.zone_id=${zone_id}) or combine like '%<<__${platform}_${zone_id}__>>%')")"
|
||
declare -p row
|
||
}
|
||
|
||
# sql语句执行结果中的第一行
|
||
# 返回的结果存放在$ROW变量中
|
||
# 用法示例:
|
||
# eval "$(mysql_get_row select * from mysql.user)"
|
||
# for k in ${!row[@]}; do
|
||
# echo $k = ${row[$k]}
|
||
# done
|
||
mysql_get_row(){
|
||
#set names utf8;
|
||
local sql="$@ limit 1 "
|
||
IFS=$'\n'
|
||
# local lines=( $(${db_conn} -ss -e"$sql\G") )
|
||
local lines=( $(mysql -h$db_host -P$db_port -u$db_user -p$db_pass -D$db_name -ss -e"$sql\G") )
|
||
lines=( ${lines[*]//\**/} ) # 删除分隔符
|
||
lines=( ${lines[*]//:\ /\'\]=\"} ) # 替换等号
|
||
lines=( ${lines[*]/#/tmp\[\'} ) # 替换变量名
|
||
lines=( ${lines[*]/%/\"} ) # 增加尾部双引号
|
||
declare -A tmp row
|
||
eval "$(echo "${lines[*]}")" # 转成关联数组
|
||
# 去除多余空格
|
||
for k in ${!tmp[@]}; do
|
||
row[${k/#* /}]=${tmp[$k]}
|
||
done
|
||
declare -p row
|
||
}
|
||
# 获取所有物理服务器ID列表
|
||
fun_get_all_machine(){
|
||
if [ "${mac_list}" = "all" ]; then
|
||
mac_list=( $(${db_conn} -ss -e "select distinct m.name from machines as m, nodes as n, zones as z where m.product_id=$product_id and m.machine_id=n.machine_id and n.platform_id=z.platform_id and n.zone_id=z.zone_id and z.lang='${la}' and z.ver='${ver}' and m.name not in (${kick_mac}) order by m.name") )
|
||
fi
|
||
}
|
||
|
||
# 获取所有服务信息
|
||
fun_get_all_zone(){
|
||
if [ "${zone_list}" = "all" ]; then
|
||
zone_list=( $(${db_conn} -ss -e "select concat(p.name,',', z.zone_id) as a from zones z, platforms p where z.product_id=$product_id and z.platform_id=p.platform_id and lang='${la}' and ver='${ver}' and installed=1 and srv_status in ($srv_status) and p.name not in (${kick_platform}) ${ext_zone_sql} order by p.name, zone_id") )
|
||
elif [ $(echo ${zone_list} | grep "'" | wc -l) -gt 0 ]; then
|
||
zone_list=( $(${db_conn} -ss -e "select concat(p.name,',', zone_id) as a from zones z, platforms p where z.product_id=$product_id and z.platform_id=p.platform_id and ver='${ver}' and p.name in (${zone_list}) and installed=1 and srv_status in ($srv_status) ${ext_zone_sql} order by p.name, zone_id") )
|
||
fi
|
||
}
|
||
|
||
# 上传文件
|
||
fun_upload_file(){
|
||
machine=$1
|
||
source=$2
|
||
target=$3
|
||
eval "$(mysql_get_row "select * from machines where product_id=$product_id and name = '${machine}'")"
|
||
scp -P${row['ssh_port']} $source ${row['ssh_user']}@${row['ip']}:${target}
|
||
}
|
||
|
||
# 下载文件
|
||
fun_download_file(){
|
||
machine=$1
|
||
source=$2
|
||
target=$3
|
||
eval "$(mysql_get_row "select * from machines where product_id=$product_id and name = '${machine}'")"
|
||
scp -P${row['ssh_port']} ${row['ssh_user']}@${row['ip']}:${source} ${target}
|
||
}
|
||
|
||
# 命令计数器
|
||
fun_idx(){
|
||
# echo "=============== $(jobs -l | wc -l)"
|
||
if [ $((idx%pro_max)) -eq 0 ]; then
|
||
echo "$(fun_time)正在批量执行命令,请等待=== 当前命令编号:$idx"
|
||
fi
|
||
let idx=$idx+1
|
||
fun_wait_pro
|
||
}
|
||
|
||
# 暂停等待后台进程结束
|
||
fun_wait_pro(){
|
||
while [ $(jobs -l | wc -l) -ge $pro_max ]
|
||
do
|
||
sleep 0.1
|
||
done
|
||
}
|
||
|
||
# 使用screen方式执行
|
||
fun_screen_do(){
|
||
path=${code_out_dir}
|
||
tmp_file=$path/tmp_code_update.sh
|
||
cat > ${tmp_file} <<EOF
|
||
#!/bin/bash
|
||
ulimit -SHn 102400
|
||
${filepath}/code_update.sh do
|
||
EOF
|
||
chmod +x ${tmp_file}
|
||
screen -dmSL update_zone_$la -s ${tmp_file}
|
||
fun_shell
|
||
}
|
||
|
||
# 进入shell
|
||
fun_shell(){
|
||
screen -r update_zone_$la
|
||
}
|
||
|
||
# 时间
|
||
fun_time(){
|
||
echo $(date +">>##[%Y-%m-%d %H:%M:%S]")
|
||
}
|
||
|
||
# 颜色
|
||
fun_color(){
|
||
echo "\e[$1m$2\e[0;0m"
|
||
}
|
||
|
||
# 显示ssh登录指定服务器
|
||
fun_ssh(){
|
||
platform=$1
|
||
zone_id=$2
|
||
eval "$(fun_main_srv_info $platform $zone_id)"
|
||
echo "ssh -p${row['ssh_port']} ${row['ssh_user']}@${row['ip']} # 主服目录:${row['root']}" # && cd ${row['root']}
|
||
ssh -p${row['ssh_port']} ${row['ssh_user']}@${row['ip']} # && cd ${row['root']}
|
||
}
|
||
|
||
# 下载文件
|
||
fun_ssh_m(){
|
||
machine=$1
|
||
eval "$(mysql_get_row "select * from machines where product_id=$product_id and name = '${machine}'")"
|
||
ssh -p${row['ssh_port']} ${row['ssh_user']}@${row['ip']}
|
||
}
|
||
|
||
# 打包代码
|
||
fun_pack(){
|
||
./srv.sh srv pack_all $ver $1
|
||
}
|
||
|
||
fun_main(){
|
||
cmd=$1
|
||
shift
|
||
case $cmd in
|
||
show) fun_update show $@;;
|
||
do) fun_update do $@;;
|
||
fdo) fun_update fdo $@;;
|
||
sdo) fun_screen_do $@;;
|
||
shell) fun_shell;;
|
||
srv) fun_srv_info $@;;
|
||
main) fun_main_srv_info $@;;
|
||
mach) fun_get_all_machine && echo "==>>( ${mac_list} )";;
|
||
srvs) fun_get_all_zone && echo "===>>( ${zone_list[*]} )";;
|
||
ssh) fun_ssh $@;;
|
||
ssh_m) fun_ssh_m $@;;
|
||
ufile) fun_upload_file $@;;
|
||
dfile) fun_download_file $@;;
|
||
pack) fun_pack $@;;
|
||
*)
|
||
echo "show 显示即将执行的语句"
|
||
# echo "do 执行更新操作"
|
||
echo "sdo 用screen方式执行更新操作"
|
||
echo "shell 进入screen查看执行情况"
|
||
echo "ssh P Z 进入指定服务器"
|
||
echo "srv P Z 查看指定服务器信息"
|
||
echo "main P Z 查看指定服务器主合服信息"
|
||
echo "ufile 10001 /data/test.txt /data/ 上传文件到指定目录"
|
||
echo "dfile 10001 /data/fsgj_4399_1/env.cfg /data/card/ 下载文件到指定目录"
|
||
echo "group GroupId Platform Z1 Z2 Z3 设置分组 Z1为主服"
|
||
exit 1
|
||
;;
|
||
esac
|
||
exit 0
|
||
}
|
||
|
||
if [ "$undo" != 'true' ]; then
|
||
fun_main $@
|
||
fi
|
||
|