Jenkins中通过execute shell无法启动tomcat
一、问题描述
环境:
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-jarjenkins.war 2.2、使用Tomcat启动,Linux系统修改catalina.sh,在环境变量的说明后,脚本开始前加上 JAVA_OPTS="$JAVA_OPTS-Dhudson.util.ProcessTree.disable=true" Windows系统修改catalina.bat,在环境变量的说明后,脚本开始前加上 setJAVA_OPTS=%JAVA_OPTS%"-Dhudson.util.ProcessTree.disable=true" 修改好Tomcat的配置文件后重新启动Tomcat
三、最后附上完整脚本
192.168.2.17服务器上shell脚本
#!/bin/bash exportBUILD_ID=dontkillme#随便写 exportJAVA_HOME=/usr/java/jdk1.7.0_80#tomcat需要的jdk # #__auther__:zhan #__time__:2018年08月16日22:00:00 #__作用__:用于jenkinsbuild完成之后的最后操作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服务器备份文件------------------------------------- echogoto$BACKUP_HOME cd$BACKUP_HOME echobackuptime$BACK_TIME /bin/mkdir$BACK_TIME echogoto$BACK_TIME cd$BACK_TIME echo"backuppath" pwd echo"startcopyprojectfiles" #复制项目文件 cp$PUBLISHED_PATH.-R #-------------------------------tomcat服务器解压war包--------------------------------------- #进入要发布版本的文件夹 cd$PUBLISHVERSION_HOME echo"goto$PUBLISHVERSION_HOME" #解压前先删除旧解压后的文件 rm-rf$WAR__NAME echo"rmsuccessfull" #解压项目war包 /bin/unzip$WAR__NAME.war-d$WAR__NAME/&>/dev/null echo"unzipsuccessfull" #复制远程服务器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.warrmsuccessfull" --------------------------------------------说明---------------------------------------------------------------------------------- #下面的命令会将【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/servicetomcatstop #$TOMCAT_HOME/bin/shutdown.sh cd$TOMCAT_HOME/bin #查看进程 ps-ef|grep$TOMCAT_HOME|grep-vgrep|grep-vkill #上一个命令退出后就执行kill进程号,否则是执行下一个语句说明 #【if[$-eq0]:代表上一个命令执行后的退出状态:0为成功,非0为失败】 if[$-eq0];then kill-9`ps-ef|grep$TOMCAT_HOME|grep-vgrep|grep-vkill|awk'{print$2}'` sleep3 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/servicetomcatstart $TOMCAT_HOME/bin/startup.sh #tail-f$TOMCAT_HOME/logs/catalina.$timedate.out