一、安装jenkins
注:这里不多说哈,百度遍地都是,安装方式不限,默认选择将推荐插件都安装,然后安装两个需要使用到的插件。
调用脚本插件:Conditional BuildStep
控制台时间戳插件:timestamper
二、jenkins创建项目
注:这里有个坑需要说一下,最开始我使用的是maven构建,但是如果按照我的这套方案会有一个编译死循环的问题,也就是说我本来是通过脚本来判断是编译构建新包或者是回滚旧包,但是问题来了,使用maven构建项目的话即使上边有脚本判断还是跳不出编译这一步,也就是说不管你是发布新版本还是旧版本都会重新编译一遍,那么坑的点是什么呢?发布的时候会编译两次,回滚的时候也是会编译两次,正常回滚就是不需要编译的直接将包传送过来启动即可,经过各种尝试后,终于找到问题点在哪?使用maven构建项目的话它自带的maven项无法关掉,所以就会造成上边脚本的编译和下边的maven编译重复,最终的解决方案:不使用maven构建项目,使用其他的比如我这里用的是自由风格,这样的话可以根据我们的需求来选择用不用maven编译,然后只需要在脚本里判断如果是发布新版本那么就调用maven编译并发布,如果是回滚操作那么将直接跳过编译即可。 重点:跳过编译你会发现回滚最多三五秒,这样的话对于我们运维来说缩短了回滚的时间,同时降低了用户访问失败的时长。
三、配置自动发布和回滚的脚本
1、丢弃旧的构建
注:以上配置根据自己需求调整就行。
2、参数化构建
3、字符参数
4、源码管理
5、构建环境
注:以上选项主要是为了统计编译构建和回滚的时长。
6、Build Steps
注:上图中的maven版本我这里是自己安装的这个版本所以配置选择了这个,如果没有提前配置的话就是默认选项。
#!/bin/bash
if [ -z $version ];then
echo "need build"
exit 0
else
echo "no need build"
exit -1
fi
clean install -Pprod -U -Dmaven.test.skip=true
pom.xml
7、执行shell
注:这里截图为了清楚就大概截一下图,具体详细信息在下边单独输出。
###########################################
case $deploy_environment in
deploy)
echo "deploy $deploy_env"
#mvn install -Dmaven.test.skip=true -e
#创建每次要备份的目录
path="${WORKSPACE}/bak/${BUILD_NUMBER}"
echo "$path"
echo "-d $path"
if [ -d $path ];
then
echo "The files is already exists "
else
mkdir -p $path
fi
#因为代码有双层目录,而target目录是在第二层目录里,所以在第一层创建一个新target目录
#\mkdir -p $WORKSPACE/target/
#将打包好的jar包重新定义新目录
#\cp -f $WORKSPACE/cjkj-account-server/target/*.jar $WORKSPACE/target/
#将打包好的jar包备份到相应目录,覆盖已存在的目标
\cp -f $WORKSPACE/target/*.jar $path
echo "Completing!"
;;
rollback)
echo "rollback $deploy_env version=$version"
############创建回滚的jar包数据目录##########################
#注:为了防止出现不断发布新版本,再不断修改和发布后,不知道该回滚哪个版本是没问题的版本
#创建每次要备份的目录
path="${WORKSPACE}/bak/${BUILD_NUMBER}"
echo "$path"
echo "-d $path"
if [ -d $path ];
then
echo "The files is already exists "
else
mkdir -p $path
fi
##############
#进入备份目录
cd ${WORKSPACE}/bak/$version
#这里cjkj-sass-web是你打包的jar包的名字
if [ -d ${WORKSPACE}target/ ];
then
echo "The files is already exists "
else
mkdir -p ${WORKSPACE}/target/
fi
#将备份拷贝到程序打包目录中,并覆盖之前的jar包
\cp -f *.jar ${WORKSPACE}/target/
######拷贝回滚jar包到最新备份目录保证最新备份永远是没问题的jar包########
\cp -f *.jar $path
echo "Completing!"
####################################
;;
*)
esac
#####################################################
#保留文件数
ReservedNum=5
FileDir=${WORKSPACE}/bak/
date=$(date "+%Y%m%d-%H%M%S")
#进入备份目录
cd $FileDir
#当前有几个文件夹,即几个备份
FileNum=$(ls -l | grep '^d' | wc -l)
while(( $FileNum > $ReservedNum))
do
#获取最旧的那个备份文件夹
OldFile=$(ls -rt | head -1)
echo $date "Delete File:"$OldFile
rm -rf $FileDir/$OldFile
let "FileNum--"
done
8、执行shell
#设置项目名的变量
project="cjkj-sassweb"
#创建应用服务器的所需目录
ssh jenkins@IP地址 "mkdir -p /data/apps/$project/{temp,logs}"
ssh jenkins@IP地 "mkdir -p /data/logs/$project"
#使用机器上脚本进行服务更新过程
ssh jenkins@IP地 "bash /data/apps/deploy.sh $project"
四、配置java应用节点的shell脚本
#!/bin/bash
#将jenkins的第一个变量参数传递过来$1=cjkj-appweb
PROJECT="$1"
#判断Jenkins的变量参数是否传递过来
if [ -z "$PROJECT" ]; then
echo "cannot be empty"
exit 1
else
echo "传递参数:$PROJECT"
fi
#将jar包路径和日志路径赋值
DEPLOY_DIR="/data/apps/$PROJECT"
APP_LOG="/data/logs/$PROJECT"
#将java应用的物理限制赋值
JAVA_OPTS="-Xms512m -Xmx512m -Xmn256m -Xss256K -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"
#定义当前环境(测试环境或者线上环境)
springProf="test"
#springProf="prod"
#刷新环境变量
source /etc/profile
[ -f "${DEPLOY_DIR}/.env" ] && source $DEPLOY_DIR/.env
#停止old版本应用
pid=$(jps | grep $PROJECT | awk '{print $1}')
if [ -n "$pid" ]; then
kill -15 $pid
sleep 15
ps aux | grep $pid
if [ $? -eq 0 ]; then
kill -9 $pid
echo "强制killed进程"
else
echo "进程已结束"
fi
else
echo "no pid"
fi
#拷贝新的jar包到指定服务器的指定目录
scp root@172.16.148.135:/var/lib/jenkins/workspace/$PROJECT/target/*.jar /data/apps/$PROJECT/$PROJECT.jar
if [ $? -eq 0 ]; then
echo "将新的jar包拷贝到指定目录"
else
echo "jar包拷贝失败"
fi
#启动new版本应用
nohup java -Dbasedir=${DEPLOY_DIR} -DLOGS_FOLDER=${APP_LOG} ${JAVA_OPTS} -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${DEPLOY_DIR}/temp \
-Dsecurerandom.source=file:/dev/urandom -Djava.security.egd=file:/dev/./urandom -Dnetworkaddress.cache.ttl=10 -Dsun.net.inetaddr.ttl=10 \
-verbose:gc -Xloggc:${APP_LOG}/gc_start_at_`date '+%Y%m%d%H%M%S'`.log \
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+DisableExplicitGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSParallelInitialMarkEnabled -XX:+PrintGCDetails -XX:+CMSScavengeBeforeRemark -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=${APP_LOG}/dump.hprof -DAPP_LOG_HOME=${APP_LOG}/ \
-XX:ErrorFile=${APP_LOG}/java_error.log -server -jar ${DEPLOY_DIR}/*.jar --spring.profiles.active=$springProf --server.tomcat.accesslog.enabled=true > $APP_LOG/start_`date '+%Y%m%d%H%M%S'`.log &
#检查新版本应用是否健康启动
ps aux | grep $PROJECT | grep -v grep
if [ $? -eq 0 ]; then
echo "$PROJECT running"
else
echo "$PROJECT Startup failed"
fi