Apache Anakia 常用 CLI 命令与工具详解

Apache Anakia 常用 CLI 命令详解:ant 环境查询、构建执行与目标选择、输出日志控制、属性传递、诊断排障五大类逐一实测,含 -v/-e/-logfile/-D/-k 等参数差异回显与 unzip/jar 包检查工具。

Apache AnakiaAnakia2026/10/13

Apache Anakia 常用 CLI 命令与工具详解

目标:梳理 Apache Anakia 的全部命令行操作面——Anakia 本身没有独立可执行文件,它以 Ant task 形态随 Velocity 1.7 发行包分发,因此「Anakia 的命令行」即「Ant 的命令行」:环境查询、构建执行、目标选择、输出控制、属性传递、诊断排障五大类 ant 参数逐一实测,并覆盖 unzip/jar 等包检查工具,全部示例在 Ubuntu 22.04(OpenJDK 1.8.0_504、Ant 1.10.18、Velocity 1.7)实测通过。

一、环境信息

本篇所有命令与回显均在以下环境中实测采集:

  • 操作系统:Ubuntu 22.04.5 LTS,x86_64
  • JDK:OpenJDK 1.8.0_504(/usr/lib/jvm/java-8-openjdk-amd64)
  • 构建工具:Apache Ant 1.10.18(ANT_HOME=/opt/apache-ant-1.10.18,tar.gz 方案安装)
  • 组件版本:Apache Anakia(org.apache.velocity:velocity:1.7,jar 位于 /opt/anakia-lib/)
  • 演示工程:/opt/anakia-demo(结构见《Ubuntu 22.04 安装 Apache Anakia 指南》,src/xml/ 源 XML、styles/ 模板、build.xml 中 taskdef 注册 anakia)
  • 执行用户:root;演示账号 admin / q1w2e3r4(本篇为本地构建操作,如涉及远程登录使用该账号)

💡 技术拓展:/opt/apache-ant-1.10.18/bin/ant 是一个 shell 启动脚本(launcher),它拼装 classpath 后调用 org.apache.tools.ant.launcher.Launcher;Anakia 的全部命令行能力都来自这个 launcher 与 Ant 核心的参数解析,<anakia> task 自身不接收任何命令行参数——命令行能控制的是「构建怎么跑、日志怎么记、属性怎么传」。

二、前置条件

本篇示例可直接执行,前提:Ant 已安装且版本正确、演示工程可跑。核验命令与实测回显:

which ant && ant -version

回显(实测):

/opt/apache-ant-1.10.18/bin/ant
Apache Ant(TM) version 1.10.18 compiled on September 3 2026
cd /opt/anakia-demo && ant

回显(实测):

Buildfile: /opt/anakia-demo/build.xml

docs:
    [mkdir] Created dir: /opt/anakia-demo/docs
   [anakia] Transforming into: /opt/anakia-demo/docs
   [anakia] Input:  index.xml
   [anakia] Output: /opt/anakia-demo/docs/index.html
   [anakia] Input:  internal/secret.xml
   [anakia] Output: /opt/anakia-demo/docs/internal/secret.html
   [anakia] Input:  notes.xml
   [anakia] Output: /opt/anakia-demo/docs/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds

(首次在空产物目录运行,三个源文件全量转换。)环境安装过程见《Ubuntu 22.04 安装 Apache Anakia 指南》或《CentOS 8 安装 Apache Anakia 指南》。

三、命令速查表

ant 命令行总表(完整帮助见 ant -help,4.4 节附全文):

