之前说过很长一段时间内,我使用jenkins仅仅是涉及两个地方:配置svn版本,点击立即构建。
所以一直特别好奇jenkins的各个插件究竟是怎么工作的。然后最近研究了一下我这边用上的几个插件,虽然不够透彻,但好歹对jenkins的构建过程有了一定程度的了解^_^
Ant
jenkins是如何利用ant编译程序并打成war包的呢?ant是基于build.xml工作的。所以我研究了一下build.xml的具体内容:
【可参考http://www.cnblogs.com/xionghui/archive/2012/03/13/2393679.html,博主写的非常详细】
<?xml version="1.0" encoding="UTF-8"?> <!--<project>标签: (1) name:项目名称。这个属性即在jenkins新建任务时配置Invoke Ant 填写的targets。如以上代码 有两个target--"local"和"remote",指向不同的文件路径,ant会根据target name去执行task。 (2) default:默认的运行目标,这个属性是必须的。可以直接在cmd窗口执行ant命令更利于理解:进入 源码目录,键入ant回车,因为没有带上target name,ant直接按照默认的target "local"执行 task,也可以键入ant remote回车,ant即按照target "remote"执行task (3) basedir:项目的基准目录。"."即以jenkins_home为基准目录,生成的文件都以 {jenkins_home}\jobs\{project.name}\workspace为根目录--> <project name="MyFirstJob" default="local" basedir="."> <!--<property/> 通常把用到的路径、名称都在这里定义成全局变量 --> <!--ervironment 类型,主要的系统环境属性:由Ant构建文件调用的外部命令或程序,<env>元素制定了 哪些环境变量要传给正在执行的系统命令--> <property environment="env" /> <property name="java.home.dir" value="${env.JAVA_HOME}" /> <property name="tomcat.home.dir" value="${env.CATALINA_HOME}" /> <!--源码及配置文件路径--> <property name="src.dir" value="src" /> <property name="webroot.dir" value="WebContent" /> <property name="web-inf.dir" value="${webroot.dir}/WEB-INF" /> <property name="meta-inf.dir" value="${webroot.dir}/META-INF" /> <property name="configuration-local.dir" value="configuration-local" /> <property name="configuration-remote.dir" value="configuration-remote" /> <!--项目用到的jar包路径--> <property name="java.lib.dir" value="${java.home.dir}/lib" /> <property name="tomcat.lib.dir" value="${tomcat.home.dir}/lib" /> <property name="project.lib.dir" value="${web-inf.dir}/lib" /> <!--编译的属性变量--> <property name="compile.debug" value="true" /> <property name="compile.deprecation" value="true" /> <property name="compile.optimize" value="true" /> <!--war包路径--> <property name="release.dir" value="release" /> <!--定义存放编译文件的路径"{jenkins_home}\jobs\FirstJob\workspace\build\classes"--> <property name="output.dir" value="build/classes" /> <path id="classpath"> <pathelement location="${output.dir}" /> <fileset dir="${java.lib.dir}"> <include name="*.jar" /> </fileset> <fileset dir="${tomcat.lib.dir}"> <include name="*.jar" /> </fileset> <fileset dir="${project.lib.dir}"> <include name="**/*.jar" /> </fileset> </path> <!--初始化任务,清除旧的目录,创建新的目录--> <target name="init"> <delete dir="${output.dir}" /> <delete dir="${release.dir}" /> <delete dir="${web- inf.dir}/classes}" /> <mkdir dir="${output.dir}" /> </target> <!--编译源代码任务,基于初始化任务,编译生成的文件放在${output.dir},并把该文件夹copy到${web-inf.dir}/classes--> <target name="compilesrc" depends="init"> <javac srcdir="src" destdir="${output.dir}" includeantruntime="false" deprecation="${compile.deprecation}" debug="${compile.debug}" optimize="${compile.optimize}" encoding="UTF-8"> <classpath refid="classpath" /> </javac> <copy todir="${web-inf.dir}/classes"> <fileset dir="${output.dir}" /> </copy> </target> <!--将除源码外的可配置文件copy到${web-inf.dir}/classes,overwrite=true表示覆盖源文件, 以${webroot.dir}为准目录将所有文件打成war包存放到${release.dir}--> <target name="local" depends="compilesrc"> <copy file="${configuration-local.dir}/web.config" tofile="${web-inf.dir}/classes/web.config" overwrite="true"/> <copy file="${configuration-local.dir}/web.xml" tofile="${web-inf.dir}/web.xml" overwrite="true"/> <copy file="${configuration-local.dir}/log4j.properties" tofile="${web-inf.dir}/log4j.properties" overwrite="true"/> <war destfile="${release.dir}/MyFirstJob.war" basedir="${webroot.dir}" webxml="${web-inf.dir}/web.xml" /> </target> <target name="remote" depends="compilesrc"> <copy file="${configuration-remote.dir}/web.config" tofile="${web-inf.dir}/classes/web.config" overwrite="true"/> <copy file="${configuration-remote.dir}/web.xml" tofile="${web-inf.dir}/web.xml" overwrite="true"/> <copy file="${configuration-remote.dir}/log4j.properties" tofile="${web-inf.dir}/log4j.properties" overwrite="true"/> <delete file="${meta-inf.dir}/context.xml"/> <war destfile="${release.dir}/MyFirstJob.war" basedir="${webroot.dir}" webxml="${web-inf.dir}/web.xml" /> </target> </project>
2.svn
jenkins安装的时候默认安装了svn插件。
配置项目的时候,源码管理选择"Subversion"
Repository URL填入源码的svn路径,可以在路径后面加上@版本号,如@1251jenkins则会从 svndownload1251版本的代码
3.deploy
将war包远程到服务器上。
那么问题来了,jenkins是如何得知war包将放到什么位置呢?
还记得在“jenkins部署java项目之小白的笔记”配置deploy环节吗,当时我配置的Tomcat URL=http://localhost:8080,因为localhost:8080是本地的指向本地tomcat,所以war包将发送到
${env.CATALINA_HOME}/webapps
在此之前我所操作的步骤都是基于本地,但实际上java项目一般都是放到linux机器来运行,那么
接下来说说deploy插件将war远程到linux机器上。
因为8080是tomcat的默认端口,所以一般对于基于tomcat运行的项目会另外配置一个端口号,具体
步骤如下:
(1)在apach目录下新建一个文件夹,以项目名称命名[当然文件夹路径和项目名称也可以按个
人喜好自取]
cd apache-tomcat mkdir MyFirstJob
(2)在项目文件下新建三个文件夹,并将tomcat的相应内容copy过来
cd MyFirstJob mkdir conf mkdir webapps mkdir temp cp -r /home/tomcat/apache-tomcat/conf/server.xml /home/tomcat/apache-tomcat/testJob/conf/ cp -r /home/tomcat/apache-tomcat/conf/tomcat-users.xml /home/tomcat/apache-tomcat/testJob/conf/ cp -r /home/tomcat/apache-tomcat/conf/web.xml /home/tomcat/apache-tomcat/testJob/conf/ cp -r /home/tomcat/apache-tomcat/webapps/manager /home/tomcat/apache-tomcat/testJob/webapps
(3)对server.xml及tomcat-user.xml,context.xml进行编辑,使用vi命令,此处不再一一赘述,仅给出最后范本
cat server.xml
<Server port="${tomcat.server.port}" shutdown="SHUTDOWN"> <GlobalNamingResources> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <Service name="Catalina"> <Connector port="${tomcat.http.port}" protocol="HTTP/1.1" connectionTimeout="3600000" acceptorThreadCount="3" redirectPort="8443" maxThreads="400" /> <Connector port="${tomcat.ajp.port}" protocol="AJP/1.3" redirectPort="8443" /> <Engine name="Catalina" defaultHost="localhost" jvmRoute="${tomcat.instance.name}"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" deployOnStartup="false"> <!--localhost_access_log记录收到的serverlet请求,如果把下面这一段注释则不会记录accesslog--> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs/${tomcat.instance.name}" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>
cat tomcat-user.xml
<?xml version='1.0' encoding='utf-8'?> <role rolename="manager-gui"/> <role rolename="manager-script"/> <user username="system" password="password" roles="manager-gui, admin-gui,manager-script"/> </tomcat-users>
修改server.xml,主要是为了设置端口号及配置deploy属性,该文件中的变量值都是从启动项目的可执行文件中获取的,即我在第(4)步将中提到的MyFirstJob-startup.sh
修改tomcat-user.xml前面也提到过,因为jenkins在配置deploy是需要填写的用户名和密码即来自该处
context.xml是配置数据库连接,此处就不提供详细内容了~
(4)新建编辑启动项目的可执行文件MyFirstJob-startup.sh,它的作用同同${env.CATALINA_HOME}/bin/startup.bat。我在本地部署项目的时候,上面提到jenkins会将war包打到${env.CATALINA_HOME}/webapps,之后双击${env.CATALINA_HOME}/bin/startup.bat,tomcat会自动解压war包并启动项目,因为项目现在需要部署在linux机器上,同样需要.sh一个可执行文件来启动项目
cd conf vi MyFirstJob-startup.sh
#!/bin/sh export CATALINA_HOME=$CATALINA_HOME7 export TOMCAT_HOME=$TOMCAT_HOME7 export CATALINA_OPTS="-agentpath:/home/tomcat/soft/jprofiler8/bin/linux-x64/libjprofilerti.so=port=8849,nowait -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.xx.xx -Dtomcat.server.port=7001 -Dtomcat.http.port=8001 -Dtomcat.ajp.port=9001 -Dtomcat.instance.name=MyFirstJob -Xms8192m -Xmx8192m -XX:PermSize=1024m -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseConcMarkSweepGC -XX:+UseParNewGC" export CATALINA_OUT="/home/tomcat/apache-tomcat/MyFirstJob/logs/Catalina/catalina.$(date +'%Y-%m-%d').out" export CATALINA_PID="/home/tomcat/apache-tomcat/tomcat-MyFirstJob.pid" export CATALINA_BASE="/home/tomcat/apache-tomcat/MyFirstJob" export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TOMCAT_HOME/lib:/usr/local/apr/lib:/usr/local/apr rm -rf /home/tomcat/apache-tomcat/MyFirstJob/work /home/tomcat/apache-tomcat/bin/catalina.sh start exit $?
ps:端口号可自行更换
再将MyFirstJob-startup.sh变成一个可执行文件,之后可以看到文件变成粗体,ll命令也可以看到权限改变。
chmod a+x MyFirstJob-startup.sh ll conf
-rwxrwxr-x 1 tomcat tomcat 1072 Apr 9 15:10 MyFirstJob-startup.sh
-rw------- 1 tomcat tomcat 6466 Apr 9 12:05 server.xml
-rw------- 1 tomcat tomcat 1530 Apr 9 12:05 tomcat-users.xml
-rw------- 1 tomcat tomcat 162905 Apr 9 12:06 web.xml
安装过tomcat的童鞋都知道tomcat由startup.bat启动,由shutdown.bat停止
vi MyFirstJob-shutdown.sh
#!/bin/sh export JAVA_OPTS="-Dtomcat.server.port=7001" export CATALINA_HOME=$CATALINA_HOME7 export TOMCAT_HOME=$TOMCAT_HOME7 export CATALINA_PID="/home/tomcat/apache-tomcat/tomcat-MyFirstJob.pid" export CATALINA_BASE="/home/tomcat/apache-tomcat/MyFirstJob" /home/tomcat/apache-tomcat/bin/catalina.sh stop 0 -force exit $?
现在执行
./MyFirstJob-startup.sh
可以试着访问http://192.168.xx.xxx:8001,如果没有问题的话是可以访问的,虽然返回的是一个空白网页,然后可以访问http://192.168.xx.xxx:8001/manager,用户名和密码就是tomcat-user.xml配置的,也就是deploy中需要配置的用户名密码,在返回的页面上也可以看见deploy功能,至此,我也终于明白了jekins的deploy插件是如何工作的。其实原理和manager下面提供的这个deploy功能一样,只是jenkins通过deploy的插件去访问http://192.168.xx.xxx:8001,然后根据MyFirstJob-startup.sh获得项目指向路径,将war包发送到相应路径
CATALINA_BASE="/home/tomcat/apache-tomcat/MyFirstJob