CentOS 8 安装 Apache AntUnit 指南
在 CentOS 8 从零安装 Apache AntUnit 1.5.0:JDK 17 与 Ant 1.10.18 安装、sha512 校验、antlib 注册及 RPM 版 ant 排障实录、dnf 备选方案与最小测试验收,全程实测。
CentOS 8 安装 Apache AntUnit 指南
目标:在 CentOS 8 服务器上从零安装 Apache AntUnit 1.5.0(基于 Apache Ant 1.10.18 的单元测试 antlib),覆盖 JDK 安装、官方发行包下载校验、antlib 两种注册方式、RPM 版 ant 的 antlib 注册排障实录与最小测试验收,已在 CentOS 8.4.2105(OpenJDK 17.0.1、Ant 1.10.18)实测通过。
一、环境信息
本篇所有命令与回显均在以下环境中实测采集,复现时请保持相近版本:
- 操作系统:CentOS Linux 8.4.2105,x86_64
- JDK:OpenJDK 17.0.1(
java-17-openjdk-devel,AppStream 仓库) - 构建工具:Apache Ant 1.10.18(官方 dlcdn 发行包,2026-10 实测当前最新)
- 组件版本:Apache AntUnit 1.5.0(官方 dlcdn 发行包,2026-10 实测当前最新;jar 64749 字节)
- 安装目录:
/opt/apache-ant-1.10.18(Ant 主目录)、/opt/apache-ant-antunit-1.5.0(AntUnit 解压目录) - 实验目录:
/opt/lab(验收测试文件) - 执行用户:root
二、前置条件
AntUnit 不是独立进程,而是挂在 Ant 上的 antlib 任务库,安装链路为「JDK → Ant → AntUnit jar 注册」。CentOS 8 已于 2021 年底停止维护,官方源下线后需先确认源可用性。
2.1 确认系统版本与源状态
cat /etc/redhat-release
回显(实测):
CentOS Linux release 8.4.2105
dnf repolist
回显(实测节选):
repo id repo 名称
AppStream CentOS Linux 8 - AppStream
BaseOS CentOS Linux 8 - BaseOS
若你的机器源仍指向已下线的 mirror.centos.org,先整体切换到 vault 归档源再继续:
sed -i -e 's|mirror.centos.org|vault.centos.org|g' -e 's|^#baseurl=http://vault|baseurl=http://vault|g' /etc/yum.repos.d/CentOS-Linux-*.repo && dnf clean all && dnf repolist
回显(实测节选):
AppStream CentOS Linux 8 - AppStream
BaseOS CentOS Linux 8 - BaseOS
2.2 安装基础工具
dnf install -y wget curl
回显(实测节选):
Complete!
wget --version | head -1
回显(实测):
GNU Wget 1.19.5 built on linux-gnu.
2.3 安装 JDK 17
dnf install -y java-17-openjdk-devel
回显(实测节选):
Installed:
java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-devel-17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-headless-17.0.1.0.12-2.el8_5.x86_64
Complete!
java -version
回显(实测):
openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM (build 17.0.1+12-LTS, mixed mode, sharing)
确认 JDK 实际主目录(后面配 JAVA_HOME 要用):
readlink -f /usr/bin/java && ls -d /usr/lib/jvm/java-17-openjdk
回显(实测):
/usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64/bin/java
/usr/lib/jvm/java-17-openjdk
java -version 正常输出即 JDK 就绪;/usr/lib/jvm/java-17-openjdk 是固定不变的通用软链接,推荐作为 JAVA_HOME 值。
三、版本选型说明
先实测官方站点当前最新版本:
curl -s https://dlcdn.apache.org/ant/antlibs/antunit/binaries/ | grep -oE 'apache-ant-antunit-[0-9.]+-bin\.tar\.gz' | sort -uV | tail -3
回显(实测):
apache-ant-antunit-1.4-bin.tar.gz
apache-ant-antunit-1.4.1-bin.tar.gz
apache-ant-antunit-1.5.0-bin.tar.gz
curl -s https://dlcdn.apache.org/ant/binaries/ | grep -oE 'apache-ant-1\.10\.[0-9]+-bin\.tar\.gz' | sort -uV | tail -1
回显(实测):
apache-ant-1.10.18-bin.tar.gz
⚠️ 注意:AntUnit 的发行路径是
https://dlcdn.apache.org/ant/antlibs/antunit/binaries/(antlibs 子目录下),直接访问https://dlcdn.apache.org/ant/antunit/会得到 404 Not Found——这是实测踩过的第一个坑。
| 组件 | 实测最新版本 | 要求/兼容 | 获取渠道 | 说明 |
|---|---|---|---|---|
| Apache AntUnit | 1.5.0(2026-06 发布) | Ant 1.8.1+ 运行;classpath 嵌套特性需 Ant 1.10.13+ | dlcdn.apache.org/ant/antlibs/antunit/binaries/ | 本文采用,sha512 校验通过 |
| Apache AntUnit | 1.4.1 | Ant 1.8.1+ | archive.apache.org / Maven 中央仓库 | 存量工程常见;中央仓库最新为 1.4.1,1.5.0 仅发行官方包 |
| Apache Ant | 1.10.18 | Java 8+ | dlcdn.apache.org/ant/binaries/ | 本文采用,与 AntUnit 1.5.0 组合实测通过 |
| Apache Ant(AppStream) | 1.10.5-1.module_el8.0.0 | Java 8+ | CentOS 8 AppStream 模块 | 方案 B 使用,版本较旧 |
| JDK | OpenJDK 17.0.1 | Java 8+ | AppStream java-17-openjdk-devel | 运行 Ant 与 AntUnit 正常 |
关键差异与选型建议:生产测试基座选官方最新组合「Ant 1.10.18 + AntUnit 1.5.0」;AppStream 里的 ant 1.10.5 落后多年,仅适合临时验证。AntUnit 1.5.0 新增的 classpath/classpathrefid 属性要求 Ant 1.10.13 以上,方案 B(1.10.5)无法使用该特性。另外 RPM 版 ant 启动脚本对 antlib jar 的发现机制与官方发行版不同,是 CentOS 上最常见的坑,详见 8.2 节排障实录。
四、安装方案 A:官方 tar.gz 安装(推荐)
方案 A 从官方站点下载 Ant 与 AntUnit 发行包部署到 /opt,版本最新、路径可控。AntUnit 1.5.0 只有一个 jar(64749 字节),注册就是把 jar 放进 Ant 的 lib 目录。
4.1 下载 Ant 1.10.18 并校验 sha512
cd /opt && wget https://dlcdn.apache.org/ant/binaries/apache-ant-1.10.18-bin.tar.gz && wget https://dlcdn.apache.org/ant/binaries/apache-ant-1.10.18-bin.tar.gz.sha512
回显(实测节选):
apache-ant-1.10.18-bin.tar.gz 100%[===================>] 6.80M 11.8MB/s in 0.6s
apache-ant-1.10.18-bin.tar.gz.s 100%[===================>] 129 --.-KB/s in 0s
cd /opt && printf '%s %s\n' "$(cat apache-ant-1.10.18-bin.tar.gz.sha512)" apache-ant-1.10.18-bin.tar.gz | sha512sum -c -
回显(实测):
apache-ant-1.10.18-bin.tar.gz: OK
校验输出 OK 说明下载完整(官方 sha512 值为 c510d744876d8da48dabc9495b023b6ec5284a0f18b40ee50d98ce099e791ca5c73e3cd4c80d3c90d3efc03f9620be43aad0a373ed47198284f7e3373e0db2c3,包大小 7133405 字节)。
4.2 解压 Ant 并安装 AntUnit 1.5.0
cd /opt && tar xzf apache-ant-1.10.18-bin.tar.gz && ls -d /opt/apache-ant-1.10.18
回显(实测):
/opt/apache-ant-1.10.18
下载 AntUnit 发行包并校验解压:
cd /opt && wget https://dlcdn.apache.org/ant/antlibs/antunit/binaries/apache-ant-antunit-1.5.0-bin.tar.gz && wget https://dlcdn.apache.org/ant/antlibs/antunit/binaries/apache-ant-antunit-1.5.0-bin.tar.gz.sha512 && printf '%s %s\n' "$(cat apache-ant-antunit-1.5.0-bin.tar.gz.sha512)" apache-ant-antunit-1.5.0-bin.tar.gz | sha512sum -c - && tar xzf apache-ant-antunit-1.5.0-bin.tar.gz
回显(实测):
apache-ant-antunit-1.5.0-bin.tar.gz: OK
ls -l /opt/apache-ant-antunit-1.5.0/ | head -12
回显(实测):
total 356
-rw-r--r-- 1 root root 1306 Jun 18 2026 CONTRIBUTORS
-rw-r--r-- 1 root root 3577 Jun 18 2026 LICENSE
-rw-r--r-- 1 root root 166 Jun 18 2026 NOTICE
-rw-r--r-- 1 root root 2317 Jun 18 2026 README
-rw-r--r-- 1 root root 9255 Jun 18 2026 README.html
-rw-r--r-- 1 root root 5827 Jun 18 2026 WHATSNEW
-rw-r--r-- 1 root root 7379 Jun 18 2026 ant-antunit-1.5.0-cyclonedx.json
-rw-r--r-- 1 root root 6596 Jun 18 2026 ant-antunit-1.5.0-cyclonedx.xml
-rw-r--r-- 1 root root 64749 Jun 18 2026 ant-antunit-1.5.0.jar
-rw-r--r-- 1 root root 161 Jun 18 2026 ant-antunit-1.5.0.jar.sha512
AntUnit 发行包结构说明:核心只有一个 ant-antunit-1.5.0.jar(64749 字节,Java 8 字节码,无第三方依赖);docs/ 是 antunit 任务、断言任务与监听器的官方手册;etc/ 是配 junitreport 生成 HTML 报告的两个 XSL 样式表;javadoc/ 是 API 文档。
4.3 配置环境变量
CentOS 上需同时配置 JAVA_HOME 与 ANT_HOME(Ant 启动脚本找不到 java 命令时会直接报错退出):
printf 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk\nexport ANT_HOME=/opt/apache-ant-1.10.18\nexport PATH=$ANT_HOME/bin:$JAVA_HOME/bin:$PATH\n' > /etc/profile.d/ant.sh && source /etc/profile.d/ant.sh
回显(实测,无输出):
配置项说明:JAVA_HOME 指向 JDK 主目录,Ant 启动脚本用它定位 java 可执行文件;ANT_HOME 指向 Ant 主目录,脚本据此扫描 lib 目录;PATH 前置两者保证命令优先命中安装的版本。
验证:
echo $JAVA_HOME && echo $ANT_HOME && which ant java
回显(实测):
/usr/lib/jvm/java-17-openjdk
/opt/apache-ant-1.10.18
/opt/apache-ant-1.10.18/bin/ant
/usr/lib/jvm/java-17-openjdk/bin/java
4.4 注册 AntUnit antlib
Ant 官方发行版启动脚本会扫描 $ANT_HOME/lib/*.jar,把 AntUnit jar 拷进去即完成注册(命名空间 antlib:org.apache.ant.antunit 自动生效):
cp /opt/apache-ant-antunit-1.5.0/ant-antunit-1.5.0.jar /opt/apache-ant-1.10.18/lib/ && ls -l /opt/apache-ant-1.10.18/lib/ant-antunit-1.5.0.jar
回显(实测):
-rw-r--r-- 1 root root 64749 Oct 13 08:54 /opt/apache-ant-1.10.18/lib/ant-antunit-1.5.0.jar
4.5 验证安装
ant -version
回显(实测):
Apache Ant(TM) version 1.10.18 compiled on September 3 2026
ant -diagnostics | grep ant-antunit
回显(实测):
ant-antunit-1.5.0.jar (64749 bytes)
ant -version 输出 1.10.18 且诊断列表出现 ant-antunit-1.5.0.jar,方案 A 安装完成。
五、安装方案 B:AppStream 仓库 dnf 安装(备选)
方案 B 用 dnf 装 AppStream 里的 ant(实测版本 1.10.5),一条命令完成,但版本落后且 RPM 版脚本的 antlib 注册方式特殊,本节同时给出实测排障结论。
5.1 安装 Ant
dnf list --showduplicates ant
回显(实测节选):
Available Packages
ant.noarch 1.10.5-1.module_el8.0.0+47+197dca37 AppStream
dnf install -y ant
回显(实测节选):
Installed:
ant-1.10.5-1.module_el8.0.0+47+197dca37.noarch
ant-lib-1.10.5-1.module_el8.0.0+47+197dca37.noarch
Complete!
/usr/bin/ant -version && rpm -q ant
回显(实测):
Apache Ant(TM) version 1.10.5 compiled on June 24 2019
ant-1.10.5-1.module_el8.0.0+47+197dca37.noarch
5.2 注册 AntUnit antlib(RPM 版特殊,须显式注册)
先按常规方式把 jar 拷入 RPM 布局的 lib 目录:
cp /opt/apache-ant-antunit-1.5.0/ant-antunit-1.5.0.jar /usr/share/ant/lib/ && ls /usr/share/ant/lib/
回显(实测):
ant-antunit-1.5.0.jar
ant-bootstrap.jar
ant-launcher.jar
ant.jar
其中 ant-bootstrap.jar、ant-launcher.jar、ant.jar 是指向 /usr/share/java/ 的符号链接。但此时直接运行含 <au:antunit> 的构建会失败(实测,这是 CentOS 8 RPM 版 ant 的真实行为):
BUILD FAILED
/opt/lab/build.xml:4: Problem: failed to create task or type antlib:org.apache.ant.antunit:antunit
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
No types or tasks have been defined in this namespace yet
This appears to be an antlib declaration.
Action: Check that the implementing library exists in one of:
-/usr/share/ant/lib
-/root/.ant/lib
-a directory added on the command line with the -lib argument
根因(实测定位):RPM 版 /usr/bin/ant 启动脚本用 build-classpath 构建类路径,实测只包含固定两个 jar:
/usr/bin/build-classpath ant ant-launcher
回显(实测):
/usr/share/java/ant.jar:/usr/share/java/ant-launcher.jar
脚本既不扫描 /usr/share/ant/lib/*.jar,也不扫描 /root/.ant/lib,实测 -lib 命令行参数同样无效;jar 拷入即生效只是官方 tar.gz 版与 Debian/Ubuntu 版脚本的行为。可行的注册方式有两种。
方式一:CLASSPATH 环境变量(脚本会将其并入启动类路径):
export CLASSPATH=/usr/share/ant/lib/ant-antunit-1.5.0.jar
回显(实测,无输出):
cd /opt/lab && /usr/bin/ant -f build.xml
回显(实测):
Buildfile: /opt/lab/build.xml
antunit:
[au:antunit] Build File: /opt/lab/math-test.xml
[au:antunit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.02 sec
[au:antunit] Target: test-version-equals took 0.013 sec
[au:antunit] Target: test-buildfile-exists took 0.002 sec
BUILD SUCCESSFUL
Total time: 0 seconds
方式二:构建文件内 taskdef 显式指定 jar 路径(不依赖环境变量,建议固化在构建文件里):
<project name="antunit-runner-cp" default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
<taskdef uri="antlib:org.apache.ant.antunit"
resource="org/apache/ant/antunit/antlib.xml"
classpath="/usr/share/ant/lib/ant-antunit-1.5.0.jar"/>
<target name="antunit">
<au:antunit>
<fileset dir="${basedir}" includes="math-test.xml"/>
<au:plainlistener/>
</au:antunit>
</target>
</project>
实测运行(/opt/lab/build-cp.xml):
cd /opt/lab && /usr/bin/ant -f build-cp.xml
回显(实测):
Buildfile: /opt/lab/build-cp.xml
antunit:
[au:antunit] Build File: /opt/lab-dnf/math-test.xml
[au:antunit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.017 sec
[au:antunit] Target: test-version-equals took 0.01 sec
[au:antunit] Target: test-buildfile-exists took 0.001 sec
BUILD SUCCESSFUL
Total time: 0 seconds
两种方式均可让 RPM 版 ant 加载 AntUnit antlib;taskdef 方式随构建文件走,换机器只要 jar 路径一致即可复用,推荐固化。
六、方案对比与选择建议
| 维度 | 方案 A:官方 tar.gz | 方案 B:AppStream dnf |
|---|---|---|
| Ant 版本 | 1.10.18(官方最新) | 1.10.5(模块仓库,2019 年构建) |
| AntUnit 版本 | 1.5.0 | 1.5.0(jar 手动注册) |
| antlib 注册 | jar 拷入 $ANT_HOME/lib 即生效 | 须 CLASSPATH 或 taskdef 显式注册 |
| 是否联网 | 需访问 dlcdn.apache.org | 需访问 CentOS vault 镜像 |
| AntUnit 1.5.0 classpath 特性 | 可用(Ant ≥ 1.10.13) | 不可用(1.10.5 过旧) |
| 适合场景 | 生产 CI/测试基座 | 临时验证、内网无外网渠道 |
选择建议:CentOS 8 上优先选方案 A——AppStream 的 ant 已落后七个年头且模块流不再更新;方案 B 唯一的优势是不依赖外网文件分发渠道,但注册方式更绕,反而容易踩坑。
七、安装验收:运行最小 AntUnit 测试
本节用「断言文件存在 + 断言属性相等」的最小测试套件验收安装。AntUnit 测试模型:测试 target 名以 test 开头,由 <au:antunit> 任务驱动,监听器汇总结果。
7.1 编写测试文件与运行器
cd /opt/lab && cat > math-test.xml << 'EOF'
<project name="math-test" xmlns:au="antlib:org.apache.ant.antunit">
<property name="app.version" value="1.5.0"/>
<target name="test-buildfile-exists">
<au:assertFileExists file="${ant.file}"/>
</target>
<target name="test-version-equals">
<au:assertEquals expected="1.5.0" actual="${app.version}" message="app.version should be 1.5.0"/>
</target>
</project>
EOF
回显(实测,无输出):
cd /opt/lab && cat > build.xml << 'EOF'
<project name="antunit-runner" default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
<target name="antunit">
<au:antunit>
<fileset dir="${basedir}" includes="math-test.xml"/>
<au:plainlistener/>
</au:antunit>
</target>
</project>
EOF
回显(实测,无输出):
配置说明:math-test.xml 里 test-buildfile-exists 用 assertFileExists 断言构建文件存在(内置属性 ant.file 即当前构建文件的绝对路径),test-version-equals 用 assertEquals 断言属性值;build.xml 是运行器,<fileset> 选中测试文件,<au:plainlistener> 汇总输出。两个文件都需声明 xmlns:au 命名空间。
7.2 运行验收
cd /opt/lab && ant -f build.xml
回显(实测):
Buildfile: /opt/lab/build.xml
antunit:
[au:antunit] Build File: /opt/lab/math-test.xml
[au:antunit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.016 sec
[au:antunit] Target: test-version-equals took 0.01 sec
[au:antunit] Target: test-buildfile-exists took 0.001 sec
BUILD SUCCESSFUL
Total time: 0 seconds
Tests run: 2, Failures: 0, Errors: 0 且 BUILD SUCCESSFUL,方案 A 环境验收通过;方案 B 环境用 5.2 节两种注册方式之一后同样实测通过(见 5.2 回显)。
八、常见问题(FAQ)
8.1 ant 报 “We cannot run Java”
现象(实测):
We cannot run Java, please ensure you have Java installed.
We have tried to execute java but failed.
If you have installed Java in a unusual place you can set JAVA_HOME
to the directory containing the Java installation.
原因:RHEL 系 JDK 默认不把 JAVA_HOME 写入全局环境,Ant 启动脚本找不到 java。解决:把 JDK 通用软链接写入 profile:
printf 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk\n' > /etc/profile.d/java.sh && source /etc/profile.d/java.sh
回显(实测,无输出):
8.2 RPM 版 ant 加载 antlib 报 “Could not load definitions from resource org/apache/ant/antunit/antlib.xml. It could not be found.”
现象:jar 已在 /usr/share/ant/lib(报错信息也提示该目录),-lib 参数也试过,仍然报错。
定位过程(实测):bash -x /usr/bin/ant -version 跟踪发现脚本实际执行的类路径仅 LOCALCLASSPATH=/usr/share/java/ant.jar:/usr/share/java/ant-launcher.jar——RPM/jpackage 版脚本用 build-classpath ant ant-launcher 拼固定清单,不扫描 $ANT_HOME/lib,/root/.ant/lib 与 -lib 参数实测均无效。逐项验证结论:
| 注册方式 | 实测结果 |
|---|---|
jar 拷入 /usr/share/ant/lib | 失败(脚本不扫描该目录) |
-lib <jar> 命令行参数 | 失败 |
jar 放 /root/.ant/lib | 失败 |
export CLASSPATH=<jar> | 成功(脚本把 $CLASSPATH 并入启动类路径) |
taskdef + classpath 指向 jar | 成功(不依赖启动脚本,推荐固化) |
解决方案见 5.2 节两种方式(CLASSPATH 环境变量或构建文件内 taskdef 显式注册)。对照说明:官方 tar.gz 版与 Debian/Ubuntu 版 ant 启动脚本会扫描 lib 目录与用户 lib 目录,拷入即生效;RPM 版差异源自脚本对类路径的构建方式。
8.3 访问 dlcdn.apache.org/ant/antunit/ 返回 404
AntUnit 属于 Ant 的 antlib(附属库)系列,发行目录是 ant/antlibs/antunit/。正确的 binaries URL:
https://dlcdn.apache.org/ant/antlibs/antunit/binaries/apache-ant-antunit-1.5.0-bin.tar.gz
8.4 想让测试失败后构建继续执行报告与清理
给 <au:antunit> 加 failOnError="false" 与 errorProperty:
<au:antunit failOnError="false" errorProperty="tests-failed">
<fileset dir="${basedir}" includes="math-test.xml"/>
<au:plainlistener/>
</au:antunit>
<fail if="tests-failed">At least one test has failed</fail>
failOnError 默认 true;设为 false 后失败结果落到 errorProperty 指定属性,构建不中断,最后用 <fail if="..."> 自行判定(该用法在 Ant 1.10.18 + AntUnit 1.5.0 实测有效)。
九、卸载与清理
方案 A 的卸载:
rm -rf /opt/apache-ant-1.10.18 /opt/apache-ant-antunit-1.5.0
rm -f /opt/apache-ant-1.10.18-bin.tar.gz* /opt/apache-ant-antunit-1.5.0-bin.tar.gz*
rm -f /etc/profile.d/ant.sh
回显(实测,无输出):
方案 B 的卸载:
dnf remove -y ant && rm -f /usr/share/ant/lib/ant-antunit-1.5.0.jar
回显(实测节选):
Removed:
ant-1.10.5-1.module_el8.0.0+47+197dca37.noarch
Complete!
验证清理干净:
which ant; echo "exit=$?"
回显(实测):
exit=1
which ant 无输出且退出码 1,卸载完成。
十、参考链接
- Apache AntUnit 官方主页:https://ant.apache.org/antlibs/antunit/
- AntUnit 官方手册(antunit 任务):https://ant.apache.org/antlibs/antunit/antunit.html
- 官方发行包(当前版本):https://dlcdn.apache.org/ant/antlibs/antunit/binaries/
- 历史版本归档:https://archive.apache.org/dist/ant/antlibs/antunit/binaries/
- Apache Ant 官方手册:https://ant.apache.org/manual/
- Maven 中央仓库坐标:https://repo1.maven.org/maven2/org/apache/ant/ant-antunit/