类别命令/参数作用实测小节
环境查询ant -version打印版本后退出4.1
环境查询ant --execdebug打印启动脚本生成的 exec 命令行4.3
环境查询ant -help打印全部参数说明后退出4.4
构建执行ant [target...]按默认目标(或指定目标序列)执行构建5.1
构建执行ant -p / -projecthelp打印工程目标清单与默认目标5.2
构建执行ant -f <file>使用指定构建文件5.3
构建执行ant -find <file>从当前目录向文件系统根搜索构建文件5.4
输出控制ant -eemacs 模式:日志去掉 [任务名] 前缀装饰6.1
输出控制ant -q安静模式:只输出构建结果与错误6.2
输出控制ant -S静默模式:除任务自身输出外什么也不打印6.3
输出控制ant -v冗长模式:解析过程、目标依赖序列全部可见6.4
输出控制ant -logfile <file>构建日志写入指定文件6.5
属性传递ant -D<属性>=<值>命令行定义属性,优先级高于构建文件7.1
属性传递ant -propertyfile <file>从属性文件批量加载属性7.2
属性传递ant -lib <path>向 launcher classpath 追加 jar/类目录7.3
依赖控制ant -k某目标失败后继续执行其余不依赖它的目标7.4
排障ant -diagnostics生成诊断报告(版本、属性、jar 清单)8.1
排障ant -debug调试级日志:类加载、属性求值全程可见8.2
包检查unzip -l <jar> / jar tf <jar>列出 jar 内条目(确认 Anakia 类存在)8.3

四、版本与环境查询命令

4.1 ant -version 与 which ant

ant -version

回显(实测):

Apache Ant(TM) version 1.10.18 compiled on September 3 2026

Ubuntu 上存在两套 Ant 时(apt 仓库的 /usr/bin/ant 1.10.12 与 tar.gz 的 /opt/apache-ant-1.10.18/bin/ant 1.10.18),务必用 which ant 确认当前 shell 生效的是哪一套:

which ant

回显(实测,登录 shell 中 PATH 前置 /opt/apache-ant-1.10.18/bin):

/opt/apache-ant-1.10.18/bin/ant

ant -version 打印后立即退出,不执行任何构建——适合写进 CI 脚本第一步做环境断言。

4.2 java -version

Anakia/Velocity 1.7 运行在 JVM 之上,JDK 版本决定 class 文件兼容性(velocity-1.7.jar 内 class 为 1.5 目标版本,1.8 与 17 均可运行):

java -version

回显(实测):

openjdk version "1.8.0_504"
OpenJDK Runtime Environment (build 1.8.0_504-8u504-ga-1ubuntu1~22.04.3-b01)
OpenJDK 64-Bit Server VM (build 25.504-b01, mixed mode)

4.3 ant --execdebug:查看启动命令行

--execdebug 属于启动脚本的 Script Options(注意是双横线),打印 launcher 最终 exec 的 JVM 命令行——排查 ANT_HOME、ANT_OPTS 是否生效最直接:

cd /opt/anakia-demo && ant --execdebug 2>&1 | head -2

回显(实测):

exec "$JAVACMD" -Xms256m -Xmx512m -Dfile.encoding=UTF-8 -classpath "$LOCALCLASSPATH" -Dant.home="$ANT_HOME" -Dant.library.dir="$ANT_LIB"  org.apache.tools.ant.launch.Launcher  -cp "$CLASSPATH"
Buildfile: /opt/anakia-demo/build.xml

第一行可见 -Xms256m -Xmx512m(来自环境变量 ANT_OPTS)与 -Dant.home 指向,说明 JVM 堆参数与 Ant 安装位置均按预期注入。

4.4 ant -help 全文

ant -help 输出全部运行参数,是本篇各节的权威索引。全文实测如下:

ant -help

回显(实测,全文):

/usr/bin/ant [script options] [options] [target [target2 [target3] ..]]
Script Options:
  --help, --h            print this message and ant help
  --noconfig             suppress sourcing of /etc/ant.conf,
                         $HOME/.ant/ant.conf, and $HOME/.antrc
                         configuration files
  --usejikes             enable use of jikes by default, unless
                         set explicitly in configuration files
  --execdebug            print ant exec line generated by this
                         launch script

