Apache Tentacles 常用 CLI 命令与工具详解
逐一实测 Apache Tentacles 0.1 全部 CLI 用法(远程与本地 URI、输出目录、-Dfilter、-ea、退出码)与联动工具 Apache Rat 0.18 的核心命令,含 Rat --help 全量转录与异常行为实录。
Apache Tentacles 常用 CLI 命令与工具详解
目标:把 Apache Tentacles 0.1 的全部命令行用法(两个位置参数、一个系统属性、一个 JVM 开关、退出码语义)逐项实测成册,并完整转录联动工具 Apache Rat 0.18 的
--help输出、逐项实测其核心选项,作为发布合规审计流水线的命令速查手册。全部命令已在 Ubuntu 22.04.5 LTS + OpenJDK 17 环境实测通过。
一、环境信息
本文所有命令与回显均实测采集,演示统一在 /root 目录下进行:
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Java 运行时:OpenJDK 17.0.20.1(
openjdk-17-jre-headless) - 主工具:Apache Tentacles 0.1(
apache-tentacles-0.1-jar-with-dependencies.jar) - 联动工具:Apache Rat 0.18(
apache-rat-0.18.jar) - 安装目录:
/root/tentacles(两个 jar 所在),演示输出目录:/root/tentacles-demo;官方站点 https://creadur.apache.org/tentacles/ 与 https://creadur.apache.org/rat/
二、工具概览
2.1 工具构成
发布合规审计流水线涉及两个同属 Apache Creadur 的单 jar 命令行工具,均无独立服务进程,按需以 java -jar 运行:
| 工具 | jar | 职责 | CLI 形态 |
|---|---|---|---|
| Apache Tentacles 0.1 | apache-tentacles-0.1-jar-with-dependencies.jar | 批量下载远程仓库发行件、递归解包、生成 LICENSE/NOTICE 汇总报告 | 无选项体系:2 个位置参数 + 1 个系统属性 + 1 个 JVM 开关 |
| Apache Rat 0.18 | apache-rat-0.18.jar | 对本地目录/归档逐文件识别许可证头,输出审计报告 | 传统选项体系:--help 可见 40 余个选项 |
2.2 命令语法总览
Tentacles 全部语法一式一条(每一项的实测见第四章):
| 语法要素 | 必填 | 作用 |
|---|---|---|
java -ea [-Dfilter=<正则>] -jar apache-tentacles-0.1-jar-with-dependencies.jar <URI> [输出目录名] | - | 完整调用形态 |
第 1 参数 URI(https://…、http://…、file:/…) | 是 | 远程仓库地址(递归爬取下载)或本地目录(复制取样) |
| 第 2 参数 输出目录名 | 否 | 输出根目录名;缺省取 URI 路径末段 |
-Dfilter=<正则> | 否(file: 模式实际必改) | 仅本地模式生效:按绝对路径正则全匹配筛选归档,默认 org/apache/openejb |
-ea | 否 | 启用 Java 断言,官方 README 要求携带;退出码恒为 0,成败看日志与产出 |
💡 技术拓展:
-ea是 JVM 的断言启用开关(enable assertions),与 Tentacles 的参数解析无关。带断言运行的程序在内部状态异常时抛AssertionError便于暴露问题;实测不带-ea时 Tentacles 主流程同样正常(见 4.6 节),官方要求携带属于运行约定而非硬性依赖。
三、前置条件
两件准备工作:JDK 就位、两个发行件就位。安装与校验的完整流程见《Apache Tentacles 在 Ubuntu 22.04 集成使用指南》第三章,此处仅验证就位状态。
apt-get install -y openjdk-17-jre-headless && java -version
实测输出(节选):
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
发行件就位状态(ls -la /root/tentacles/ 实测):apache-tentacles-0.1-jar-with-dependencies.jar(9715403 字节)与 apache-rat-0.18/(含 apache-rat-0.18.jar)均已就位,且 Tentacles jar 的 sha512 校验结果与官方 .sha512 文件一致(ae6e8d8d9e55517c0d2efc8bb5a63ad1514013d57f2d90552025321cfa246bc351b5a2a72a92882e4efca324f39391b01df2caa9aaf395f1c2099031c868d301)。
四、Apache Tentacles 0.1 命令详解
4.1 无参启动:唯一的帮助形态
Tentacles 没有 --help、--version 选项(0.1 CLI 未实现选项体系),漏传参数时输出的引导提示就是它的「帮助」:
cd /root/tentacles && java -ea -jar apache-tentacles-0.1-jar-with-dependencies.jar
实测输出:
0 [main] INFO org.apache.creadur.tentacles.Main - Launching Apache Tentacles ...
0 [main] ERROR org.apache.creadur.tentacles.Main - Error: Input parameter missing - you did not specify any component to run Apache Tentacles on.
0 [main] ERROR org.apache.creadur.tentacles.Main - Please launch Apache Tentacles with an URI to work on such as 'https://repository.apache.org/content/repositories/orgapachecreadur-1000/'.
要点:即便以 ERROR 提示退出,进程退出码仍为 0(4.8 节汇总)。提示中的示例 URI 指向一个 Apache staging 仓库地址。
4.2 第 1 参数:远程 HTTP 仓库 URI
核心用法。Tentacles 从给定 URL 开始递归爬取目录树,下载全部匹配 .*\.(jar|zip|war|ear|rar|tar.gz) 的文件,逐个递归解包并生成报告。以 Apache releases 仓库的 tentacles 目录为目标(5 个发行件,适合演练):
mkdir -p /root/tentacles-demo && cd /root/tentacles-demo && java -ea -jar /root/tentacles/apache-tentacles-0.1-jar-with-dependencies.jar https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/
实测输出(全程日志):
0 [main] INFO org.apache.creadur.tentacles.Main - Launching Apache Tentacles ...
36 [main] INFO org.apache.creadur.tentacles.Main - Remote repository: https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/
36 [main] INFO org.apache.creadur.tentacles.Main - Local root directory: tentacles
129 [main] INFO org.apache.creadur.tentacles.NexusClient - Crawl https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/
1372 [main] INFO org.apache.creadur.tentacles.NexusClient - Crawl https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/
1661 [main] INFO org.apache.creadur.tentacles.NexusClient - Crawl https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/0.1/
1980 [main] INFO org.apache.creadur.tentacles.NexusClient - Download https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/0.1/apache-tentacles-0.1-jar-with-dependencies.jar
4518 [main] INFO org.apache.creadur.tentacles.NexusClient - Download https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/0.1/apache-tentacles-0.1-javadoc.jar
4799 [main] INFO org.apache.creadur.tentacles.NexusClient - Download https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/0.1/apache-tentacles-0.1-source-release.zip
5080 [main] INFO org.apache.creadur.tentacles.NexusClient - Download https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/0.1/apache-tentacles-0.1-sources.jar
5360 [main] INFO org.apache.creadur.tentacles.NexusClient - Download https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/apache-tentacles/0.1/apache-tentacles-0.1.jar
5642 [main] INFO org.apache.creadur.tentacles.Main - Unpack tentacles/repo/apache-tentacles/0.1/apache-tentacles-0.1-sources.jar
5646 [main] INFO org.apache.creadur.tentacles.Main - Unpack tentacles/repo/apache-tentacles/0.1/apache-tentacles-0.1-jar-with-dependencies.jar
6441 [main] ERROR org.apache.creadur.tentacles.Main - Not a zip tentacles/repo/apache-tentacles/0.1/apache-tentacles-0.1-jar-with-dependencies.jar
6442 [main] INFO org.apache.creadur.tentacles.Main - Unpack tentacles/repo/apache-tentacles/0.1/apache-tentacles-0.1.jar
6445 [main] INFO org.apache.creadur.tentacles.Main - Unpack tentacles/repo/apache-tentacles/0.1/apache-tentacles-0.1-source-release.zip
6449 [main] INFO org.apache.creadur.tentacles.Main - Unpack tentacles/repo/apache-tentacles/0.1/apache-tentacles-0.1-javadoc.jar
日志三类动作:Crawl 为目录爬取(本例三层)、Download 为发行件下载(本例 5 个:4 个 jar 与 1 个 zip)、Unpack 为递归解包。
⚠️ 注意:日志中的
ERROR Not a zip是递归解包阶段对个别非标准 zip 嵌套条目的跳过提示,不中断流程(后续 Unpack 继续执行、报告齐全、退出码 0)。看到该行应人工抽查对应归档内是否遗漏 LICENSE/NOTICE。
4.3 第 1 参数:本地 file: 目录 URI
把本地目录当仓库离线取样,全程不访问网络。准备演示目录并正确运行(-Dfilter 的必要性见 4.5 节):
mkdir -p /root/local-repo/org/apache/creadur
cp /root/tentacles/apache-tentacles-0.1-source-release.zip /root/local-repo/org/apache/creadur/
cd /root/local-repo && java -ea -Dfilter='.*' -jar /root/tentacles/apache-tentacles-0.1-jar-with-dependencies.jar file:/root/local-repo/ out-b
实测输出:
0 [main] INFO org.apache.creadur.tentacles.Main - Launching Apache Tentacles ...
39 [main] INFO org.apache.creadur.tentacles.Main - Remote repository: file:/root/local-repo/
40 [main] INFO org.apache.creadur.tentacles.Main - Local root directory: out-b
43 [main] INFO org.apache.creadur.tentacles.Main - Copy file:/root/local-repo/org/apache/creadur/apache-tentacles-0.1-source-release.zip
43 [main] INFO org.apache.creadur.tentacles.Main - Unpack out-b/repo/org/apache/creadur/apache-tentacles-0.1-source-release.zip
本地模式的动作是 Copy(而非 Download),其余流程(解包、报告)与远程模式一致,解包产物同样落在 out-b/content/ 下的 .contents/ 目录。
4.4 第 2 参数:本地输出目录名
省略第 2 参数时输出根目录名取 URI 路径末段(4.2 节实测为 tentacles/);显式传入时按传入值创建,相对与绝对路径均实测生效(如传 /root/x5 时日志为 Local root directory: /root/x5,退出码 0,目录内含 archives.html、content/、licenses.html、notices.html、repo/、style.css,与 4.7 节清单一致)。
4.5 -Dfilter 系统属性:本地模式的路径过滤器
该属性仅对 file: 本地模式生效,默认值 org/apache/openejb(源自 Tentacles 在 OpenEJB 中的出身),匹配规则是对归档文件绝对路径做正则全匹配(源码 IsArchiveInPathFilter.accept 中为 path.matches(pathNameFilter))。两个实测结论:
结论一:不覆盖默认值必然空跑。
cd /root/local-repo && rm -rf out-a && java -ea -jar /root/tentacles/apache-tentacles-0.1-jar-with-dependencies.jar file:/root/local-repo/ out-a
实测输出(仅 3 行启动信息,无 Copy/Unpack 动作;out-a/repo/ 为空目录且退出码 0):
0 [main] INFO org.apache.creadur.tentacles.Main - Launching Apache Tentacles ...
38 [main] INFO org.apache.creadur.tentacles.Main - Remote repository: file:/root/local-repo/
38 [main] INFO org.apache.creadur.tentacles.Main - Local root directory: out-a
**结论二:子串写法不命中。**全匹配意味着 -Dfilter=creadur 不命中任何路径,必须写 .*creadur.* 或 .* 等正则完整形态:
cd /root/local-repo && java -ea -Dfilter='.*' -jar /root/tentacles/apache-tentacles-0.1-jar-with-dependencies.jar file:/root/local-repo/ out-b
实测输出(.* 覆盖后正常 Copy):
43 [main] INFO org.apache.creadur.tentacles.Main - Copy file:/root/local-repo/org/apache/creadur/apache-tentacles-0.1-source-release.zip
远程 HTTP 模式不受该属性影响(远程爬取按后缀过滤,写死在源码 Main.CRAWL_PATTERN,值为 .*\.(jar|zip|war|ear|rar|tar.gz))。
4.6 -ea 开关:带与不带的实测对比
官方 README 要求 java -ea -jar 运行(断言必须启用)。实测不带 -ea 的完整下载解包流程:
cd /root && java -jar /root/tentacles/apache-tentacles-0.1-jar-with-dependencies.jar https://repository.apache.org/content/repositories/releases/org/apache/creadur/tentacles/ /root/noea-out > /tmp/noea.log 2>&1; echo "exit=$?"; grep -cE 'Download' /tmp/noea.log
实测输出(下载计数为 5,流程完整):
exit=0
5
4.7 输出物清单
一次成功运行后,输出根目录内固定生成以下内容(以 4.2 节为例):
| 产物 | 说明 |
|---|---|
repo/ | 原样归档的发行件,按仓库相对路径存放 |
content/<归档名>.contents/ | 每个归档的递归解包内容,嵌套归档继续下钻 .contents |
archives.html | 主报告:全部顶层归档及其 LICENSE/NOTICE 声明清单 |
<归档名>.licenses.html / <归档名>.notices.html | 每个归档的法定文件详情页(Declared/Undeclared 分段) |
licenses.html / notices.html | 全部许可/声明文本的汇总页 |
style.css | 报告样式 |
4.8 退出码与异常输入行为
Tentacles 所有实测场景退出码均为 0,成败只能通过日志与产出判断。逐场景实测(均无管道直采 $?):
| 场景 | 命令要点 | 实测退出码 | 行为 |
|---|---|---|---|
| 无参数 | java -ea -jar …jar | 0 | 输出 2 行 ERROR 引导后退出 |
| 正常远程下载 | 第 1 参数 https URI | 0 | 下载、解包、出报告 |
| 不支持协议 | 第 1 参数 s3://example/repo | 0 | 静默生成空报告骨架 |
| 非法 URI | 第 1 参数 foo | 0 | 静默生成空报告骨架 |
| 本地默认过滤器 | file: 模式不带 -Dfilter | 0 | 不复制任何文件,只生成空骨架 |
| 本地正常取样 | file: 模式带 -Dfilter='.*' | 0 | Copy、解包、出报告 |
以不支持协议场景为例,实测回显中无任何 ERROR 提示、只有 3 行启动信息(Launching、Remote repository: s3://example/repo、Local root directory: out-e2),随后静默生成空报告骨架退出;非法 URI foo 的行为与之完全一致。
五、Apache Rat 0.18 命令详解(联动工具)
Tentacles 摊开发行件,Rat 逐文件判定许可头,两者组合成完整流水线。本章先全量转录 Rat 的 --help(命令全集骨架),再逐项实测核心选项。
5.1 --help 全量转录(命令全集)
java -jar /root/tentacles/apache-rat-0.18/apache-rat-0.18.jar --help
实测输出(全文转录,按终端宽度换行原样保留):
INFO: Apache Creadur RAT 0.18 (Apache Software Foundation)
usage: java -jar apache-rat/target/apache-rat-0.18.jar [options] [DIR|ARCHIVE]
====== Available Options ======
-?,--help Print help for the RAT command line interface and exit.
-a [Deprecated for removal since 0.17: Use --edit-license instead.]
-A,--addLicense [Deprecated for removal since 0.17: Use --edit-license instead.]
Add the Apache-2.0 license header to any file with an unknown
license that is not in the exclusion list.
-c,--copyright <arg> [Deprecated for removal since 0.17: Use --edit-copyright instead.]
The copyright message to use in the license headers.
--config <File> File names for system configuration. Multiple values may be
specified. Note that '--' or a following option is required when
using this parameter.
--configuration-no-defaults Ignore default configuration.
--counter-max <CounterPattern> The acceptable maximum number for the specified counter. A value
of '-1' specifies an unlimited number. Multiple values may be
specified. Note that '--' or a following option is required when
using this parameter.
--counter-min <CounterPattern> The minimum number for the specified counter. Multiple values may
be specified. Note that '--' or a following option is required
when using this parameter.
-d,--dir <DirOrArchive> [Deprecated for removal since 0.17: Use the standard '--' to
signal the end of arguments.] Used to indicate end of list when
using options that take multiple arguments.
--dry-run If set do not update the files but generate the reports.
-e,--exclude <Expression> [Deprecated for removal since 0.17: Use --input-exclude instead.]
Excludes files matching <Expression>. Multiple values may be
specified. Note that '--' or a following option is required when
using this parameter.
-E,--exclude-file <File> [Deprecated for removal since 0.17: Use --input-exclude-file
instead.] Reads <Expression> entries from a file. Entries will be
excluded from processing.
--edit-copyright <arg> The copyright message to use in the license headers. Usually in
the form of "Copyright 2008 Foo". Only valid with --edit-license
--edit-license Add the Apache-2.0 license header to any file with an unknown
license that is not in the exclusion list. By default new files
will be created with the license header, to force the modification
of existing files use the --edit-overwrite option.
--edit-overwrite Forces any changes in files to be written directly to the source
files so that new files are not created. Only valid with
--edit-license.
-f,--force [Deprecated for removal since 0.17: Use --edit-overwrite instead.]
Forces any changes in files to be written directly to the source
files so that new files are not created.
--help-licenses Print information about registered licenses.
--include <Expression> [Deprecated for removal since 0.17: Use --input-include instead.]
Includes files matching <Expression>. Will override excluded
files. Multiple values may be specified. Note that '--' or a
following option is required when using this parameter.
--includes-file <File> [Deprecated for removal since 0.17: Use --input-include-file
instead.] Reads <Expression> entries from a file. Entries will be
excluded from processing.
--input-exclude <Expression> Excludes files matching <Expression>. Multiple values may be
specified. Note that '--' or a following option is required when
using this parameter.
--input-exclude-file <File> Reads <Expression> entries from a file. Entries will be excluded
from processing.
--input-exclude-parsed-scm <StandardCollection> Parse SCM based exclusion files to exclude specified files and
directories. This action can apply to any standard collection that
implements a file processor. Multiple values may be specified.
Note that '--' or a following option is required when using this
parameter.
--input-exclude-size <Integer> Excludes files with sizes less than the number of bytes specified.
--input-exclude-std <StandardCollection> Excludes files defined in standard collections based on commonly
occurring groups. Excludes any path matcher actions but DOES NOT
exclude any file processor actions. Multiple values may be
specified. Note that '--' or a following option is required when
using this parameter.
--input-include <Expression> Includes files matching <Expression>. Will override excluded
files. Multiple values may be specified. Note that '--' or a
following option is required when using this parameter.
--input-include-file <File> Reads <Expression> entries from a file. Entries will override
excluded files.
--input-include-std <StandardCollection> Includes files defined in standard collections based on commonly
occurring groups. Includes any path matcher actions but DOES NOT
include any file processor actions. Multiple values may be
specified. Note that '--' or a following option is required when
using this parameter.
--input-source <File> A file containing file names to process. File names must use linux
directory separator ('/') or none at all. File names that do not
start with '/' are relative to the directory where the argument is
located. Multiple values may be specified. Note that '--' or a
following option is required when using this parameter.
--license-families-approved <FamilyID> A comma separated list of approved license family IDs. These
license families will be added to the list of approved license
families.
--license-families-approved-file <File> Name of file containing comma separated lists of approved family
IDs.
--license-families-denied <FamilyID> A comma separated list of denied License family IDs. These license
families will be removed from the list of approved licenses. Once
license families are removed they can not be added back.
--license-families-denied-file <File> Name of file containing comma separated lists of denied license
IDs. These license families will be removed from the list of
approved licenses. Once license families are removed they can not
be added back.
--licenses <File> [Deprecated for removal since 0.17: Use --config instead.] File
names for system configuration. Multiple values may be specified.
Note that '--' or a following option is required when using this
parameter.
--licenses-approved <LicenseID> A comma separated list of approved License IDs. These licenses
will be added to the list of approved licenses.
--licenses-approved-file <File> Name of file containing comma separated lists of approved License
IDs.
--licenses-denied <LicenseID> A comma separated list of denied License IDs. These licenses will
be removed from the list of approved licenses. Once licenses are
removed they can not be added back.
--licenses-denied-file <File> Name of file containing comma separated lists of the denied
license IDs. These licenses will be removed from the list of
approved licenses. Once licenses are removed they can not be added
back.
--list-families <LicenseFilter> [Deprecated for removal since 0.17: Use --output-families
instead.] List the defined license families. (Default value =
NONE)
--list-licenses <LicenseFilter> [Deprecated for removal since 0.17: Use --output-licenses
instead.] List the defined licenses. (Default value = NONE)
--log-level <LogLevel> Sets the log level. (Default value = WARN)
--no-default-licenses [Deprecated for removal since 0.17: Use
--configuration-no-defaults instead.] Ignore default
configuration.
-o,--out <File> [Deprecated for removal since 0.17: Use --output-file instead.]
Define the output file where to write a report to. (Default value
= System.out)
--output-archive <ProcessingType> Specifies the level of detail in ARCHIVE file reporting. (Default
value = NOTIFICATION)
--output-families <LicenseFilter> List the defined license families. (Default value = NONE)
--output-file <File> Define the output file where to write a report to. (Default value
= System.out)
--output-licenses <LicenseFilter> List the defined licenses. (Default value = NONE)
--output-standard <ProcessingType> Specifies the level of detail in STANDARD file reporting. (Default
value = ABSENCE)
--output-style <StyleSheet> XSLT stylesheet to use when creating the report. Either an
external xsl file may be specified or one of the internal named
sheets.
-s,--stylesheet <StyleSheet> [Deprecated for removal since 0.17: Use --output-style instead.]
XSLT stylesheet to use when creating the report.
--scan-hidden-directories [Deprecated for removal since 0.17: Use --input-include-std with
'HIDDEN_DIR' argument instead.] Scans hidden directories.
-x,--xml [Deprecated for removal since 0.17: Use --output-style with the
'xml' argument instead.] forces XML output rather than the textual
report.
====== Argument Types ======
<File>
A file name.
<Integer>
An integer value.
<DirOrArchive>
A directory or archive file to scan.
<Expression>
A file matching pattern usually of the form used in Ant build files and '.gitignore' files (see
https://ant.apache.org/manual/dirtasks.html#patterns for examples). Regular expression patterns may be
specified by surrounding the pattern with '%regex[' and ']'. For example '%regex[[A-Z].*]' would match files
and directories that start with uppercase latin letters.
<LicenseFilter>
A defined filter for the licenses to include. Valid values: ALL, APPROVED, NONE.
<LogLevel>
The log level to use. Valid values DEBUG, INFO, WARN, ERROR, OFF.
<ProcessingType>
Specifies how to process file types. Valid values are:
NOTIFICATION: List file as present
PRESENCE: List any licenses found
ABSENCE: List licenses found and any unknown licences
<StyleSheet>
Either an external xsl file or one of the internal named sheets. Internal sheets are:
plain-rat: The default style.
missing-headers: Produces a report of files that are missing headers.
unapproved-licenses: Produces a report of the files with unapproved licenses.
xml: Produces output in pretty-printed XML.
<LicenseID>
The ID for a license.
<FamilyID>
The ID for a license family.
<StandardCollection>
Defines standard expression patterns (see above). Valid values are:
ALL: All of the Standard Excludes combined.
ARCH: The files and directories created by an ARCH source code control based tool.
--help 退出码为 0(实测)。标准集合(StandardCollection)还包含 BAZAAR、BITKEEPER 等版本控制工具的排除清单。
5.2 基本扫描:位置参数与 --output-file
对 Tentacles 解包出的源码树做文件级扫描,报告写入文件(位置参数为待扫目录,报告路径经 --output-file 指定,stdout 重定向到文件后经 grep -v SLF4J 过滤日志前缀,以下同):
cd /root/tentacles-demo && java -jar /root/tentacles/apache-rat-0.18/apache-rat-0.18.jar --output-file /root/rat-src-report.txt tentacles/content/apache-tentacles/0.1/apache-tentacles-0.1-source-release.zip.contents/apache-tentacles-0.1/src > /root/rat-src-stdout.txt 2>&1
grep -v SLF4J /root/rat-src-stdout.txt | head -14
实测输出:
INFO: Apache Creadur RAT 0.18 (Apache Software Foundation)
INFO: RAT summary:
INFO: Approved: 39
INFO: Archives: 0
INFO: Binaries: 0
INFO: Document types: 1
INFO: Ignored: 0
INFO: License categories: 2
INFO: License names: 2
INFO: Notices: 0
INFO: Standards: 42
INFO: Unapproved: 3
INFO: Unknown: 3
ERROR: Unexpected count for UNAPPROVED, limit is [0,0]. Count: 3
Exception in thread "main" org.apache.rat.document.RatDocumentAnalysisException: Issues with UNAPPROVED
报告文件中未批准文件以 ! 标注:
grep -E '^!' /root/rat-src-report.txt
实测输出:
! Unapproved: 3 A count of unapproved licenses.
! /main/resources/licenses/cddl-1.0.txt
! /main/resources/licenses/cpl-1.0.txt
! /site/site.xml
扫描级别选项 --output-archive / --output-standard 均取 ProcessingType 三值:NOTIFICATION(仅列出存在)、PRESENCE(列出发现的许可)、ABSENCE(列出发现与缺失,最详尽),默认值分别为 NOTIFICATION 与 ABSENCE(见 5.1 节转录)。对归档目录(Tentacles 的 repo/)应显式加 --output-archive ABSENCE:默认级别下归档内部的许可完全不被识别(实测 Approved: 0、License categories: 0),加 ABSENCE 后识别出 4 个 jar 内的 Apache License 2.0(Approved: 4、License categories: 2,Archives: 5);对已解包源码树(content/)默认级别即可覆盖文件级审计。
💡 技术拓展:Rat 报告的计数器(Approved/Standards/Unapproved/Unknown 等)不只是统计——每个计数器带有内置阈值区间(如 UNAPPROVED 上限 0),超阈值即抛异常并以非零码退出。这让「许可审计通过与否」可直接程序化判定,但也意味着扫描失败与「审计不通过」在退出码上不可区分,见 5.5 节。
5.3 --input-exclude:多值选项与参数顺序坑
--input-exclude 可多次出现以排除匹配文件,但它是多值选项:后续一切非选项参数(含位置参数目录)都会被它吞掉,直到遇到 -- 或另一个选项。实测错误用法(目录放在最后,被吞后报错):
java -jar /root/tentacles/apache-rat-0.18/apache-rat-0.18.jar --output-file /root/rat-excl-report.txt --input-exclude **/resources/licenses/cddl-1.0.txt --input-exclude **/resources/licenses/cpl-1.0.txt --input-exclude **/site/site.xml tentacles/content/apache-tentacles/0.1/apache-tentacles-0.1-source-release.zip.contents/apache-tentacles-0.1/src > /root/rat-excl-stdout.txt 2>&1
grep -v SLF4J /root/rat-excl-stdout.txt | head -3
实测输出:
INFO: Apache Creadur RAT 0.18 (Apache Software Foundation)
ERROR: No directories or files specified for scanning. Did you forget to close a multi-argument option?
usage: java -jar apache-rat/target/apache-rat-0.18.jar [options] [DIR|ARCHIVE]
正确用法:把待扫目录作为第一个参数放在所有选项之前(或用 -- 显式分隔):
java -jar /root/tentacles/apache-rat-0.18/apache-rat-0.18.jar tentacles/content/apache-tentacles/0.1/apache-tentacles-0.1-source-release.zip.contents/apache-tentacles-0.1/src --output-file /root/rat-excl-report.txt --input-exclude **/resources/licenses/cddl-1.0.txt --input-exclude **/resources/licenses/cpl-1.0.txt --input-exclude **/site/site.xml > /root/rat-excl-stdout.txt 2>&1; echo "exit=$?"
grep -v SLF4J /root/rat-excl-stdout.txt | head -14
实测输出(3 个无许可头文件被合理排除后,审计干净通过、退出码 0):
exit=0
INFO: Apache Creadur RAT 0.18 (Apache Software Foundation)
INFO: RAT summary:
INFO: Approved: 39
INFO: Archives: 0
INFO: Binaries: 0
INFO: Document types: 2
INFO: Ignored: 3
INFO: License categories: 1
INFO: License names: 1
INFO: Notices: 0
INFO: Standards: 39
INFO: Unapproved: 0
INFO: Unknown: 0
5.4 --help-licenses:查看内置许可证清单
java -jar /root/tentacles/apache-rat-0.18/apache-rat-0.18.jar --help-licenses
实测输出(节选,退出码 0):
INFO: Apache Creadur RAT 0.18 (Apache Software Foundation)
Listing of licenses for Apache Creadur RAT 0.18 (Apache Software Foundation)
====== Licenses ======
The defined licenses are:
AL1.0 (Apache License 1.0)
该清单中的许可证 ID 即 --licenses-approved / --licenses-denied 等选项接受的 <LicenseID> 取值来源。另注意 Rat 0.18 没有 --version 选项,误用会得到 ERROR: Unrecognized option: --version 与「Please use the --help option」提示(实测),版本号一律看任何命令输出首行的 INFO。
5.5 退出码与计数阈值治理
Rat 0.18 的退出码语义(全部实测):--help、--help-licenses、排除后干净的扫描为 0;存在超阈值计数时抛 RatDocumentAnalysisException、退出码 1,但报告文件仍完整生成。阈值由 --counter-min / --counter-max 调整,取值格式为 计数器名:数值(冒号分隔;实测逗号、等号写法均报 is not a valid Counter,如 'UNAPPROVED,5' is not a valid Counter)。将归档级扫描的 4 个默认阈值全部放宽后即可干净通过:
cd /root/tentacles-demo && java -jar /root/tentacles/apache-rat-0.18/apache-rat-0.18.jar --counter-max 'UNAPPROVED:5' --counter-min 'STANDARDS:0' --counter-min 'LICENSE_CATEGORIES:0' --counter-min 'LICENSE_NAMES:0' --output-file /tmp/rat-cm.txt tentacles/repo > /root/rat-cm-stdout.txt 2>&1; echo "exit=$?"
实测输出:
exit=0
默认阈值区间(由未放宽时的报错文案实测反推):UNAPPROVED [0,0]、STANDARDS [1,2147483647]、LICENSE_CATEGORIES [1,2147483647]、LICENSE_NAMES [1,2147483647]。自动化流水线可治理阈值让干净状态退出码归 0,或以报告文件生成为准、退出码仅作参考。
六、注意事项
- Tentacles 退出码恒为 0:成败判断看日志动作(
Crawl/Download/Copy/Unpack)与repo/、content/、HTML 报告产出,不能依赖退出码(4.8 节六场景实测)。 - 本地模式必须覆盖
-Dfilter:默认值org/apache/openejb几乎必然不命中,且空跑无任何警告、退出码 0(4.5 节实测);过滤器是对绝对路径的正则全匹配,子串写法无效。 - Rat 多值选项吞位置参数:
--input-exclude等带「Multiple values may be specified」注释的选项,必须把待扫目录放在最前或用--分隔(5.3 节实测)。 - Rat 退出码 1 不等于扫描失败:报告照常生成,含义是「审计发现超阈值项」(5.5 节实测)。
- 下载后缀写死:Tentacles 只抓
jar|zip|war|ear|rar|tar.gz,tar.gz只下载不解包,其余格式无法通过参数扩展。
七、常见问题
Q1:Tentacles 运行完 repo/ 是空的,哪里错了?
按顺序排查:本地模式是否漏了 -Dfilter(默认过滤器不命中任何路径);URI 协议是否为 http/https/file: 之外的不识别值(静默空跑);URL 下是否有匹配后缀的文件。正常取样必有 Crawl(远程)或 Copy(本地)日志行。
Q2:Tentacles 日志出现 ERROR Not a zip 怎么处理?
该归档(或其嵌套条目)存在非标准 zip 结构,Tentacles 跳过该条目继续,整体流程与退出码不受影响;需人工抽查被跳过归档的法定文件是否齐全。
Q3:Rat 报告生成了但退出码 1,CI 流水线算失败吗?
按 5.5 节处理:报告文件完整生成即扫描成功;退出码 1 表示计数器超阈值(审计发现问题)。可调整阈值策略或在流水线中显式区分两种退出码含义;调整时 --counter-max 取值必须是 计数器名:数值 冒号格式(如 UNAPPROVED:5),逗号、等号写法均实测报 is not a valid Counter。
Q4:Rat 传了目录却报 No directories or files specified for scanning? 目录参数被前面的多值选项吞掉了,把目录移到所有选项之前(5.3 节实测对比)。
八、参考链接
- Apache Tentacles 官方站点与 0.1 发行目录:https://creadur.apache.org/tentacles/ 、https://downloads.apache.org/creadur/apache-tentacles-0.1/
- Tentacles 官方源码仓库:https://github.com/apache/creadur-tentacles
- Apache Rat 官方站点与 0.18 发行目录:https://creadur.apache.org/rat/ 、https://downloads.apache.org/creadur/apache-rat-0.18/
- 站内延伸:安装与集成实操见《Apache Tentacles 在 Ubuntu 22.04 集成使用指南》,工具定位与选型见《Apache Tentacles 介绍与选型指南》