http://blog.sina.com.cn/s/blog_61aed0450100r0x6.html
1Ant的安装
(1)在官方网站http://ant.apache.org/下载apache-ant-1.8.1-bin.tar.gz二进制版本包。
(2)使用命令tar -zxvf apache-ant-1.8.1-bin.tar.gz解压。
(3)将解压好的文件夹apache-ant-1.8.1-bin移动到到需要的安装目录中,例如/usr/local目录下,可以根据需要重命名为apache-ant或apache-ant-1.8.1等。
2设置环境变量
(1)vi /etc/profile 增加两行
ANT_HOME=/usr/local/apache-ant-1.8.1
export ANT_HOME
一般情况下,该配置与JAVA,TOMCAT的配置一起写例如:
JAVA_HOME=/usr/java/jdk1.5.0_22
ANT_HOME=/usr/local/apache-ant-1.8.1
TOMCAT_HOME=/usr/apache-tomcat-6.0.26
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$TOMCAT_HOME/lib
PATH=$JAVA_HOME/bin:$TOMCAT_HOME/bin:$ANT_HOME/bin:$PATH
export LANG JAVA_HOME ANT_HOME CLASSPATH TOMCAT_HOME PATH
(2)应用该文件 source /etc/profile 或者重启电脑生效
在某些机器上如果环境变量无法自动加载,尝试把以上代码放到~/.bash_rc中
(2)打开一个新的终端,在命令行中输入ant出现以下提示
Buildfile: build.xml does not exist!
Build failed
表明ant环境变量已经配好
3配置build.xml
(1)完整的build.xml事例见附属文件build.xml。
(2)需要注意的是,如果java文件里含有中文,编译时有可能不能识别,故要在build.xml文件中的调用javac的地方加入encoding的参数。
如下所示:
<javac encoding="utf-8" destdir="${compile.dir}" debug="on" source="1.5">
<src path="${src.java.dir}"/>
<patternset refid="compile.sources"/>
<classpath>
<path refid="compile.dependencies"/>
</classpath>
</javac>
(3)如果要在重新构建时避免删除一些测试资源目录可以在删除时使用exclude(排除),代码如下:
<delete dir="${webapps.dir}/${cvs.projectName}" includeemptydirs="true" fail>
<exclude name="image*"/>
</delete>
(4)build.xml指定属性放在build.properties文件(见附属文件),需要根据具体情况改动,以下红色部分是必须改动的部分
base.dir=./temp/
baselib.dir=${base.dir}/lib
src.dir=${base.dir}/src
build.dir=${base.dir}/build
dest.dir=${base.dir}/dist
doc.dir=${base.dir}/javadoc
webapps.dir=/usr/apache-tomcat-6.0.26/webapps //tomcat的服务目录
cvs.server=10.0.0.1 //服务器IP地址
cvs.user=username //cvs用户名
cvs.pw=password //cvs密码
cvs.repositoryPath=/usr/cvs_home //cvs主目录
cvs.projectName=test //项目名,同时也是cvs模块名、网站目录名
cvs.root=:pserver:${cvs.user}:${cvs.pw}@${cvs.server}:${cvs.repositoryPath}
cvs.tag=
4执行ant
(1)进入build.xml所在目录,执行ant命令,或者在其他目录输入 ant -file build.xml执行
5配置ant定时执行
(1)检查crontab服务是否启动。如果没有启动,启动命令service crond start
(2)在终端中输入crontab -e,加入以下定时命令(这些命令要写在一行内)
16 * * * * export CLASSPATH=.:/usr/java/jdk1.5.0_22/lib:/usr/java/jdk1.5.0_22/jre/lib; export PATH=/usr/java/jdk1.5.0_22/bin:/usr/local/apache-ant-1.8.1/bin:$PATH; ant -file /usr/apache-tomcat-6.0.26/webapps/ant/build.xml > /var/log/ant.log 2>&1
该命令表示每个小时的第16分钟自动执行该命令。该命令包含设置环境变量,执行操作和输出日志三部分,其中可以省略输出日志,输出日志是为了出错时查看错误。
6ant常见问题分析
(1)编译是出现不能识别乱码,解决方法见上文的build.xml配置。
(2)提示找不到某些类。有些类的jar包在tomcat的lib目录中,但ant找不到,解决办法之一是把tomcat lib目录中的jar包复制到ant的lib目录中。
(3)提示cvs退出,因为code问题。建议删除ant构建目录中src的文件,重新编译,才能看出真正的问题所在,实际的问题可能是前面两项或其他错误。
7使用cruisecontrol持续集成工具控制ant自动构建
如果使用cruisecontrol工具就可以不配置crontab了。Cruisecontrol会定时(比如一分钟一次)检测cvs(或其他代码库)中代码是否有更新,如果有更新就重新构建。
(1)从http://cruisecontrol.sourceforge.net/下载cruisecontrol-bin-2.8.4.zip(linux版)。使用unzip命令解压。把解压好的文件放到选定的目录例如/usr/local打开cruisecontrol文件夹下的/etc/jetty.xml,配置jetty服务器的端口为8082,或其他端口,不与其他服务端口冲突即可。
<New class="org.mortbay.jetty.nio.SelectChannelConnector">
<Set name="host"><SystemProperty name="jetty.host" /></Set>
<Set name="port"><SystemProperty name="jetty.port" default="8082"/></Set>
<Set name="maxIdleTime">30000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">5000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
(2)执行./cruisecontrol.sh启动cruisecontrol
启动完成后在别的机器上访问http://10.0.0.1:8082/dashboard/可以看到cruisecontrol的控制台。
访问http://10.0.0.1:8082/cruisecontrol/可以看到一个默认的项目connectfour,点击右边的build可以构建该项目。
(3)准备根据不同的情况定制自己的config.xml。默认的config.xml是为connectfour项目准备的,使用了cruisecontrol自带的ant。
我们打算配置一个使用自己安装的ant而不是自带的ant,同时使用cvs版本控制的config.xml。
<cruisecontrol>
<project name="test"><!--项目名-->
<listeners>
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
<bootstrappers>
<cvsbootstrapper localWorkingCopy="projects/${project.name}" /><!--cvs代码库的一个拷贝存放地址-->
</bootstrappers>
<modificationset quietperiod="30">
<!-- touch any file in project to trigger a build -->
<cvs localworkingcopy="projects/${project.name}"/>
<!--触发构建的文件存放地址与cvsbootstrapper 中的相同-->
</modificationset>
<!-- 60表示每隔60秒执行一次,发现代码库有变就执行构建-->
<schedule interval="60">
<ant anthome="/usr/local/apache-ant-1.8.1" buildfile="/usr/local/apache-ant-1.8.1/build/build.xml"/><!--自定义的ant地址和build.xml构建文件地址-->
</schedule>
<log>
<merge dir="projects/${project.name}/target/test-results"/>
</log>
<publishers>
<onsuccess>
<artifactspublisher dest="artifacts/${project.name}" file="projects/${project.name}/target/${project.name}.war"/><!--对于web项目使用war包-->
</onsuccess>
</publishers>
</project>
</cruisecontrol>.
config.xml标签和属性的具体含义参见http://10.0.0.1:8082/documentation/。也可以到官方网站上查阅。
(4)check cvs项目的一个最新版本放到cruisecontrol的project文件夹中。如果之前使用过过ant那么从ant构建的src文件夹中以项目名命名的文件夹即可。
(5)完成以上工作后,可以通过http://10.0.0.1:8082/cruisecontrol/手动构建项目,也可以等待cruisecontrol定时自动构建项目。
附属的文件如下:
build.properties:
base.dir=./temp/
baselib.dir=${base.dir}/lib
src.dir=${base.dir}/src
build.dir=${base.dir}/build
dest.dir=${base.dir}/dist
doc.dir=${base.dir}/javadoc
webapps.dir=/usr/apache-tomcat-6.0.26/webapps
cvs.server=10.0.0.1
cvs.user=username
cvs.pw=password
cvs.repositoryPath=/usr/cvs_home
cvs.projectName=test
cvs.root=:pserver:${cvs.user}:${cvs.pw}@${cvs.server}:${cvs.repositoryPath}
cvs.tag=
--------------------------------------------------------------------------------
build.xml:
<?xml version="1.0"?>
<project name="testWeb" default="all" basedir=".">
<target name="all" depends="init,clean,checkout,build,unpack,javadoc">
<echo>all in ${cvs.projectName}</echo>
</target>
<target name="init">
<echo>init in ${cvs.projectName}</echo>
<property file="build.properties" />
<path id="class.path">
<fileset dir="${baselib.dir}" includes="*.jar"/>
</path>
</target>
<target name="clean">
<echo>clean in ${cvs.projectName}</echo>
<delete dir="${src.dir}/${cvs.projectName}" fail />
<delete dir="${build.dir}/${cvs.projectName}" fail />
<delete quiet="false">
<fileset dir="${dest.dir}" includes="*.*" />
</delete>
<delete dir="${doc.dir}" fail />
<delete dir="${webapps.dir}/${cvs.projectName}" fail />
</target>
<target name="checkout">
<echo>check out in ${cvs.projectName}</echo>
<cvs cvsRoot="${cvs.root}" package="${cvs.projectName}" tag="${cvs.tag}" dest="${src.dir}" fail />
</target>
<target name="build">
<echo>build class in ${cvs.projectName}</echo>
<mkdir dir="${build.dir}/${cvs.projectName}" />
<javac encoding="utf-8"
srcdir="${src.dir}" destdir="${build.dir}/${cvs.projectName}">
<classpath>
<path refid="class.path" />
</classpath>
</javac>
<echo>build ${cvs.projectName}.war in ${cvs.projectName}</echo>
<war destfile="${dest.dir}/${cvs.projectName}.war" webxml="${src.dir}/${cvs.projectName}/WebRoot/WEB-INF/web.xml">
<fileset dir="${src.dir}/${cvs.projectName}/WebRoot" />
<classes dir="${build.dir}/${cvs.projectName}" />
</war>
</target>
<target name="unpack">
<echo>unpack the ${cvs.projectName}.war in ${cvs.projectName}</echo>
<copy todir="${webapps.dir}">
<fileset dir="${dest.dir}" includes="*.*" />
</copy>
<unzip src="${webapps.dir}/${cvs.projectName}.war" dest="${webapps.dir}/${cvs.projectName}" />
<delete file="${webapps.dir}/${cvs.projectName}.war" />
</target>
<target name="javadoc">
<echo>generate the API documentation in ${cvs.projectName}</echo>
<javadoc destdir="${doc.dir}"
sourcepath="${src.dir}/${cvs.projectName}/src"
windowtitle="${cvs.projectName} API"
use="yes"
linksource="yes"
splitindex="yes"
encoding="UTF-8"
docencoding="UTF-8">
<classpath>
<path refid="class.path" />
</classpath>
</javadoc>
</target>
</project>
---------------------------------------------------------------------------
config.xml:
<cruisecontrol>
<project name="test">
<listeners>
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
<bootstrappers>
<cvsbootstrapper localWorkingCopy="projects/${project.name}" />
</bootstrappers>
<modificationset quietperiod="30">
<!-- touch any file in project to trigger a build -->
<cvs localworkingcopy="projects/${project.name}"/>
</modificationset>
<!-- 60表示每隔60秒执行一次,发现代码库有变就执行构建-->
<schedule interval="60">
<ant anthome="/usr/local/apache-ant-1.8.1" buildfile="/usr/local/apache-ant-1.8.1/build/build.xml"/>
</schedule>
<log>
<merge dir="projects/${project.name}/target/test-results"/>
</log>
<publishers>
<onsuccess>
<artifactspublisher dest="artifacts/${project.name}" file="projects/${project.name}/target/${project.name}.war"/>
</onsuccess>
</publishers>
</project>
</cruisecontrol>