Apache Ant 实现自动化部署

Apache Ant 实现自动化部署

http://www.netkiller.cn/journal/java.ant.html

Mr. Neo Chen (陈景峯), netkiller, BG7NYT

中国广东省深圳市龙华新区民治街道溪山美地
518131
+86 13113668890

<netkiller@msn.com>

版权声明

转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。

文档出处:
http://netkiller.github.io
http://netkiller.sourceforge.net

微信扫描二维码进入 Netkiller 微信订阅号

群:128659835 请注明“读者”

 

2015-12-10

这篇文章帮你解决下列问题:

源码获取,源码编译,处理配置文件,应用部署,远程备份,部署回撤,启动,服务器状态,停止

我的系列文档

编程语言

Netkiller Architect 手札 Netkiller Developer 手札 Netkiller PHP 手札 Netkiller Python 手札 Netkiller Testing 手札 Netkiller Cryptography 手札
Netkiller Perl 手札 Netkiller Docbook 手札 Netkiller Project 手札 Netkiller Java 手札 Netkiller DevOps 手札  

操作系统

Netkiller Linux 手札 Netkiller Debian 手札 Netkiller CentOS 手札 Netkiller FreeBSD 手札 Netkiller Shell 手札 Netkiller Security 手札
Netkiller Web 手札 Netkiller Monitoring 手札 Netkiller Storage 手札 Netkiller Mail 手札 Netkiller Multimedia 手札  

数据库

Netkiller Database 手札 Netkiller PostgreSQL 手札 Netkiller MySQL 手札 Netkiller NoSQL 手札 Netkiller LDAP 手札  

网络设备及其他

Netkiller Network 手札 Netkiller Cisco IOS 手札 Netkiller H3C 手札 Netkiller Amateur Radio 手札    

您可以使用iBook阅读当前文档


目录

1. 背景

在你的企业中是怎样完成从开发,测试到运维的?

很多企业的升级是这样做的,写完代码后编译打包,放到FTP上,同时发送一个升级邮件。然后让运维按照升级文档,一步一步操作。

这样的流程有很多问题

  1. 开发者通常是在Windows系统上完成开发与编译,而服务器通常是Linux操作系统,操作系统的差异可能导致编译后的程序运行不了。
  2. 安全角度,源码可以审查,但编译文件无法审查,打包过程可能被植入恶意代码
  3. 经常出现生产环境与本地开发环境不一致,运行有差异
  4. 浪费人力,理论上代码写完,就跟开发人员一点关系都没有了,但实际上每次升级过程开发与测试都需要在场

稍先进一点做法是使用Subversion/Git,开发将代码放到版本库中,运维直接使用 svn up / git pull 升级,这样做法也有很多问题存在

  1. 首次升级非常慢,svn 还好些,svn只取最后一次提交的版本;git 将所有的版本克隆到本地。
  2. 如果修改了本地文件,更新会产生冲突
  3. 配置文件无法个性化配置

2. 我们需要什么样的流程

我们需要什么样的流程或者什么样的流程才是最理想流程?

我认为:

  1. 开发人员不要做与开发无关的事情,代码写完就与开发没有半点关系了。通知测试人员,代码已经完成。
  2. 测试人员自己部署测试环境,不依赖开发人员,测试完成,通知运维人员可能升级了
  3. 运维人员不接受任何部门提供的打包或补丁程序,代码只能在配置管理服务器上完成编译打包以及部署。
  4. 升级应该由自动化工具完成,而不是人工操作。

开发,测试,运维各司其职,这就是DevOps。

3. 怎样实现自动部署

实现自动化部署有很多方法,很多年前笔者就开始研究总结,下面是一些经验分享。

3.1. 操作系统

开发,测试,生产三个环境的配置如果出自同一个模板会减少很多由于环境差异带来的困扰。

