Ubuntu 22.04 安装 Apache Hop 2.19.0 指南
在 Ubuntu 22.04 上从零完整安装 Apache Hop 2.19.0 数据编排平台:前置依赖、官方包下载、项目与运行配置、转换与工作流实测执行,并说明 JVM 内存与卸载方式。
Ubuntu 22.04 安装 Apache Hop 2.19.0 指南
目标:在 Ubuntu 22.04 LTS 上从零完整安装 Apache Hop 2.19.0,配置 JDK、项目与运行配置,并用内置命令行实测创建、执行一个转换(pipeline)与一个工作流(workflow),全部命令与回显均为本机实测。本指南不涉及产品代码。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(x86_64) |
| 内核版本 | 5.15.x |
| 安装软件 | Apache Hop 2.19.0(官方 client 发行包) |
| 运行 JDK | OpenJDK 21.0.12.1 LTS(/usr/lib/jvm/java-21-openjdk-amd64) |
| 安装目录 | /opt/apache-hop/hop |
| 数据/项目目录 | /opt/data/apache-hop/project |
| 日志目录 | /opt/data/apache-hop/logs |
| 本地 Web 日志端口 | 8080(hop server 选装) |
| 示例账号 | root,示例密码 q1w2e3r4 |
💡 说明:Apache Hop 是 Apache 软件基金会(ASF)开源的数据编排与数据集成平台(ETL/ELT 工具),前身是 Kettle/PDI。它通过「转换(pipeline,
.hpl)」与「工作流(workflow,.hwf)」两种可执行单元完成数据抽取、转换、加载与编排,可无图形界面地以hop/hop-run命令行在服务器上运行。
二、前置条件
安装前确认以下条件满足:
- 系统为 Ubuntu 22.04 LTS,可用
apt安装软件包。验证系统版本:
cat /etc/os-release | head -3
实测回显(节选):
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
-
具备 root 权限。下文所有安装类命令均以 root 身份执行;普通用户使用时请加
sudo。 -
可访问 Apache 下载站。本文使用官方发行镜像站
https://dlcdn.apache.org(实测HTTP/2 200可达)。 -
必装解压工具
unzip。Apache Hop 官方交付的是.zip发行包,先安装解压工具:
apt-get update
apt-get install -y unzip
实测回显(节选):
Reading package lists... Done
Setting up unzip (6.0-...+1ubuntu...)
💡 说明:Hop 官方将完整功能发行包统一命名为
apache-hop-client-<版本>.zip(客户端发行包,内含全部命令脚本与插件),本指南基于该发行包部署。
三、版本选型说明
3.1 当前版本与发行包
截至本文成稿,Apache Hop 官方发布站 https://dlcdn.apache.org/hop/ 可用的最新稳定版为 2.19.0(2026-08-17 发布)。历史版本包括 2.18.1、2.18.0、2.17.0、2.10.0 等,发行包命名规律均为 apache-hop-client-<版本>.zip(约 330MB,含命令脚本、插件与依赖库)。
3.2 JDK 版本要求(重要)
实测确认:Apache Hop 2.19.0 编译目标为 JDK 21(字节码版本 65.0),必须使用 JDK 21 运行。若误用 JDK 17,启动会直接报 UnsupportedClassVersionError。JDK 11/17 适用于较早的 Hop 1.x 与部分早期 2.x 版本,安装 2.19.0 请务必选用 JDK 21。
| 组件 | 推荐版本 | 实测结果 |
|---|---|---|
| JDK | 21(LTS,如 21.0.12.1) | ✅ 可正常运行 |
| JDK | 17(如 17.0.20.1) | ❌ 报 UnsupportedClassVersionError,不可运行 |
| JDK | 11(如 11.0.32.1) | 不适用 2.19.0,仅适用旧版本 |
3.3 版本选择建议
- 生产环境推荐直接采用当前最新稳定版 2.19.0,配套 JDK 21 LTS。
- 若受内网管制无法访问外网,可在可联网机器下载
apache-hop-client-2.19.0.zip后离线传输并解压部署。 - 升级时只需替换
/opt/apache-hop/hop下的发行包并复用已有项目目录即可,配置相对路径使用${PROJECT_HOME},不受安装目录变更影响。
四、部署步骤
4.1 安装 JDK 21 并确认 JAVA_HOME
2.19.0 要求 JDK 21。若系统未安装,则通过 apt 安装:
apt-get install -y openjdk-21-jre-headless
查看已安装的 JDK 目录列表,确认存在 java-21-openjdk-amd64:
ls /usr/lib/jvm/
实测回显:
java-1.11.0-openjdk-amd64
java-1.17.0-openjdk-amd64
java-1.21.0-openjdk-amd64
java-11-openjdk-amd64
java-17-openjdk-amd64
java-21-openjdk-amd64
openjdk-11
openjdk-17
openjdk-21
确认 JDK 21 版本信息:
/usr/lib/jvm/java-21-openjdk-amd64/bin/java -version
实测回显:
openjdk version "21.0.12.1" 2026-08-18
OpenJDK Runtime Environment (build 21.0.12.1+1-1-22.04.4-Ubuntu)
OpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-22.04.4-Ubuntu, mixed mode, sharing)
4.2 下载解压并安装 Hop 2.19.0
创建安装目录,并下载官方发行包(下至临时目录 /tmp):
mkdir -p /opt/apache-hop
curl -sO https://dlcdn.apache.org/hop/2.19.0/apache-hop-client-2.19.0.zip
ls -lh /tmp/apache-hop-client-2.19.0.zip
实测回显:
-rw-r--r-- 1 root root 333M Oct 11 05:41 /tmp/apache-hop-client-2.19.0.zip
解压发行包到安装目录:
unzip -q /tmp/apache-hop-client-2.19.0.zip -d /opt/apache-hop/
ls -la /opt/apache-hop/hop/ | head -20
实测回显(节选,可见主命令脚本 hop 及 hop-run.sh 等工具脚本位于安装目录顶层):
drwxr-xr-x 8 root root 4096 Aug 12 11:19 .
-rw-r--r-- 1 root root 142529 Aug 12 11:19 LICENSE
-rw-r--r-- 1 root root 753 Aug 12 11:19 NOTICE
-rw-r--r-- 1 root root 2545 Aug 12 11:19 README.txt
drwxr-xr-x 3 root root 4096 Aug 12 11:19 config
-rwxr-xr-x 1 root root 5512 Aug 12 11:19 hop
-rwxr-xr-x 1 root root 4738 Aug 12 11:19 hop-conf.sh
-rwxr-xr-x 1 root root 4686 Aug 12 11:19 hop-encrypt.sh
-rwxr-xr-x 1 root root 5332 Aug 12 11:19 hop-gui.sh
-rwxr-xr-x 1 root root 4737 Aug 12 11:19 hop-run.sh
-rwxr-xr-x 1 root root 4740 Aug 12 11:19 hop-search.sh
-rwxr-xr-x 1 root root 4999 Aug 12 11:19 hop-server.sh
drwxr-xr-x 5 root root 4096 Aug 12 11:19 lib
drwxr-xr-x 10 root root 4096 Aug 12 11:19 plugins
drwxr-xr-x 2 root root 4096 Aug 12 11:19 pwd
⚠️ 注意:本发行包把
hop、hop-run.sh等脚本放在安装目录顶层(父目录即安装目录,无bin/子目录),可直接把<安装目录>(即/opt/apache-hop/hop)加入PATH。
4.3 配置环境变量并验证版本
把 Java、Hop 环境变量写入 /etc/profile.d/hop-env.sh,使登录 shell 自动加载:
cat > /etc/profile.d/hop-env.sh <<'EOF'
# Apache Hop environment
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
export HOP_HOME=/opt/apache-hop/hop
export PATH="$HOP_HOME:$PATH"
export HOP_OPTIONS="-Xms256m -Xmx512m"
EOF
chmod 644 /etc/profile.d/hop-env.sh
💡 说明:
HOP_OPTIONS控制 Hop Java 进程的默认 JVM 参数。Hop 启动脚本默认堆上限为-Xmx2048m,此处主动覆盖为-Xms256m -Xmx512m,将堆限制在 256–512MB(见「五、配置说明」中的 JVM 内存专项)。
重新加载环境变量后验证 Java 与 Hop 均已就绪:
source /etc/profile.d/hop-env.sh
echo "JAVA_HOME=$JAVA_HOME"
echo "HOP_HOME=$HOP_HOME"
echo "HOP_OPTIONS=$HOP_OPTIONS"
hop --version
实测回显:
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
HOP_HOME=/opt/apache-hop/hop
HOP_OPTIONS=-Xms256m -Xmx512m
2.19.0
⚠️ 注意:实测
hop --version会正确打印版本号2.19.0,但该命令(以及hop --help)退出码为1,这是 Hop 命令行对 help/version 分支的既有行为,拉到版本标识即为成功,请勿将其误判为失败。
4.4 初始化项目目录与运行配置
Hop 采用「项目(Project)驱动」的配置模型:所有转换/工作流都必须位于项目的 PROJECT_HOME 之下,并配好本地运行配置才能执行。本文统一把数据目录 PROJECT_HOME 设为真实数据目录 /opt/data/apache-hop/project。
创建数据目录及子目录,并写入 project-config.json:
mkdir -p /opt/data/apache-hop/project/pipelines
mkdir -p /opt/data/apache-hop/project/workflows
mkdir -p /opt/data/apache-hop/project/metadata
cat > /opt/data/apache-hop/project/project-config.json <<'EOF'
{
"metadataBaseFolder": "${PROJECT_HOME}/metadata",
"unitTestsBasePath": "${PROJECT_HOME}",
"dataSetsCsvFolder": "${PROJECT_HOME}/datasets",
"enforcingExecutionInHome": true,
"parentProjectName": "",
"config": {
"variables": []
}
}
EOF
把安装目录 hop-config.json 中 default 项目的 projectHome 指向上面这个数据目录:
python3 - <<'PY'
import json
p = "/opt/apache-hop/hop/config/hop-config.json"
d = json.load(open(p))
for c in d["projectsConfig"]["projectConfigurations"]:
if c["projectName"] == "default":
c["projectHome"] = "/opt/data/apache-hop/project"
json.dump(d, open(p, "w"), indent=2)
PY
为 default 项目补齐本地运行配置与审计目录(本地执行需 pipeline-run-configuration/local.json 与 workflow-run-configuration/local.json):
mkdir -p /opt/data/apache-hop/project/metadata/pipeline-run-configuration
mkdir -p /opt/data/apache-hop/project/metadata/workflow-run-configuration
mkdir -p /opt/data/apache-hop/project/metadata/execution-info-location
cat > /opt/data/apache-hop/project/metadata/pipeline-run-configuration/local.json <<'EOF'
{
"engineRunConfiguration": {
"Local": {
"feedback_size": "50000",
"sample_size": "100",
"sample_type_in_gui": "Last",
"rowset_size": "10000",
"safe_mode": false,
"show_feedback": false,
"topo_sort": false,
"gather_metrics": false
}
},
"name": "local",
"configurationVariables": [],
"description": "",
"defaultSelection": true
}
EOF
cat > /opt/data/apache-hop/project/metadata/execution-info-location/local-audit.json <<'EOF'
{
"locationType": "local",
"auditFolder": "/opt/data/apache-hop/audit",
"name": "local-audit"
}
EOF
mkdir -p /opt/data/apache-hop/logs
⚠️ 注意:若不同步创建运行配置,
hop run会报Please specify a run configuration to execute the pipeline with。pipeline-run-configuration/local.json定义了名为local的本地引擎运行配置,是命令行无界面执行转换的关键。
4.5 功能验证:执行一个转换(pipeline)
创建一个最简单的转换 my-first-pipeline.hpl:由 RowGenerator 生成 10 行数据,交给 Dummy 结束。文件写入 /opt/data/apache-hop/project/pipelines/:
cat > /opt/data/apache-hop/project/pipelines/my-first-pipeline.hpl <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<pipeline>
<info>
<name>my-first-pipeline</name>
<name_sync_with_filename>Y</name_sync_with_filename>
<description>my first hop pipeline</description>
<extended_description/>
<pipeline_version/>
<pipeline_type>Normal</pipeline_type>
<parameters/>
<created_user>root</created_user>
<created_date>2026/10/11 10:00:00.000</created_date>
<modified_user>root</modified_user>
<modified_date>2026/10/11 10:00:00.000</modified_date>
</info>
<notepads/>
<order>
<hop><from>Generate Rows</from><to>Dummy</to><enabled>Y</enabled></hop>
</order>
<transform>
<name>Generate Rows</name>
<type>RowGenerator</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning><method>none</method><schema_name/></partitioning>
<fields>
<field><name>x</name><type>Integer</type><length>9</length><precision>-1</precision></field>
<field><name>m</name><type>String</type><length>20</length><precision>-1</precision></field>
</fields>
<interval_in_ms>1000</interval_in_ms>
<last_time_field/>
<limit>10</limit>
<never_ending>N</never_ending>
<row_time_field/>
<attributes/>
<GUI><xloc>96</xloc><yloc>144</yloc></GUI>
</transform>
<transform>
<name>Dummy</name>
<type>Dummy</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning><method>none</method><schema_name/></partitioning>
<attributes/>
<GUI><xloc>304</xloc><yloc>144</yloc></GUI>
</transform>
<transform_error_handling/>
<attributes/>
</pipeline>
EOF
进入项目目录,用 hop run 执行该转换:
cd /opt/data/apache-hop/project
hop run -f pipelines/my-first-pipeline.hpl
实测回显:
2026/10/11 05:45:48 - HopRun - Enabling project 'default'
2026/10/11 05:45:48 - HopRun - Two-way password encoder initialized with plugin ID 'Hop' for project 'default'
2026/10/11 05:45:48 - HopRun - Relative path filename specified: /opt/data/apache-hop/project/pipelines/my-first-pipeline.hpl
2026/10/11 05:45:48 - HopRun - Starting pipeline: /opt/data/apache-hop/project/pipelines/my-first-pipeline.hpl
2026/10/11 05:45:48 - my-first-pipeline - Executing this pipeline using the Local Pipeline Engine with run configuration 'local'
2026/10/11 05:45:48 - my-first-pipeline - Execution started for pipeline [my-first-pipeline]
2026/10/11 05:45:48 - Generate Rows.0 - Finished processing (I=0, O=0, R=0, W=10, U=0, E=0)
2026/10/11 05:45:48 - Dummy.0 - Finished processing (I=0, O=0, R=10, W=10, U=0, E=0)
2026/10/11 05:45:48 - my-first-pipeline - Pipeline duration : 0.093 seconds [ 0.093" ]
2026/10/11 05:45:48 - my-first-pipeline - Execution finished on a local pipeline engine with run configuration 'local'
✅ 验证要点:日志中出现
Starting pipeline、Execution started for pipeline、各变换的Finished processing (… W=10 …)统计,以及结尾Pipeline duration与Execution finished on a local pipeline engine with run configuration 'local',进程退出码为0,即转换执行成功。Generate Rows.0写出(W)10 行、Dummy.0读入(R)10 行。
4.6 功能验证:执行一个工作流(workflow)
创建同名简单工作流 my-first-workflow.hwf:Start 起始动作 → DUMMY 空动作。写入 /opt/data/apache-hop/project/workflows/:
cat > /opt/data/apache-hop/project/workflows/my-first-workflow.hwf <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<workflow>
<name>my-first-workflow</name>
<name_sync_with_filename>Y</name_sync_with_filename>
<description>my first hop workflow</description>
<extended_description/>
<workflow_version/>
<workflow_status>0</workflow_status>
<created_user>root</created_user>
<created_date>2026/10/11 10:00:00.000</created_date>
<modified_user>root</modified_user>
<modified_date>2026/10/11 10:00:00.000</modified_date>
<parameters/>
<actions>
<action>
<name>Start</name>
<description/>
<type>SPECIAL</type>
<attributes/>
<DayOfMonth>1</DayOfMonth>
<doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution>
<hour>12</hour>
<intervalMinutes>60</intervalMinutes>
<intervalSeconds>0</intervalSeconds>
<minutes>0</minutes>
<repeat>N</repeat>
<schedulerType>0</schedulerType>
<weekDay>1</weekDay>
<parallel>N</parallel>
<xloc>48</xloc><yloc>160</yloc>
<attributes_hac/>
</action>
<action>
<name>Dummy Action</name>
<description/>
<type>DUMMY</type>
<attributes/>
<parallel>N</parallel>
<xloc>176</xloc><yloc>160</yloc>
<attributes_hac/>
</action>
</actions>
<hops>
<hop><from>Start</from><to>Dummy Action</to><enabled>Y</enabled><evaluation>Y</evaluation><unconditional>Y</unconditional></hop>
</hops>
<notepads/>
<attributes/>
</workflow>
EOF
用 hop run 执行该工作流:
cd /opt/data/apache-hop/project
hop run -f workflows/my-first-workflow.hwf
实测回显:
2026/10/11 05:46:08 - HopRun - Enabling project 'default'
2026/10/11 05:46:08 - HopRun - Two-way password encoder initialized with plugin ID 'Hop' for project 'default'
2026/10/11 05:46:08 - HopRun - Relative path filename specified: /opt/data/apache-hop/project/workflows/my-first-workflow.hwf
2026/10/11 05:46:08 - HopRun - Starting workflow: /opt/data/apache-hop/project/workflows/my-first-workflow.hwf
2026/10/11 05:46:08 - my-first-workflow - Start of workflow execution
2026/10/11 05:46:08 - my-first-workflow - Starting action [Start]
2026/10/11 05:46:08 - my-first-workflow - Finished action [Start] (result=[true])
2026/10/11 05:46:08 - my-first-workflow - Starting action [Dummy Action]
2026/10/11 05:46:08 - my-first-workflow - Finished action [Dummy Action] (result=[true])
2026/10/11 05:46:08 - my-first-workflow - Workflow execution finished
2026/10/11 05:46:08 - my-first-workflow - Workflow duration : 0.027 seconds [ 0.027" ]
✅ 验证要点:日志中出现
Start of workflow execution、每个动作的Starting action … / Finished action … (result=[true])、结尾Workflow execution finished与Workflow duration,退出码为0,即工作流执行成功。
五、配置说明
5.1 全局配置入口
hop-config.json(<安装目录>/config/hop-config.json):全局级配置,含语言、项目列表与默认项目等。示例字段:LocaleDefault、projectsConfig.enabled、projectsConfig.projectMandatory、projectsConfig.defaultProject、projectsConfig.projectConfigurations[].projectName/projectHome/configFilename。project-config.json(<PROJECT_HOME>/project-config.json):项目级配置,含元数据基路径与行为开关。常用键见 4.4 节写的文件内容(metadataBaseFolder、enforcingExecutionInHome等)。/etc/profile.d/hop-env.sh:登录环境变量(JAVA_HOME、HOP_HOME、PATH、HOP_OPTIONS)。hop启动脚本(<安装目录>/hop):Hop 对 Java 的定位顺序为HOP_JAVA_HOME→JAVA_HOME→ 系统java;内置默认HOP_OPTIONS="-Xmx2048m"。
5.2 本地运行配置(Run Configuration)
hop run 无界面执行转换/工作流时,依赖项目 metadata/pipeline-run-configuration/(转换)与 metadata/workflow-run-configuration/(工作流)下的 local.json。关键本地引擎参数:
| 参数 | 默认值 | 含义 |
|---|---|---|
feedback_size | 50000 | 反馈日志周期(处理多少行打印一次反馈) |
sample_size | 100 | 预览采样行数 |
rowset_size | 10000 | 变换之间行集缓冲大小 |
safe_mode | false | 是否开启安全模式 |
gather_metrics | false | 是否采集性能指标 |
5.3 JVM 内存专项(含 Java 进程必备)
Hop 是纯 Java 程序,其启动脚本 hop 中默认 HOP_OPTIONS="-Xmx2048m"(堆上限 2GB)。为了控制服务器内存占用,建议将堆限制在 256–512MB,修改方式如下(本指南已在 4.3 节落地):
- 全局生效:修改
/etc/profile.d/hop-env.sh中的export HOP_OPTIONS="-Xms256m -Xmx512m"并source/重登后生效,适用于所有hop*命令; - 临时生效(仅当前 shell):
export HOP_OPTIONS="-Xms256m -Xmx512m"
- 默认堆的兜底说明:若未设置
HOP_OPTIONS,Hop 会按脚本预设的-Xmx2048m(或镜像环境中的-XX:+AggressiveHeap)启动,安装后请务必确认实际生效值。
验证实际生效的堆参数——启动一个常驻进程(如 hop server)后,用 jps -v 复查:
export HOP_OPTIONS="-Xms256m -Xmx512m"
hop server &
jps -v | grep -i hop | tr ' ' '\n' | grep -E '^\-Xms|^\-Xmx'
实测回显:
-Xms256m
-Xmx512m
✅ 验证要点:
jps -v将 Hop 进程的完整 JVM 参数挂出来,其中出现-Xms256m与-Xmx512m即表示堆限制已按 256–512MB 生效。
六、注意事项
- JDK 版本必须为 21:2.19.0 面向 JDK 21 编译,使用 JDK 17 会报
UnsupportedClassVersionError(见「九、常见问题」Q1)。推荐安装时将JAVA_HOME显式指向 JDK 21 目录。 - 所有可执行文件必须在项目
PROJECT_HOME下:默认enforcingExecutionInHome=true,hop run -f的路径要在项目内(本文用pipelines/与workflows/子目录),否则报「pipeline path is invalid」。 - 运行前必须准备本地运行配置:缺
pipeline-run-configuration/local.json时hop run报Please specify a run configuration to execute the pipeline with。 - 发行包无
bin/子目录:hop与各hop-*.sh脚本位于安装目录顶层,加入PATH时填安装目录本身。 HOP_OPTIONS覆盖默认堆:脚本默认-Xmx2048m,须通过HOP_OPTIONS覆盖到 256–512MB。
七、常见问题
7.1 hop 启动报 UnsupportedClassVersionError
现象:
Error: LinkageError occurred while loading main class org.apache.hop.hop.Hop
java.lang.UnsupportedClassVersionError: org/apache/hop/hop/Hop has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0
定位:当前默认 Java 为 JDK 17(类文件版本 61.0),而 Hop 2.19.0 由 JDK 21(65.0)编译。解决方案:将 JAVA_HOME 指向 JDK 21,例如 export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64(见 4.3 节)。
7.2 hop run 报 Please specify a run configuration to execute the pipeline with
定位:项目 metadata/pipeline-run-configuration/ 缺少 local.json 运行配置。解决方案:按 4.4 节补齐 local.json(engineRunConfiguration.Local 段,名称 local)。
7.3 hop run -f 报 The pipeline path ... is invalid, and will not run successfully
定位:文件不在项目 PROJECT_HOME 内(enforcingExecutionInHome=true)。解决方案:把 .hpl/.hwf 放到项目内(如 pipelines/、workflows/ 子目录),再以相对路径执行。
7.4 hop --version / -h 打印内容正常但退出码为 1
定位:Hop 命令行对 --version/--help 分支统一返回退出码 1(picocli 包装行为),属既有现象。判定标准以是否输出版本号/帮助文本为准,非异常。
八、卸载方式
- 停止 Hop 相关进程(
jps找到org.apache.hop.hop.Hop对应 PID 后kill <PID>),并移除环境变量文件:
kill $(jps -l | grep -E 'org.apache.hop' | awk '{print $1}')
rm -f /etc/profile.d/hop-env.sh
- 删除安装目录与数据目录:
rm -rf /opt/apache-hop
rm -rf /opt/data/apache-hop
- 若 JDK 21 系本次安装且不再使用,可一并卸载:
apt-get purge -y openjdk-21-jre-headless
apt-get autoremove -y
九、参考链接
- Apache Hop 官方下载站:https://dlcdn.apache.org/hop/
- Apache Hop 项目官网:https://hop.apache.org/
- Apache Hop 官方文档(project 配置):https://hop.apache.org/manual/latest/
- Apache Hop GitHub 仓库:https://github.com/apache/hop