当前位置: > 其它学习 > Jenkins >

Jenkins中通过execute shell无法启动tomcat

时间:2018-12-20 16:55来源:未知 作者:IT

一、问题描述

环境:

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启动的子进程。

图片.png

    构建后报错如下图:

图片.png

百度很多说明都是需要在脚本头部加上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路径。

图片.png

    原因分析(个人理解):项目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


(责任编辑:IT)
------分隔线----------------------------