过程 1. 操作系统部署

  1. 无人值守安装

    通过无人值守脚本安装操作系统,减少人为安装造成的差异

  2. 运行环境

    统一配置运行环境,开发库以及版本统一

  3. 应用服务器统一

    应用服务器版本,安装标准,配置文件都需要统一,减少差异

3.2. 程序部署

实现应用程序自动部署,首先你要清楚自动部署所需要的流程,部署一个流程通常是这样的:

过程 2. 自动部署步骤

  1. 初始化

    建立工作环境,例如目录,检查所需环境

  2. 获取

    从版本库指定分支中获取代码并保存到本地

  3. 编译

    编译可执行代码

  4. 配置

    处理配置文件

  5. 备份

    备份应用程序

  6. 停止

    服务服务

  7. 部署

    部署应用程序到目的主机,如果已存在需要覆盖原来的程序

  8. 启动

    启动服务

3.3. 自动部署程序

自动部署程序完成上面的部署,还需要做下面一些事情。

日志功能

  1. 记录什么时间点做过部署
  2. 部署了那些文件

4. Apache Ant 实现自动化部署

4.1. 运行环境

准备一个全新的的服务器,最小化安装CentOS 7操作系统,然后运行下面脚本初始化

curl -s https://raw.githubusercontent.com/oscm/shell/master/os/centos7.sh | bash
curl -s https://raw.githubusercontent.com/oscm/shell/master/os/selinux.sh | bash
curl -s https://raw.githubusercontent.com/oscm/shell/master/os/iptables/iptables.sh | bash
curl -s	https://raw.githubusercontent.com/oscm/shell/master/os/ntpd/ntp.sh |	bash
curl -s	https://raw.githubusercontent.com/oscm/shell/master/os/ssh/sshd_config.sh	| bash
curl -s	https://raw.githubusercontent.com/oscm/shell/master/os/user/www.sh |	bash
curl -s	https://raw.githubusercontent.com/oscm/shell/master/lang/gcc/gcc.sh	| bash

安装 server-jre 与 apache-tomcat

curl -s	https://raw.githubusercontent.com/oscm/shell/master/lang/java/server-jre-8u40.sh	| bash
curl -s	https://raw.githubusercontent.com/oscm/shell/master/web/tomcat/apache-tomcat-8.0.26.sh	| bash
curl -s	https://raw.githubusercontent.com/oscm/shell/master/web/tomcat/systemctl.sh	| bash

请使用systemctl 启动与停止 Tomcat

systemctl start tomcat
systemctl stop tomcat

Infrastructure Management Shell https://github.com/oscm/shell

4.2. 部署机

安装Ant

curl -s	https://raw.githubusercontent.com/oscm/shell/master/lang/java/ant.sh | bash

下载build.xml文件 https://github.com/oscm/build/tree/master/Ant

wget https://raw.githubusercontent.com/oscm/build/master/Ant/build.xml			

打开 build.xml 文件

