一、问题描述
环境:
192.168.2.20 jenkins服务器
192.168.2.17 tomcat服务器
设置jenkins与tomcat服务器相互免密钥登陆,shell在远程的tomcat服务器上的,用jenkins控制台去调用shell脚本。
用jekins+shell搭建自动化部署更新tomcat,脚本在Linux下运行一切正常,但是当用jenkins构建完毕后,发现shell脚本会将tomcat停止,但是却怎么也无法再次启动tomcat,查了权限问题,脚本问题等等都无法解决,后经过不懈之努力,测试发现,当jekins中只有一个工程(tomcat项目)的时候是正常的,但是有多个工程(tomcat项目)就无法启动,最后在网上查资料知道是jenkins的问题。原因如下:
Jenkins会在构建完成后使用processTreeKiller杀掉了所有子进程,而且这是Jenkins的默认行为。其实回头来看这个问题,就发现Jenkins的做法非常合理。当一次build异常结束,或被人终止时,必然需要结束所有这次build启动的子进程。
构建后报错如下图:
百度很多说明都是需要在脚本头部加上export BUILD_ID="xxxxxx"随便写,可以通过改变BUILD_ID的值来防止后台进程被杀死。但是我试过在我这边加了这个没有作用的,最后才想到上面那个找不到jdk或者jre路径的提示,感觉脚本中startup.sh 启动的不是项目Tomcat,而是Jenkins自身Tomcat,于是修改项目Tomcat的catalina.sh, 重新设置了Tomcat启动需要的变量或在脚本头部加上“export JAVA_HOME=xxxx”;
在次构建项目,项目Tomcat启动成功。此时,Jenkins控制台输出的环境变量也变成了项目Tomcat路径,不再是JenkinsTomcat路径。
原因分析(个人理解):项目Tomcat未启动应该环境变量的问题,脚本./startup.sh启动了一个tomcat, 但启动的是Jekins本身的TOMCAT , 不是cd到目录下的目标TOMCAT,正常在服务器cd到对应目录, 此时环境变更(CATALINA_BASE、CATALINA_HOME、CATALINA_TMPDIR、JRE_HOME、CLASSPATH)没值,./startup.sh默认使用当前目录Tomcat路径,故可正常启动当前目录下的TOMCAT;而在Jenkins的脚本中,Jenkins是用TOMCAT启的, 启动的时候设置了环境变量, 要启动的目标TOMCAT是通过Jenkins启动的, 延用了Jenkins的环境变量,其startup.sh (其实是 CATALINA.sh)运行时上述几个环境变量还是Jenkins的值,故再一次启动了Jenkins的TOMCAT,而不是目标TOMCAT。
二、通过Jenkins提供的启动参数禁用杀死子进程的特性
2.1、使用java -jar启动,-Dhudson.util.ProcessTree.disable=true -jar jenkins.war 2.2、使用Tomcat启动,Linux系统修改catalina.sh,在环境变量的说明后,脚本开始前加上 JAVA_OPTS="$JAVA_OPTS -Dhudson.util.ProcessTree.disable=true" Windows系统修改catalina.bat,在环境变量的说明后,脚本开始前加上 set JAVA_OPTS=%JAVA_OPTS% "-Dhudson.util.ProcessTree.disable=true" 修改好Tomcat的配置文件后重新启动Tomcat
三、最后附上完整脚本
192.168.2.17服务器上shell脚本
#!/bin/bash export BUILD_ID=dontkillme #随便写 export JAVA_HOME=/usr/java/jdk1.7.0_80 #tomcat需要的jdk # # __auther__: zhan # __ time __: 2018年08月16日 22:00:00 # __ 作用 __: 用于jenkins build完成之后的最后操作shell脚本 # __ 使用 __: 定义jenkins # #---------------------------------- 文件路径配置 ---------------------------------- #tomcat服务器获取系统时间以 2018-08-16 显示 timedate=$(date +%Y-%m-%d) #client服务器tomcat安装路径 TOMCAT_HOME=/web/tomcat-jih-8080 #tomcat服务器备份文件存放路径 BACKUP_HOME=$TOMCAT_HOME/bak #tomcat服务器war包服务器更新包名称 WAR__NAME=yk #tomcat服务器最新版本文件存放路径 PUBLISHVERSION_HOME=/web/appwar/yk #client服务器以时间的方式备份发布前的项目文件目录名称 BACK_TIME=`date +%Y%m%d%H%M` #tomcat服务器项目发布后的路径 PUBLISHED_PATH=$TOMCAT_HOME/webapps/$WAR__NAME #war包远程jenkins服务器项目配置文件 PROJECT_CONFIG_FILE=/web/appwar/yk/classes #war包远程jenkins服务器地址 WAR_SERVER_IP='192.168.2.20' #war包远程jenkins服务器存放路径 WAR_SERVER_HOME='/web/appwar/yk' #---------------------- 远程复制war包 [需要SSH免密码登陆设置]------------------- #复制远程jenkins服务器war包到tomcat服务器上最新版本文件存放路径 scp -r $WAR_SERVER_IP:/$WAR_SERVER_HOME/$WAR__NAME.war $PUBLISHVERSION_HOME #--------------------------------- tomcat服务器备份文件 ------------------------------------- echo go to $BACKUP_HOME cd $BACKUP_HOME echo backup time $BACK_TIME /bin/mkdir $BACK_TIME echo go to $BACK_TIME cd $BACK_TIME echo "backup path" pwd echo "start copy project files" #复制项目文件 cp $PUBLISHED_PATH . -R #------------------------------- tomcat服务器解压war包 --------------------------------------- #进入要发布版本的文件夹 cd $PUBLISHVERSION_HOME echo "go to $PUBLISHVERSION_HOME" #解压前先删除旧解压后的文件 rm -rf $WAR__NAME echo "rm successfull" #解压项目war包 /bin/unzip $WAR__NAME.war -d $WAR__NAME/ &>/dev/null echo "unzip successfull" #复制远程服务器war包最新配置文件到本地服务器配置文件存放路径 scp -r $WAR_SERVER_IP:/$PROJECT_CONFIG_FILE/* $PUBLISHVERSION_HOME/$WAR__NAME/WEB-INF/classes #最后删除war包,以便下次更新下载最新war包 rm -rf $WAR__NAME.war echo "$WAR__NAME.war rm successfull" -------------------------------------------- 说明 ---------------------------------------------------------------------------------- #下面的命令会将【PROJECT_CONFIG_FILE=/web/appwar/yj/classes】classes目录给拷贝到本地文件的properties目录的 #scp -r $WAR_SERVER_IP:/$PROJECT_CONFIG_FILE/ $PUBLISHVERSION_HOME/$WAR__NAME/WEB-INF/classes/properties #将远程【PROJECT_CONFIG_FILE=/web/appwar/yj/classes】classes目录下的所有文件(不包含classes目录)拷贝本地properties目录下 #scp -r $WAR_SERVER_IP:/$PROJECT_CONFIG_FILE/* $PUBLISHVERSION_HOME/$WAR__NAME/WEB-INF/classes/properties #将远程classes目录下的文件拷贝本地classes目录下 #scp -r $WAR_SERVER_IP:/$PROJECT_CONFIG_FILE/* $PUBLISHVERSION_HOME/$WAR__NAME/WEB-INF/classes #或者用scp -r $WAR_SERVER_IP:/$PROJECT_CONFIG_FILE/ $PUBLISHVERSION_HOME/$WAR__NAME/WEB-INF到这里即可,就直接将classes目录放到WEB-INF下面了 -------------------------------------------- 说明 ---------------------------------------------------------------------------------- #------------------------------- tomcat服务器部署文件 --------------------------------------- #关闭tomcat #/sbin/service tomcat stop #$TOMCAT_HOME/bin/shutdown.sh cd $TOMCAT_HOME/bin #查看进程 ps -ef|grep $TOMCAT_HOME|grep -v grep|grep -v kill #上一个命令退出后就执行kill进程号,否则是执行下一个语句说明 #【if [ $? -eq 0 ]:代表上一个命令执行后的退出状态:0为成功,非0为失败】 if [ $? -eq 0 ];then kill -9 `ps -ef|grep $TOMCAT_HOME|grep -v grep|grep -v kill|awk '{print $2}'` sleep 3 echo "停止tomcat服务成功" else echo $TOMCAT_HOME ' 该目录进程已KILL或项目未启动' fi #删除项目文件 rm -rf $PUBLISHED_PATH/* #删除临时文件、log日志 rm -rf $TOMCAT_HOME/temp/* rm -rf $TOMCAT_HOME/conf/Catalina/* rm -rf $TOMCAT_HOME/work/* #拷贝最新版本更新文件到项目发布路径下 cp $PUBLISHVERSION_HOME/$WAR__NAME/* $PUBLISHED_PATH/ -R #复制配置文件 # cp $PUBLISHVERSION_HOME/classes/* $PUBLISHED_PATH/WEB-INF/classes -R #启动tomcat,使用service命令时,使用普通用户需要输入密码,所以直接暂不采用service的方式启动和关闭tomcat #/sbin/service tomcat start $TOMCAT_HOME/bin/startup.sh #tail -f $TOMCAT_HOME/logs/catalina.$timedate.out
转载于:https://blog.51cto.com/meiling/2333265