在创始型的一个物流互联网平台团队里,有伙伴反复抱怨为了适用不同的环境构建、部署工程要多长多长的时间,而且一步小心就忘了啥,劳神费时!交接情况后,发现基本如此,并且一些当前高大上的一些做法也无法开展。
思前思后,觉得搞个脚本能解决些体力的事情。于是硬着头皮一遍凭着很久前对 shell 的一些记忆,一边百度,写了2个脚本。
工程介绍
工程部署在阿里云上,采用了不少的阿里云服务,是个比较典型前后端完全分离的小型分布式平台:
- dubbo集群实现业务逻辑服务;
- SpringMVC集群实现Restful服务;
- nginx发布静态网站,负载均衡和流控等。
构建脚本
|
|
部署脚本
#!/bin/bash
PROFILE=prod
SERVER_SERVICE=(10.30.*.* 10.30.*.*)
SERVER_WEB=(10.31.*.* 10.31.*.*)
SERVER_H5=(10.31.*.* 10.31.*.*)
ARTIFACT_SERVICE=(tms ams oms)
ARTIFACT_WEB=(ams-web oms-web)
ARTIFACT_JAVA=(${ARTIFACT_SERVICE[*]} ${ARTIFACT_WEB[*]})
ARTIFACT_H5=(manager)
ARTIFACT_ALL=(${ARTIFACT_JAVA[*]} ${ARTIFACT_H5[*]})
HOST_DIR="/opt/product"
function usage
{
echo ""
echo " -h | --host: 部署的目标主机"
echo " -d | --dir: 部署的目标目录。默认为:${HOST_DIR}"
echo " -s | --service-name: 部署的的服务名称,可用的服${ARTIFACT_ALL[@]}。默认为全部服务"
echo " -v | --version: 部署的服务的版本。默认为最新的生产构建版本"
echo " -p | --profile: 部署的环境。"
echo " --init: 部署后初始化目标机器,将部署的物设置为自动重启的系统服务"
echo " --start: 部署后启动(重启)服务"
echo ""
}
ARGS=`getopt -o h::d::s::v:p: --lhost::,dir::,service-name::,version:,init,start,profile -n 'deploy.sh'"$@"`
if [ $? != 0 ]; then
usage && exit 1
fi
eval set -- "${ARGS}"
ARTIFACT_PATH="/opt/build"
ARTIFACT_VERSION=
SPEC_HOST=
ARTIFACTS=(${ARTIFACT_ALL[*]})
SPEC_INIT=
SPEC_START=
while true
do
case "$1" in
-h|--host)
if [[ ! -z "$2" ]]; then
SPEC_HOST=($2)
fi
shift 2;
;;
-d|--dir)
if [[ ! -z "$2" ]]; then
HOST_DIR=$2
fi
shift 2
;;
-s|--service-name)
if [[ ! -z "$2" ]]; then
ARTIFACTS=($2)
fi
shift 2
;;
-v|--version)
if [[ ! -z "$2" ]]; then
ARTIFACT_VERSION=$2
fi
shift 2
;;
-p|--profile)
if [[ ! -z "$2" ]]; then
PROFILE=$2
fi
shift 2
;;
--init)
SPEC_INIT="true"
shift
;;
--start)
SPEC_START="true"
shift
;;
--)
shift
break
;;
*)
usage && exit 1
;;
esac
done
if [[ -z "$ARTIFACT_VERSION" ]]; then
if [[ -f "${ARTIFACT_PATH}/build_number" ]]; then
ARTIFACT_VERSION=`cat ${ARTIFACT_PATH}/build_number`
else
echo -e "\033[32;49;1m 构建文件[${ARTIFACT_PATH}/build_num丢失,请修复或通过-v 或 --version 指定部署的版本号"
exit 1
fi
fi
# 1=service, 2=host, 3=host-dir
function transter()
{
ssh "$2" "[[ -d $3 ]] || mkdir $3"
DST_REPO="${2}:${3}"
SRC_REPO="${ARTIFACT_PATH}/${PROFILE}_${ARTIFACT_VERSION}"
SRC_ARTIFACT=
SCP_FLAG=""
if [[ -f "${SRC_REPO}/${1}.jar" ]]; then
SRC_ARTIFACT="${SRC_REPO}/${1}.jar"
elif [[ -d "${SRC_REPO}/${1}" ]]; then
SRC_ARTIFACT="${SRC_REPO}/${1}"
SCP_FLAG="-r "
else
echo -e "\033[32;49;1m 资源[${SRC_REPO}/${1}]不存在\033[39;49;0m"
exit 1
fi
echo "copying ${SRC_ARTIFACT} to ${DST_REPO}/"
scp ${SCP_FLAG}${SRC_ARTIFACT} ${DST_REPO}/ > /dev/null
if [ $? == 0 ]; then
if [[ -z "$SCP_FLAG" ]]; then
ssh "$HOST" "chmod u+x ${3}/${1}.jar"
fi
echo -n `date "+%Y-%m-%d %H:%M:%S"` >> "${SRC_REPO}/info"
echo " 同步[SRC_ARTIFACT]到${DST_REPO}/" >> "${SRC_REPO}/info"
echo "${ARTIFACT_VERSION}" > "TMP_${ARTIFACT_VERSION}"
scp "TMP_${ARTIFACT_VERSION}" "${DST_REPO}/version" > /dev/null
rm -f "TMP_${ARTIFACT_VERSION}"
else
echo -e "\033[31;1m 拷贝资源[SRC_ARTIFACT]失败\033[0m"
exit 1
fi
return 0
}
function init()
{
if [[ "${ARTIFACT_JAVA[*]}" =~ "$3" ]]; then
ssh $1 "ln -sif ${2}/${3}.jar /etc/init.d/${3}"
TMP_CONF_FILE="TMP_CONF_${ARTIFACT_VERSION}"
echo "JAVA_OPTS=\"-Djava.security.egd=file:/dev/./urandom -ser-Xms1024m -Xmx2048m\"" > "$TMP_CONF_FILE"
echo "LOG_FOLDER=\"/var/log/paltformname/${ARTIFACT_VERSION}\"""$TMP_CONF_FILE"
echo "RUN_ARGS=\"--spring.profiles.active=${PROFI--application.build-number=${ARTIFACT_VERSION}\"""$TMP_CONF_FILE"
echo -n "# 自动配置于" >> "$TMP_CONF_FILE"
echo `date "+%Y-%m-%d %H:%M:%S"` >> "$TMP_CONF_FILE"
CONF_DIR="/etc/hd"
ssh "$1" "[[ -d ${CONF_DIR} ]] || mkdir ${CONF_DIR}"
scp "$TMP_CONF_FILE" "$1:${CONF_DIR}/${3}.conf" > /dev/null
rm -rf $TMP_CONF_FILE
ssh $1 "chkconfig --add ${3} && chkconfig ${3} on"
if [[ $? == 0 ]]; then
echo -e "\033[32m 初始化主机[${1}]服务[${3}]成功 \033[0m"
else
echo -e "\033[31m 初始化主机[${1}]服务[${3}]失败 \033[0m"
fi
return 0
else
echo "${3}不是JAVA构件,不能进行服务化初始化"
return 1
fi
}
for ARTIFACT in ${ARTIFACTS[*]}
do
if [[ ! "${ARTIFACT_ALL[*]}" =~ "${ARTIFACT}" ]]; then
echo -e "\033[31;1m 不支持服务[${ARTIFACT}]的部署\033[0m"
continue
fi
ARTIFACT_DST_HOST=
if [[ ! -z "$SPEC_HOST" ]]; then
ARTIFACT_DST_HOST=(${SPEC_HOST[*]})
elif [[ "${ARTIFACT_SERVICE[*]}" =~ "$ARTIFACT" ]]; then
sleep 2 # 让服务有足够的时间启动
ARTIFACT_DST_HOST=${SERVER_SERVICE[*]}
elif [[ "${ARTIFACT_WEB[*]}" =~ "$ARTIFACT" ]]; then
ARTIFACT_DST_HOST=${SERVER_WEB[*]}
elif [[ "${ARTIFACT_H5[*]}" =~ "$ARTIFACT" ]]; then
ARTIFACT_DST_HOST=${SERVER_H5[*]}
else
echo -e "\033[31;1m 脚本出错了,请报告运维人员修复\033[0m"
continue
fi
echo -e "\033[32m \n正在同步服务[${ARTIFACT}]...... \033[0m"
for HOST in ${ARTIFACT_DST_HOST[*]}
do
transter $ARTIFACT $HOST $HOST_DIR
if [[ $? == 0 ]]; then
if [[ ! -z "$SPEC_INIT" ]]; then
init $HOST $HOST_DIR $ARTIFACT && [[ ! -z "$SPEC_START"&& ssh $HOST "service ${ARTIFACT} start"
elif [[ "${ARTIFACT_JAVA[*]}" =~ "$ARTIFACT" ]]; then
CONF_FILE="/etc/hd/${ARTIFACT}.conf"
ssh $HOST "[[ ! -f $CONF_FILE ]]"
if [[ $? == 0 ]]; then
echo "主机[${HOST}]尚未配置服务[${ARTIFACT}],建deploy.sh -h${HOST} -d${HOST_DIR} --i-s${ARTIFACT}进行初始化"
else
ssh $HOST "sed -i 's/\(--application.build-number=\)igit:]]*/\1${ARTIFACT_VERSION}/g' $CONF_FILE"
ssh $HOST "sed -i 's/^LOG_FOLDER=.*/LOG_FOLDER=\"\/vlog\/paltformname\/${ARTIFACT_VERSION}\"/g' $CONF_FILE"
ssh $HOST "[[ -d /var/log/paltformname ]] || mkdir /log/paltformname"
ssh $HOST "[[ -d /var/paltformname/${ARTIFACT_VERSION} ]] || mkdir /var/paltformname/${ARTIFACT_VERSION}"
[[ ! -z "$SPEC_START" ]] && ssh $HOST "serv${ARTIFACT} restart"
fi
fi
fi
done
done