<?xml version="1.0" encoding="UTF-8" ?>
<!--
Homepage: http://www.netkiller.cn
Author: neo <netkiller@msn.com>
Date: 2015-12-07
-->
<project name="admin.example.com" default="compile" basedir=".">

	<property name="repository" value="git@58.96.11.18:example.com/admin.example.com.git" />
	<property name="branch" value="master" />

	<property name="remote" value="www@23.25.22.72" />
	<property name="destination" value="/www/example.com/admin.example.com" />

	<property name="project.dir" value="repository" />
	<property name="project.src" value="${project.dir}/src" />
	<property name="project.build" value="build" />
	<property name="project.config" value="config" />
	<property name="project.log" value="log" />

	<property name="pkg" value="example-1.0.0.jar" />

	<property name="backup.dir" value="backup" />
	<property name="receive.timepoint" value="2015-12-04.17:46:35" />

	<property name="build.sysclasspath" value="last" />
	<property environment="env" />
	<echo message="JAVA_HOME is set to = ${env.JAVA_HOME}" />
	<echo message="CATALINA_HOME is set to = ${env.CATALINA_HOME}" />

	<path id="classpath">
		<fileset dir="${env.JAVA_HOME}/lib">
			<include name="*.jar" />
		</fileset>
		<fileset dir="${env.CATALINA_HOME}/lib">
			<include name="*.jar" />
		</fileset>
		<fileset dir="${project.dir}/WebRoot/WEB-INF/lib" includes="*.jar" />
	</path>

	<macrodef name="git">
		<attribute name="command" />
		<attribute name="dir" default="" />
		<element name="args" optional="true" />
		<sequential>
			<!-- echo message="git @{command}" / -->
			<exec executable="git" dir="@{dir}">
				<arg value="@{command}" />
				<args />
			</exec>
		</sequential>
	</macrodef>

	<macrodef name="rsync">
		<attribute name="option" default="auzv" />
		<attribute name="src" default="" />
		<attribute name="dest" default="" />
		<element name="args" optional="true" />
		<sequential>
			<!-- echo message="rsync @{option} ${src} ${dest}" / -->
			<exec executable="rsync">
				<arg value="@{option}" />
				<args />
				<arg value="@{src}" />
				<arg value="@{dest}" />
			</exec>
		</sequential>
	</macrodef>

	<macrodef name="ssh">
		<attribute name="host" />
		<attribute name="command" />
		<attribute name="keyfile" default="~/.ssh/id_rsa" />
		<element name="args" optional="true" />
		<sequential>
			<exec executable="ssh">
				<arg value="@{host}" />
				<!-- arg value="-i @{keyfile}" / -->
				<args />
				<arg value="@{command}" />
			</exec>
		</sequential>
	</macrodef>

	<target name="dir.check">
		<condition property="dir.exists">
			<available file="${project.dir}" type="dir" />
		</condition>
	</target>

	<target name="clone" depends="dir.check" unless="dir.exists">
		<echo>clone</echo>
		<git command="clone">
			<args>
				<arg value="${repository}" />
				<arg value="${project.dir}" />
			</args>
		</git>
	</target>

	<target name="pull" depends="clone" if="dir.exists">
		<echo>${project.dir} exists</echo>
		<git command="pull" dir="${project.dir}" />
		<git command="clean" dir="${project.dir}">
			<args>
				<arg value="-df" />
			</args>
		</git>

		<git command="reset" dir="${project.dir}">
			<args>
				<arg value="HEAD" />
				<arg value="--hard" />
			</args>
		</git>
	</target>

	<target name="branch" depends="pull" if="dir.exists">
		<echo>${project.dir} exists</echo>
		<git command="checkout" dir="${project.dir}">
			<args>
				<arg value="-f" />
				<arg value="${branch}" />
			</args>
		</git>
	</target>

	<target name="init" depends="branch">

		<mkdir dir="${project.build}" />
		<mkdir dir="${project.log}" />

		<copy todir="${project.build}">
			<fileset dir="${project.dir}/WebRoot" includes="**/*" />
		</copy>

		<copy todir="${project.build}/WEB-INF/classes">
			<fileset dir="${project.src}">
				<include name="**/*.xml" />
				<include name="**/*.properties" />
			</fileset>
		</copy>

	</target>
	<target name="compile" depends="init">
		<javac srcdir="${project.src}" destdir="${project.build}/WEB-INF/classes">
			<classpath refid="classpath" />
		</javac>
	</target>

	<target name="config" depends="compile">
		<copy todir="${project.build}" overwrite="true">
			<fileset dir="${project.config}" includes="**/*" />
		</copy>
	</target>

	<target name="deploy" depends="config">
		<tstamp>
			<format property="timepoint" pattern="yyyy-MM-dd.HH:mm:ss" locale="cn,CN" />
		</tstamp>
		<rsync option="-auzv" src="${project.build}/" dest="${remote}:${destination}">
			<args>
				<arg value="--exclude=.git" />
				<arg value="--exclude=.svn" />
				<arg value="--exclude=.gitignore" />
				<arg value="--backup" />
				<arg value="--backup-dir=~/${backup.dir}/${timepoint}" />
				<arg value="--log-file=log/${ant.project.name}.${timepoint}.log" />
			</args>
		</rsync>
	</target>

	<target name="pkg" depends="compile">
		<jar jarfile="${pkg}" basedir="${project.build}" />
	</target>

	<target name="backup" depends="">
		<tstamp>
			<format property="TIMEPOINT" pattern="yyyy-MM-dd.HH:mm:ss" locale="cn,CN" />
		</tstamp>
		<echo>the backup directory is ${TIMEPOINT}.</echo>
		<mkdir dir="${backup.dir}/${TIMEPOINT}" />
		<rsync option="-auzv" src="${remote}:${destination}" dest="${backup.dir}/${TIMEPOINT}">
		</rsync>
	</target>

	<target name="receive" depends="">
		<echo>the receive directory is ${receive.timepoint}.</echo>
		<rsync option="-auzv" src="${backup.dir}/${receive.timepoint}" dest="${remote}:${destination}" />
	</target>

	<target name="fetch">
		<ant target="pull" />
		<ant target="branch" />
	</target>

	<target name="stop" depends="">
		<!-- ssh host="${remote}" command="/srv/apache-tomcat/bin/catalina.sh stop -force" keyfile="~/.ssh/id_rsa" / -->
		<ssh host="${remote}" command="/srv/apache-tomcat/bin/shutdown.sh" />
		<ant target="status" />
	</target>
	<target name="start" depends="">
		<ssh host="${remote}" command="/srv/apache-tomcat/bin/startup.sh" keyfile="~/.ssh/id_rsa" />
		<ant target="status" />
	</target>
	<target name="status" depends="">
		<ssh host="${remote}" command="ps ax | grep tomcat | grep -v grep" />
	</target>
	<target name="kill" depends="">
		<ssh host="${remote}" command="pkill -9 -f tomcat" />
		<ant target="status" />
	</target>
	<target name="run" depends="">
		<java classname="test.ant.HelloWorld" classpath="${hello}" />
	</target>
	<target name="clean">
		<delete dir="${project.build}" />
		<delete file="${hello}" />
	</target>