ant [options] [target [target2 [target3] ...]]
Options:
  -help, -h              print this message and exit
  -projecthelp, -p       print project help information and exit
  -version               print the version information and exit
  -diagnostics           print information that might be helpful to
                         diagnose or report problems and exit
  -quiet, -q             be extra quiet
  -silent, -S            print nothing but task outputs and build failures
  -verbose, -v           be extra verbose
  -debug, -d             print debugging information
  -emacs, -e             produce logging information without adornments
  -lib <path>            specifies a path to search for jars and classes
  -logfile <file>        use given file for log
    -l     <file>                ''
  -logger <classname>    the class which is to perform logging
  -listener <classname>  add an instance of class as a project listener
  -noinput               do not allow interactive input
  -buildfile <file>      use given buildfile
    -file    <file>              ''
    -f       <file>              ''
  -D<property>=<value>   use value for given property
  -keep-going, -k        execute all targets that do not depend
                         on failed target(s)
  -propertyfile <name>   load all properties from file with -D
                         properties taking precedence
  -inputhandler <class>  the class which will handle input requests
  -find <file>           (s)earch for buildfile towards the root of
    -s  <file>           the filesystem and use it
  -nice  number          A niceness value for the main thread:
                         1 (lowest) to 10 (highest); 5 is the default
  -nouserlib             Run ant without using the jar files from
                         ${user.home}/.ant/lib
  -noclasspath           Run ant without using CLASSPATH
  -autoproxy             Java1.5+: use the OS proxy settings
  -main <class>          override Ant's normal entry point

注意输出分两段:上半段 Script Options 由启动脚本处理(-- 双横线),下半段 Options 才是 Ant JVM 进程解析的(- 单横线)。-logfile 与 -l、-buildfile 与 -f/-file、-find 与 -s 是长短写法等价。

五、构建执行与目标选择

5.1 ant:按默认目标构建

不带参数运行 ant 时,读取当前目录 build.xml,执行其 default 属性指定的目标(本工程为 docs):

cd /opt/anakia-demo && touch src/xml/notes.xml && ant

回显(实测,touch 更新时间戳后仅 notes.xml 需重转):

Buildfile: /opt/anakia-demo/build.xml

docs:
   [anakia] Transforming into: /opt/anakia-demo/docs
   [anakia] Input:  notes.xml
   [anakia] Output: /opt/anakia-demo/docs/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds

ant 也可直接带目标名:ant docs 与不带参数等价;多目标写法 ant clean docs 按顺序执行(clean 类目标见《快速入门与集成示例》第六章 rebuild 目标)。

5.2 ant -p / -projecthelp:打印目标清单

cd /opt/anakia-demo && ant -p

回显(实测):

Buildfile: /opt/anakia-demo/build.xml

Main targets:

 docs  Transform XML docs to HTML with Anakia
Default target: docs

-p 与 -projecthelp 完全等价(回显一致)。只列出带 description 属性的 target(Main targets)与 default 目标;不带 description 的 target 不显示——给每个 target 写 description 是让 -p 有用的前提。

5.3 ant -f:从任意目录指定构建文件

在工程目录之外执行构建时用 -f 传绝对路径,basedir 仍按构建文件所在目录解析:

cd /tmp && ant -f /opt/anakia-demo/build.xml

回显(实测,产物均为最新故全部跳过):

Buildfile: /opt/anakia-demo/build.xml

docs:
   [anakia] Transforming into: /opt/anakia-demo/docs

BUILD SUCCESSFUL
Total time: 0 seconds

注意第一行打印的是 -f 指向的构建文件路径,工作日志(Transforming into:)表明输出目录仍解析为工程内 docs。

5.4 ant -find:向上搜索构建文件

在工程子目录深处不想写 ../../.. 时,-find 从当前目录逐级向文件系统根搜索指定构建文件名,找到后切到该目录执行:

cd /opt/anakia-demo/src/xml && ant -find build.xml

回显(实测):

Searching for build.xml ...
Buildfile: /opt/anakia-demo/build.xml

docs:
   [anakia] Transforming into: /opt/anakia-demo/docs

BUILD SUCCESSFUL
Total time: 0 seconds

Searching for build.xml ... 是 -find 特有输出。风险:若上层目录存在同名旧构建文件会被误命中,CI 环境建议固定用 -f 绝对路径。

六、输出与日志控制

6.1 ant -e:emacs 模式(去前缀装饰)

默认日志带 [任务名] 前缀;-e 去掉全部装饰,输出为纯行——便于工具链做逐行 diff 或 grep:

cd /opt/anakia-demo && touch src/xml/notes.xml && ant -e

回显(实测):

Buildfile: /opt/anakia-demo/build.xml

docs:
Transforming into: /opt/anakia-demo/docs
Input:  notes.xml
Output: /opt/anakia-demo/docs/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds

与 5.1 节回显逐行对比:[anakia] 前缀消失,其余内容不变。

6.2 ant -q:安静模式

-q 抑制常规进度信息,只留构建结果与错误:

cd /opt/anakia-demo && ant -q

回显(实测,源未变化、增量跳过,因此连 Input/Output 行也没有):


BUILD SUCCESSFUL
Total time: 0 seconds

失败时错误信息仍会打印(-q 不是吞错),实测见 9.2 节。

6.3 ant -S:静默模式

-S(-silent)比 -q 更进一步:除任务自身输出和构建失败信息外什么都不打印,连 BUILD SUCCESSFUL 都不输出:

cd /opt/anakia-demo && ant -S

回显(实测,全文仅此一行):

Buildfile: /opt/anakia-demo/build.xml

脚本化场景可用 ant -S && echo OK 之类方式自补结果标记。三者 verbosity 排序:-S < -q < 默认 < -v < -debug。

6.4 ant -v:冗长模式

-v 打印构建文件解析、Java/OS 探测、目标依赖序列等过程信息,是定位「为什么我的 target 没被执行」的第一工具:

cd /opt/anakia-demo && touch src/xml/notes.xml && ant -v

回显(实测,全文):

Apache Ant(TM) version 1.10.18 compiled on September 3 2026
Trying the default build file: build.xml
Buildfile: /opt/anakia-demo/build.xml
Detected Java version: 1.8 in: /usr/lib/jvm/java-8-openjdk-amd64/jre
Detected OS: Linux
parsing buildfile /opt/anakia-demo/build.xml with URI = file:/opt/anakia-demo/build.xml
Project base dir set to: /opt/anakia-demo
parsing buildfile jar:file:/opt/apache-ant-1.10.18/lib/ant.jar!/org/apache/tools/ant/antlib.xml with URI = jar:file:/opt/apache-ant-1.10.18/lib/ant.jar!/org/apache/tools/ant/antlib.xml from a zip file
Build sequence for target(s) `docs' is [docs]
Complete build sequence is [docs, ]

docs:
    [mkdir] Skipping /opt/anakia-demo/docs because it already exists.
   [anakia] Transforming into: /opt/anakia-demo/docs
   [anakia] Input:  notes.xml
   [anakia] Output: /opt/anakia-demo/docs/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds

关键行解读:Build sequence for target(s) 'docs' is [docs] 给出依赖展开后的执行序列(多依赖工程排查 depends 写错就靠它);[mkdir] Skipping ... because it already exists. 说明目标目录已存在时 mkdir 任务直接跳过。

6.5 ant -logfile:日志落盘

-logfile(短写 -l)把构建日志写入文件;终端仍会显示 Buildfile: 头行(该行由 launcher 直接打印,不入日志文件):

cd /opt/anakia-demo && touch src/xml/notes.xml && ant -logfile build-cli.log && cat build-cli.log

回显(实测,终端一行 + 日志文件全文):

Buildfile: /opt/anakia-demo/build.xml

docs:
   [anakia] Transforming into: /opt/anakia-demo/docs
   [anakia] Input:  notes.xml
   [anakia] Output: /opt/anakia-demo/docs/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds

日志文件内容与默认控制台输出一致(含前缀)。CI 里推荐固定写法 ant -logfile build-$(date +%Y%m%d).log,把每次构建日志按日期归档($(date +%Y%m%d) 为 shell 命令替换,运行时展开为如 20261013 的日期串,非占位符)。

七、属性传递与依赖控制

7.1 ant -D:命令行覆盖属性

-D属性=值 在命令行定义属性,优先级高于构建文件中 <property> 的同名定义。演示工程 build.xml 用 ${docs.dest} 作输出目录,命令行直接改道:

cd /opt/anakia-demo && rm -rf /tmp/docs-cli && ant -Ddocs.dest=/tmp/docs-cli && ls /tmp/docs-cli

回显(实测,注意 Transforming into: 已变为 /tmp/docs-cli):

Buildfile: /opt/anakia-demo/build.xml

docs:
    [mkdir] Created dir: /tmp/docs-cli
   [anakia] Transforming into: /tmp/docs-cli
   [anakia] Input:  index.xml
   [anakia] Output: /tmp/docs-cli/index.html
   [anakia] Input:  internal/secret.xml
   [anakia] Output: /tmp/docs-cli/internal/secret.html
   [anakia] Input:  notes.xml
   [anakia] Output: /tmp/docs-cli/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds
index.html
internal
notes.html

产物写入命令行指定目录且子目录结构完整(internal/ 一并生成)。同一机制可用于临时换 docs.src 指向另一套源目录做试转换,不必改构建文件。

7.2 ant -propertyfile:批量加载属性

属性较多时写成文件,配合 -propertyfile 一次载入;-D 仍然优先(帮助文本原文:-D properties taking precedence):

cd /opt/anakia-demo && rm -rf /tmp/docs-from-propfile && printf "docs.dest=/tmp/docs-from-propfile\n" > cli.properties && ant -propertyfile cli.properties && ls /tmp/docs-from-propfile && rm cli.properties

回显(实测):

Buildfile: /opt/anakia-demo/build.xml

docs:
    [mkdir] Created dir: /tmp/docs-from-propfile
   [anakia] Transforming into: /tmp/docs-from-propfile
   [anakia] Input:  index.xml
   [anakia] Output: /tmp/docs-from-propfile/index.html
   [anakia] Input:  internal/secret.xml
   [anakia] Output: /tmp/docs-from-propfile/internal/secret.html
   [anakia] Input:  notes.xml
   [anakia] Output: /tmp/docs-from-propfile/notes.html

BUILD SUCCESSFUL
Total time: 0 seconds
index.html
internal
notes.html

属性文件格式为标准 key=value 每行一对(printf 里的 \n 是换行转义)。环境差异(不同构建机的输出路径)用不同 propertyfile 承载,构建文件保持不动。

7.3 ant -lib:向 launcher classpath 追加路径

-lib <path> 把目录或 jar 追加到 Ant launcher 的 classpath(位于 ANT_HOME/lib 之后、用户 classpath 之前)。用 -diagnostics 报告中的 java.class.path 行验证生效:

mkdir -p /tmp/extra-lib && cd /opt/anakia-demo && ant -lib /tmp/extra-lib -diagnostics 2>&1 | grep "java.class.path" | head -c 220

回显(实测,截取前 220 字符):

java.class.path : /opt/apache-ant-1.10.18/lib/ant-launcher.jar:/tmp/extra-lib/:/opt/apache-ant-1.10.18/lib/ant-launcher.jar:/opt/apache-ant-1.10.18/lib/ant-commons-net.jar:/opt/apache-ant-1.10.18/lib/ant.jar:/opt/apache-

(关键证据:/tmp/extra-lib/ 紧跟在 ant-launcher.jar 之后出现,证明 -lib 注入成功。)对本工程而言 taskdef 内 <classpath> 已显式声明四个运行时 jar(见《配置参数详解》第七章),无需依赖 -lib;它在「临时试用某个新 jar、不想动构建文件」时最省事。

7.4 ant -k:失败后继续执行无关目标

默认情况下任一目标失败即终止整次构建;-k(keep-going)改为「继续执行所有不依赖失败目标的目标」。构造一个三目标演示工程(upload 必然失败,report 与 upload 无依赖):

mkdir -p /tmp/kdemo && cat > /tmp/kdemo/build.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project name="kdemo" default="all" basedir=".">
  <target name="transform" description="Transform docs"/>
  <target name="upload" description="Upload docs">
    <fail message="upload server unreachable"/>
  </target>
  <target name="report" description="Build report"/>
  <target name="all" depends="transform,upload,report"/>
</project>
EOF
cd /tmp/kdemo && ant -k

回显(实测):

Buildfile: /tmp/kdemo/build.xml

transform:

upload:
Target 'upload' failed with message 'upload server unreachable'.

report:
Cannot execute 'all' - 'upload' failed or was not executed.

BUILD FAILED
/tmp/kdemo/build.xml:5: upload server unreachable

Total time: 0 seconds

解读:upload 失败后 report 仍被执行(其输出点出现);all 因依赖链包含失败目标被跳过并打印 Cannot execute 'all';最终 BUILD FAILED 且退出码为 1——CI 可以放心用退出码判断整体成败。不带 -k 时 report 完全不会执行(对照回显见 9.2 节)。该参数适合「转换、打包、发布多个无依赖站点目录」的批量构建,一个目录出错不阻塞其余目录产出。

八、排障命令与 jar 检查工具

8.1 ant -diagnostics:诊断报告

cd /opt/anakia-demo && ant -diagnostics 2>&1 | head -25

回显(实测,报告共 171 行,此处截取前 25 行):

------- Ant diagnostics report -------
Apache Ant(TM) version 1.10.18 compiled on September 3 2026

-------------------------------------------
 Implementation Version
-------------------------------------------
core tasks     : 1.10.18 in file:/opt/apache-ant-1.10.18/lib/ant.jar

-------------------------------------------
 ANT PROPERTIES
-------------------------------------------
ant.version: Apache Ant(TM) version 1.10.18 compiled on September 3 2026
ant.java.version: 1.8
Is this the Apache Harmony VM? no
Is this the Kaffe VM? no
Is this gij/gcj? no
ant.core.lib: /opt/apache-ant-1.10.18/lib/ant.jar
ant.home: /opt/apache-ant-1.10.18

-------------------------------------------
 ANT_HOME/lib jar listing
-------------------------------------------
ant.home: /opt/apache-ant-1.10.18
ant-launcher.jar (18717 bytes)
ant-commons-net.jar (90668 bytes)

报告后续段落依次为:ANT_HOME/lib jar listing(lib 目录 jar 清单与字节数)、TASKS DEFINED、ant Homes、HOME/.ant/lib jar listing、USER CLASSPATH、系统属性全表、Temp dir 与 Locale。报障时把整份报告(重定向到文件)附给对方即可覆盖 90% 的环境问题。

8.2 ant -debug:调试级日志

-debug(短写 -d)在 -v 之上再开类加载与属性求值细节(实测全量约 701 行)。Anakia 相关最有价值的是 taskdef classpath 的类加载证据:

cd /opt/anakia-demo && ant -debug 2>&1 | grep -E "jdom|velocity.exception" | head -6

回显(实测):

Finding class org.jdom.JDOMException
Loaded from /opt/anakia-lib/jdom-1.1.3.jar org/jdom/JDOMException.class
Class org.jdom.JDOMException loaded from ant loader (parentFirst)
Finding class org.apache.velocity.exception.ResourceNotFoundException
Loaded from /opt/anakia-lib/velocity-1.7.jar org/apache/velocity/exception/ResourceNotFoundException.class
Finding class org.apache.velocity.exception.VelocityException

Loaded from <jar路径> 逐行标明每个类实际来自哪个 jar——NoClassDefFoundError、ClassNotFoundException 类问题(如《配置参数详解》FAQ Q4 的 werken-xpath 依赖链)用这一招可以直接看到缺谁、从哪加载。

8.3 unzip -l 与 jar tf:确认 Anakia 类在包内

Anakia task 类都在 velocity-1.7.jar 的 org/apache/velocity/anakia/ 包下。两种等价列法:

unzip -l /opt/anakia-lib/velocity-1.7.jar | grep anakia

回显(实测):

Archive:  /opt/anakia-lib/velocity-1.7.jar
        0  2010-11-19 12:15   org/apache/velocity/anakia/
     2642  2010-11-19 12:15   org/apache/velocity/anakia/AnakiaElement.class
     1271  2010-11-19 12:15   org/apache/velocity/anakia/AnakiaJDOMFactory.class
     2163  2010-11-19 12:15   org/apache/velocity/anakia/AnakiaTask$Context.class
    10254  2010-11-19 12:15   org/apache/velocity/anakia/AnakiaTask.class
     1267  2010-11-19 12:15   org/apache/velocity/anakia/Escape.class
      219  2010-11-19 12:15   org/apache/velocity/anakia/NodeList$1.class
     1256  2010-11-19 12:15   org/apache/velocity/anakia/NodeList$AttributeXMLOutputter.class
     7651  2010-11-19 12:15   org/apache/velocity/anakia/NodeList.class
      958  2010-11-19 12:15   org/apache/velocity/anakia/OutputWrapper.class
     1240  2010-11-19 12:15   org/apache/velocity/anakia/TreeWalker.class
      963  2010-11-19 12:15   org/apache/velocity/anakia/XPathCache.class
     1309  2010-11-19 12:15   org/apache/velocity/anakia/XPathTool.class

JDK 自带的 jar tf 同效且可计数(AnakiaTask.class 与其内部类 AnakiaTask$Context.class 均在列):

jar tf /opt/anakia-lib/velocity-1.7.jar | grep -c anakia

回显(实测):

13

下载或自编译 velocity jar 后,先用这两条确认 AnakiaTask.class 存在,再跑构建——taskdef 报 Could not load definitions from resource ... 时第一步就是它。

8.4 javap:查看 AnakiaTask 类签名

需要确认某个属性 setter 是否存在(自定义二改版本、升级 jar 后接口变化)时,用 JDK 的 javap 反编译类签名。完整用法与十个 setter 的输出见《Apache Anakia 配置参数详解》第三章,此处给最小验证:

cd /tmp && rm -rf ancls && mkdir ancls && cd ancls && unzip -q -o /opt/anakia-lib/velocity-1.7.jar 'org/apache/velocity/anakia/AnakiaTask*.class' && javap -classpath . org.apache.velocity.anakia.AnakiaTask | head -5

回显(实测):

Compiled from "AnakiaTask.java"
public class org.apache.velocity.anakia.AnakiaTask extends org.apache.tools.ant.taskdefs.MatchingTask {
  org.jdom.input.SAXBuilder builder;
  java.io.File baseDir;
  public org.apache.velocity.anakia.AnakiaTask();

九、常见问题(FAQ)

Q1:在工程外目录直接跑 ant 报什么?

Buildfile: build.xml does not exist!
Build failed

(实测回显,退出码 1。)ant 默认只认当前目录 build.xml,不会自动向上搜索;要么 cd 到工程目录,要么 -f 指定路径,要么 -find 显式向上找。

Q2:-q / -S 模式下构建失败还能看到错误吗?

能。-q 下错误照常输出(实测):


BUILD FAILED
/tmp/kdemo/build.xml:5: upload server unreachable

Total time: 0 seconds

-S 同样打印任务输出与失败信息(帮助文本原文:print nothing but task outputs and build failures)。两个模式都不影响退出码,脚本按退出码判断即可。对照:不带 -k 时 7.4 节演示工程在 upload 失败后直接终止,report 不执行。

Q3:-D 覆盖了构建文件里的属性,反过来行吗?

反方向不行。命令行 -D 定义的属性优先级最高,构建文件里的 <property> 同名定义不生效(这是 Ant 的属性不可变规则:先定义者胜)。要让构建文件内部计算值优先,就不能用 -D 传同名属性——把「可覆盖项」只写在 -D/propertyfile,把「固定计算值」留给构建文件。

Q4:服务器上 apt 装过 Ant 又装了 tar.gz 版,构建时用的哪套?

取决于 PATH 顺序。Ubuntu 22.04 实测:登录 shell 中 which ant 返回 /opt/apache-ant-1.10.18/bin/ant(profile 中前置了 tar.gz 路径),非登录环境则解析到 /usr/bin/ant(apt 的 1.10.12)。两套版本共存时每次构建前用 which ant && ant -version 断言版本,或在 CI 脚本里显式写全路径 /opt/apache-ant-1.10.18/bin/ant。

Q5:Velocity 1.7 在新版 JDK 上跑 Anakia 会有兼容问题吗?

本系列两台环境分别实测通过:Ubuntu 22.04(OpenJDK 1.8.0_504)与 CentOS 8(OpenJDK 17.0.1 + Ant 1.10.18,ant -version 返回 Apache Ant(TM) version 1.10.18 compiled on September 3 2026)。velocity-1.7.jar 的字节码目标版本低,1.8 与 17 均可直接加载运行;注意 17 下若出现反射限制告警,加 ANT_OPTS="--add-opens=java.base/java.lang=ALL-UNNAMED" 放宽即可(本系列 CentOS 8 安装指南验收章节有对应实测)。

十、参考链接