Brian Venn
软件工程师,IBM
2004 年 5 月 这里提供了一种使用 Apache ANT 的新实现来自动化 DB2 UDB 安装过程的极佳方式。
为何用 ANT?
从 Apache Foundation 的 Jakarta 项目开始,ANT 就已经成为了构建 Java 项目的行业标准。它调用基于 XML 的配置文件,而各种脚本任务就是在这些文件中执行的。当 ANT 的主要角色是作为构建管理工具,用以创建自动化构建时,它还具有完成更多工作的能力。如果您不具备 ANT 的知识,我建议在开始之前访问 Apache 的 ANT 站点,或者试一试 Matt Chapmans 的 ANT 教程。如果您熟悉 DB2 的自动安装过程,这也是有帮助的。
在 IBM Hursley Park 的 IVT 团队这里,我们已经基于 ANT 开发了一种完全端到端的测试自动化框架。它可以在 IBM 的 Websphere Application Server 上下载、解压、安装、配置、部署和运行测试案例(testcase)场景。但是,我们的自动化过程中存在一个缺陷。如果需要一个本地 DB2 数据库,那么在可以启动剩余的自动化框架之前必须手工安装它。基于我们现有的 ANT 技能,我查看了扩展该过程以便包括 DB2 的自动安装和配置以及所需 fixpack 的可能性。
前面的任务
从高层考察问题
- 需要跨越安装机器复制 DB2 的安装程序和所需的 fixpack。
- 为了节省空间和网络通信负载,需要压缩安装映像文件,然后在到达时进行解压。
- 需要通过自动安装过程来安装 DB2,这将需要响应文件。
在编写 ANT 脚本时,一个好方法就是具有一组任务(或是被调用的目标),每个都执行它们自己的功能,类似于一个 Class。因此,我们需要编写一组目标,而每个都将执行我们要求的任务。
获取映像
第一个问题就是在机器上获取 DB2 安装映像。我们的团队使用不同 fixpack 级别的 DB2 V8。DB2 基本安装程序和不同的 fixpack 都被放置在共享机器上的一个目录结构中。我们称该机器为 myserver.hursley.ibm.com。为了节省共享驱动器上的空间,要提前压缩这些图像。最后,文件夹结构将如下所示:
- DB2 基本安装映像位于 DB2/DB2Base/db2Base.zip
- DB2 Fixpack 1 位于 DB2/Fixpack1/fixpack1.zip
- DB2 Fixpack 2 位于 DB2/Fixpack2/fixpack2.zip
- DB2 Fixpack 3 位于 DB2/Fixpack3/fixpack3.zip
- DB2 Fixpack 4 位于 DB2/Fixpack4/fixpack4.zip
现在,就可以获得 DB2 安装映像了,下一步就是在机器上获取安装程序。在 ANT 中,可通过 <ftp> 或 <copy> 任务这 2 种方式从 A 到 B 获取文件。
FTP
ANT 可以实现简单的 FTP 客户机。关于该过程的进一步细节,请查阅 Apache ANT 站点。清单 1 展示了如何使用 <ftp> 任务。
清单 1. 通过 FTP 任务获取安装程序
<target name="getDB2InstallviaFTP">
<ftp server="myserver.ibm.uk.com"
userid="me"
password="password"
action="get"
remotedir="DB2/DB2V8Base">
<fileset dir="c:/DB2Install/DB2Base">
<include name="db2V8Base.zip" />
</fileset>
</ftp>
</target>
|
详细考察参数。
server - 要连接的 FTP 服务器的完全限定名。
userid 和 password - 自我说明!
action - 这里有 2 个可能值, get 和 put 。我们使用的是 get。
remotedir - 我们获取文件的文件夹。
fileset dir - 我们将要放置复制文件的目的文件夹。
include name - 我们所获取的文件的名称。
复制
另一种方法就是 <copy> 任务。清单 2 展示了如果将驱动器 X:/ 映射到 DB2 安装映像所在的 myserver上的驱动器,将如何使用 copy 任务。
清单 2. 通过 copy 任务获取安装映像
<target name="getDB2BaseInstallviaCopy">
<copy todir="c:/DB2Install/DB2Base">
<fileset dir="X:/DB2/DB2V8Base"/>
</copy>
<target>
|
将由您来决定实现哪种方法。对于本例,假定我们要使用更简单的 <copy> 方法。下一步就是在机器上使用 <copy> 任务获取 fixpack 安装程序。清单 3 展示了将如何实现。
清单 3. 获取 fixpack
<target name="getDB2Fixpack2viaCopy">
<copy todir="c:/DB2Install/DB2Fixpack2">
<fileset dir="X:/DB2/Fixpack2"/>
</copy>
<target>
|
现在,我们有了 2 个单独的 ANT 目标,一个是获取基本的安装,一个是获取 fixpack。我们可以通过使用 <antcall> 任务将其合并成单个目标, <antcall> 任务可以调用任何其他的 ANT 目标。清单 4 展示了将如何完成。
清单 4. 使用 antcall 任务
<target name="getDB2BaseAndFixpack2">
<antcall target="getDB2BaseInstallviaCopy">
<antcall target="getDB2Fixpack2viaCopy">
<target>
|
如果现在运行 getDB2BaseAndFixpack2 目标,我们就会得到压缩的(zipped)基本 DB2 和 Fixpack 2,分别位于 c:/DB2Install/DB2Base/dbBase.zip 和 c:/DB2Install/DB2Fixpack2/fixpack2.zip 。下一步就是解压为安装而准备的图像。在 ANT 中解压极其简单,因为它带有 <unzip> 任务。为了使用它,只需源 zip 文件和解压的目的文件夹。清单 5 展示了这样的一个示例。
清单 5. 使用 unzip 任务
<target name="unzipDB2Base">
<unzip src="c:/DB2Install/DB2Base/dbBase.zip" dest="c:/DB2Install/DB2Base/unzipped"/>
</target>
<target name="unzipFixpack2">
<unzip src="c:/DB2Install/DB2Fixpack2/fixpack2.zip" dest="c:/DB2Install/DB2Fixpack2/unzipped"/>
</target>
<target name="unzipDB2InstallationImages">
<antcall target="unzipDB2Base">
<antcall target="unzipFixpack2">
</target>
|
清单 5 展示了 2 个单独的任务,用以执行基本 zip 和 fixpack zip 上的解压操作。其中还包括了一个额外的目标,用以将 2 个单独的任务合并成单个 ANT 目标。现在,我们已经下载并解压了安装程序,准备运行。
响应文件的生成
正如前面所提到的,我们需要实现一种完全自动的端到端的解决方案。因此,基本安装和 fixpack 的安装就必须是自动的。自动安装就是一种在其处理过程中无需人的交互式输入来执行安装的安装过程。自动安装需要使用响应文件。该响应文件包含一般由用户在安装时将输入的信息。关于自动安装的更多信息,请查询 DB2 文档 [[LINK]]。
您在此处可以使用两种方法。一种是为了运行已准备的响应文件,也许是在获取安装映像时以同样的方式从机器上复制的。另一种是为了在安装时生成响应文件。正如已介绍的复制方法,我们将动态地生成响应文件。清单 6 展示了一个示例。
清单 6. 生成响应文件
<target name="generateBaseResponseFile">
<echo file="c:/DB2Install/DB2Base/unzipped/PROD_ESE.rsp">
PROD=ENTERPRISE_SERVER_EDITION
LIC_AGREEMENT=ACCEPT
FILE=c:/Program Files/IBM/SQLLIB
INSTALL_TYPE=TYPICAL
LANG=EN
DAS_CONTACT_LIST=LOCAL
INSTANCE=DB2
DB2.NAME=DB2
DEFAULT_INSTANCE=DB2
DB2.NNAME=N00123D4
DB2.SVCENAME=db2c_DB2
DB2.DB2COMM=TCPIP, NETBIOS
DB2.ADAPTER_NUMBER=5
DB2.PORT_NUMBER=50000
DB2.FEDERATED=NO
DB2.AUTOSTART=YES
DB2.USERNAME=db2user
DB2.PASSWORD=passw0rd
</echo>
</target>
|
此处使用了 <echo> 任务。该任务通常用于在屏幕上显示输出,但是如果在参数中指定文件名,那么就会将文本写入那个文件中,而不是显示在屏幕上。
我们还需要一个响应文件,以用于 fixpack。清单 7 展示了为 fixpack 2 而生成的响应文件。
清单 7. 为 fixpack 安装生成响应文件
<target name="generateFixpack2ResponseFile">
<echo file="c:/DB2Install/DB2Fixpack2/unzipped/db2V8Fixpack2.rsp">
PROD = FIXPAK
REBOOT = NO
KILL_PROCESSES = YES
INSTALL_ONLY = YES
</echo>
<target>
|
让我们再次将这两个任务包装成单个 ANT 任务。
清单 8. 包装响应文件生成任务
<target name="generateResponseFiles">
<antcall target="generateBaseResponseFile">
<antcall target="generateFixpack2ResponseFile">
<target>
|
在运行目标 generateResponseFiles 时,它将生成响应文件 PROD_ESE.rsp 和 db2V8Fixpack2.rsp 。
运行安装
让我们来估计一下此时已经完成了哪些工作。到目前为止,我们已经有了 ANT 目标,它们可以复制 DB2 安装映像,对其进行解压,以及生成响应文件。现在,我们需要一个可以启动安装的目标。为了从 ANT 脚本启动一个外部程序,要使用 <exec> 任务。清单 9 展示了这是如何完成的。
清单 9. 启动 DB2 基本安装
<target name="startDB2BaseInstallation>
<exec dir="c:/DB2Install/DB2Base/unzipped" executable="setup" vmlauncher="false"
failonerror="true">
<arg line="/u c:/DB2Install/DB2Base/unzipped/PROD_ESE.rsp /L
c:/DB2Install/DB2Base/unzipped/db2v8Install.log"/>
</exec>
</target>
|
让我们更详细地看一看该任务中的参数,因为这里面有很多的细节问题。
dir="c:/DB2Install/DB2Base/unzipped" —— 这是我们将要启动的可执行程序的位置。
executable="setup" ——可执行程序本身的名称。
vmlauncher="false" ——这指示 ANT 是否尝试使用 JVM 的内置命令启动器。让其设置为 false,否则将会失败。
failonerror="true" ——告诉 ANT 如果碰到问题要立即停止。
现在看下一行。 <arg line="..."> 指定传递给要执行的程序的参数。为了让 DB2 安装程序(installer)能自动运行,需要响应文件的位置,另外,最佳实践是为它提供一个日志文件,以便可以诊断问题。
/u c:/DB2Install/DB2Base/unzipped/PROD_ESE.rsp ——指示这是一个自动安装,后面紧跟的是响应文件的位置。
/L c:/DB2Install/DB2Base/unzipped/db2v8Install.log ——指示要生成安装日志文件,后面紧跟的是要编写的日志文件的位置和名称。
最后一步就是安装 fixpack。因为这是一个新版的 Windows Installer,所以参数列表稍有不同。
清单 10. 启动 DB2 Fixpack 安装
<target name="startDB2FixpackInstallation>
<exec dir="${db2V8.tempDir}" executable="update" vmlauncher="false"
failonerror="true">
<arg line="-s -a -u c:/DB2Install/DB2Fixpack2/unzipped/db2V8Fixpack2.rsp -t
${db2V8.tempDir}\\fixpack2.trc -l ${db2V8.tempDir}\\fixpack2.log"/>
</exec>
</target>
|
进一步看看这些参数
-s -a -u c:/DB2Install/DB2Fixpack2/unzipped/db2V8Fixpack2.rsp —— 将其设置为自动安装,并且提供响应文件的位置。
-t ${db2V8.tempDir}\\fixpack2.trc —— 跟踪文件的位置。
-l ${db2V8.tempDir}\\fixpack2.log —— 日志文件的位置。
可以在本文结尾处的参考资料中找到 Windows installer 命令行参数的完全列表的链接。这里先不要过多地考虑它们。
最后,让我们将这两个任务包装成单个 ANT 任务。
清单 11. 合并两个安装任务
<target name="installDB2AndFixpack2">
<antcall target="startDB2BaseInstallation">
<antcall target="startDB2FixpackInstallation">
<target>
|
向下级联
现在,我们可以在 ANT 中一个接一个地运行这些任务了,它们每个都将执行自己的脚本任务。到目前为止,我们有:
getDB2BaseAndFixpack2 —— 获取 DB2 基本安装程序和 Fixpack 2 安装程序。
unzipDB2InstallationImages - 解压安装程序。
generateResponseFiles —— 生成响应文件。
installDB2AndFixpack2 —— 启动 DB2 基本安装,然后启动 Fixpack 安装。
因此,如果我们需要调用前面创建的任务 unzipDB2BaseAndFixpack2 ,就要输入下面的命令行。
ant unzipDB2InstallationImages
该命令行将执行我们为解压基本安装和 fixpack 安装而编制的脚本中的任务。但是这里存在一个问题,如果您未下载安装映像,就无法解压它们。同样,直到生成了响应文件,您才可以运行安装。我们的任务对于在它们自己可运行之前所运行的前一任务具有逻辑依赖性。
在 ANT 中,定义任务时,您还可以通过使用 <depends> 参数声明该任务的运行依赖于另一任务。例如。
<target name="unzipDB2InstallationImages" depends="getDB2BaseAndFixpack2">
|
因此,当我们调用任务 unzipDB2InstallationImages 时,它在运行本身之前将首先运行 getDB2BaseAndFixpack2 任务。因此,通过查看任务集中的逻辑依赖性,我们可以 得出:
<target name="getDB2BaseAndFixpack2">
<target name="unzipDB2InstallationImages" depends="getDB2BaseAndFixpack2">
<target name="generateResponseFiles" depends="unzipDB2InstallationImages">
<target name="installDB2AndFixpack2" depends="generateResponseFiles"">
现在,如果我们运行目标 installDB2AndFixpack2 ,该依赖性将向下级联,所以它将真正执行的第一个任务是 getDB2BaseAndFixpack2 任务。
最后修正
我们还可以再进行一些调整来改进和修改 ANT 脚本以满足您的需要。
属性文件
在我们的脚本示例中,您将注意到我们已经硬编码了许多参数,例如安装位置。如果需要更改安装路径,这将是很痛苦的,因为这意味着需要对脚本进行编辑。可能通过单独的属性文件在运行时传递这些参数。例如,如果创建了一个称作 installation.properties 的新文件,并与 ANT build.xml 脚本放置在同一文件夹中,在 ANT 脚本的开头放置:
<property file="installation.properties" />
现在,当运行该脚本时,它将加载该文件中所声明的任何变量。假设现在在该文件中,已经具有了下面一行
unzipDestination=c:/DB2Install/DB2Base/unzipped
然后,清单 5 中的代码将被重写为:
<unzip src="c:/DB2Install/DB2Base/dbBase.zip" dest="${unzipDestination}"/>
${parameterName} 给予了您无需修改脚本就可在脚本中更改参数的灵活性。
命令行参数
本文的第一部分可能使一些管理员感到担忧。在生成了响应文件的清单 6 中,将 DB2 用户名和口令硬编码为了脚本。这绝不是个好主意,因为任何人都可以找到您的脚本并进入您的数据库。更好的解决方案就是在运行时在命令行上传递用户名和口令,并且一旦使用了,就删除响应文件。
将命令行参数传递给 ANT 是通过在命令行上指定 -D<parameterName><parameterValue> 来完成的。例如:
ant installDB2AndFixpack2 -Ddb2UserName=db2use -Ddb2Password=passw0rd
脚本中这些参数的使用与在先前提到的属性文件中的是相同的。回顾一下清单 6,带有已公开口令的当前版本,利用下面两行读起来将更好一些:
DB2.USERNAME=${db2UserName}
DB2.PASSWORD=${db2Password}
在运行该脚本时,ANT 将用 db2use 替换 ${db2UserName} 以及用 passw0rd 替换 ${db2Password}。
一旦完成了自动安装,您就可以使用 <delete> 任务自动删除响应文件。清单 12 中展示了一个示例。
清单 12. 在 ANT 中删除
<delete>
<fileset dir="c:/DB2Install/DB2Base/unzipped" includes="PROD_ESE.rsp"/>
</delete>
|
您也可以在安装运行结束时使用删除任务来完成最后的工作,例如安装程序的删除等。
Condition 和 Unless
最后的一个考虑就是重复执行任务。假设您已经下载并解压了安装程序。就无需经历及时的下载和解压过程。这可以通过小心使用 <condition> 和 <unless> 任务来避免。
清单 13 展示了一个 condition 标签的示例。
清单 13. 使用 condition 任务
<target name="checkDB2BaseAlreadyDownloaded">
<condition property="isDB2BaseZipPresent">
<available file="c:/DB2Install/DB2Base/db2V8Base.zip" property="DB2BaseZipPresent"/>
</condition>
</target>
|
该任务查看文件 db2V8Base.zip 是否存在于 c:/DB2Install/DB2Base 中。回到清单 2,这是一个下载 db2Base.zip 文件的任务。
清单 14. 改进 getDB2BaseInstallviaCopy 任务
<target name="getDB2BaseInstallviaCopy" depends="checkDB2BaseAlreadyDownloaded" unless="DB2BaseZipPresent">
<copy todir="c:/DB2Install/DB2Base">
<fileset dir="X:/DB2/DB2V8Base"/>
</copy>
</target>
|
现在当该目标运行时,它首先将调用任务 checkDB2BaseAlreadyDownloaded 。如果该任务发现 DB2BaseZipPresent 属性被设置为 true,那么它将查看是否有文件 db2Base.zip。当它返回到 getDB2BaseInstallviaCopy 任务时,因为 DB2BaseZipPresent 为 true, <unless="..."> 防止运行该目标,因此需要第二次下载该文件。
进一步推进
在成功安装之后,还可以完成许多其他的任务。例如,如果用户还需要安装和配置数据库,您就可以使用 <exec> 任务来启动 DB2 命令窗口,这将可以运行一个准备好的 DDL 文件(或像前面的响应文件一样动态地创建它)。
在本文介绍 Windows 平台上 DB2 的安装时,ANT 的长处之一就是它是与平台无关的。在各种平台上安装 DB2 可以按照此处的相同过程并调整脚本来进行。还可以将此处的脚本扩展为安装其他产品,因为现今大多数产品都提供了自动安装,其过程与为 DB2 所描述的过程极其相似。
结束语
本文通过示例演示了如何使用 ANT 的各种任务来为 DB2 开发一个完全端到端的安装解决方案。 |