</project>

修改下面几处定义

<property name="repository" value="版本库地址" />
<property name="branch" value="部署分支" />
<property name="remote" value="远程服务器" />
<property name="destination" value="远程目录" />		

开始部署代码

ant backup
ant stop
ant deploy
ant start

5. 延伸阅读

如果你想学习制作部署工具,还可以看看笔者早期的作品https://github.com/oscm/deployment这个工具使用Bash开发,写这个工具仅仅半天时间,后面小改过几次,这个工具伴随笔者很多年。

第一个版本因为很多缺陷存在,笔者使用Python重新开发 https://github.com/oscm/devops 这个工具更适合PHP项目部署

时间: 2024-11-01 13:02:14

Apache Ant 实现自动化部署的相关文章

手动利用Apache Ant构建部署自己的Java项目

虽然Eclipse从3.0开始已经继承了Ant插件,大家的项目可以自动构建 部署,此篇文章看也没多大用处,但是手动去自己使用以下 Ant来构建自己的Java项目也是一件有意义的事情,虽然现在已经没用人用Javac Java命令行的方式 来搞程序.... Ant是Apache基金项目下的一个工具,在Apache官方给出的解释 是      一个帮助我们构建软件的 Java库和命令行工具 . Apache Ant is a Java library and command-line tool tha

浅析Ant脚本在部署过程中实现系统参数的自动发现

引言 Apache Ant 被广泛使用在 Java 开发的自动化编译.打包与部署过程中.在使用 Ant 进行软件包的部署时 ,经常需要输入一些系统环境参数,例如主机名称.IP 地址,一些服务的配置文件路径以及一些系统服务的端口等等.这 些系统参数的值通常是因所在的环境而异的,因此在不同的环境上使用 Ant 脚本进行部署,也需要手动的输入这些参数值 .一般的 Ant 部署脚本都会把需要使用者输入的参数放置到配置 property 文件里面,这样每次用户修改这些配置文件之 后再运行 Ant 脚本就可

Apache Ant 1.8.2 Released发布

Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发.由http://www.aliyun.com/zixun/aggregation/14417.html">Apache软件基金会所提供. 用户群:大多数的Java设计都被用于管理大量信息流,例如纽约州就使用Apache Ant去管理美国最大的青年计划,每天可以8206.html">实时更新超过25万学生的记录. Apache Ant is a Java

【Apache Ant】ANT解析以及ANT在myEclipse中的使用

转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自[大学之旅_谙忆的博客] 维基百科上对Ant的介绍: Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发. 由Apache软件基金会所提供.默认情况下,它的buildfile(XML文件)名为build.xml.每一个buildfile含有一个<project>和至少一个预设的<target>,这些targets包含许多ta

Linux下的Jenkins+Tomcat+Maven+Gitlab+Shell环境的搭建使用(jenkins自动化部署)

jenkins自动化部署   目标:jenkins上点构建(也可以自动检查代码变化自动构建)>>>项目部署完成.   一.安装jenkins 1.下载jenkins       这里我选择的是war包安装jenkins,简单不伤脑,别的博客写的jenkins版本都很旧,没用最新的,写个比较新的配置2.20版. 官网:https://jenkins.io/index.html WAR包下载地址:http://mirrors.tuna.tsinghua.edu.cn/jenkins/war/

如何实现云应用程序安全策略自动化部署

安全性是采用云技术所必需的一个要素,缺乏安全性通常会阻碍云技术的采用.然而,随着安全策略和合规复杂性.IT 复杂性和 IT 敏捷性的增加,将安全策略转化为安全实现的任务变得更加耗时.重复.昂贵且容易出错,并且很容易增加最终用户组织的安全工作量.自动化可帮助最终用户组织(和云提供商)减少该工作量,并提高策略实施准确度.本文将重点介绍一个特别有趣的.富有挑战且经常被遗忘的话题:应用程序层的安全策略自动化. 云应用程序安全性自动化 应用程序安全策略自动化主要是一个自动化流程,将人类可理解的安全需求(比

可与apache ant工具媲美的Apache Maven

17Tech 05月28日 消息: Apache Maven一个潜在的基于java的apache ant的构建工具的替代者.两者之间的比较: 第一:ant脚本是可以直接运行在maven中的.maven和ant最大的差别就是在于maven的编译以及所有的脚本都有一个基础,就是POM(project object model).这个模型定义了项目的方方面面,然后各式各样的脚本在这个模型上工作,而ant完全是自己定义,显然maven更胜一筹. 第二:Maven对所依赖的包有明确的定义,如使用那个包,版

构建iOS持续集成平台(三)CI服务器与自动化部署

CI服务器 写到这儿,对于iOS开发者来说,需要准备好: 一个比较容易获取的源代码仓库(包含源代码) 一套自动化构建脚本 一系列围绕构建的可执行测试 接下来就需要一个CI服务器来根据源代码的变更触发构建,监控测试结果.目前,业界比较流行的,支持iOS构建的CI服务器有Travis CI和Jenkins Travis CI Travis CI[20]是一个免费的云服务平台,主要功能就是为开源社区提供免费的CI服务,对于商业用户可以使用Travis Pro版本,其基本上支持所有目前主流的语言,Obj

简述WebSphere Commerce Search Web 服务器的自动化部署和配置

WebSphere Commerce Search Web 服务器自动化部署配置概述功能概述 在 Version 7 Feature Pack 5 之前,用户在启动 foundation 功能部件之后需要手动地执行一些配置步骤以完成对 WebSphere Commerce Search Web 服务器的部署和配置工作.以 IBM HTTP Server(IHS) Web 服务器为例,用户需要手动完成以下对 Search Web 服务器的部署配置工作:创建 Search Web 服务器的 http