Ubuntu 22.04 安装 Apache Oozie 5.2.1 指南
Ubuntu 22.04 从 0 到 1 部署 Apache Oozie 5.2.1:JDK8/Maven 环境与 mkdistro.sh 源码构建(含 txw2 缺失、skipTests 排障)、Hadoop 3.3.6 伪分布式与 MySQL 8 前置、oozie-setup/sharelib/db 初始化、启动验证与常见问题
Ubuntu 22.04 安装 Apache Oozie 5.2.1 指南
目标:在 Ubuntu 22.04 服务器上从 0 到 1 安装 Apache Oozie 5.2.1 并跑通服务:源码构建发行包(mkdistro/Maven)、准备 Hadoop 3.3.6 伪分布式与 MySQL 8 元数据库、初始化 DB schema 与 HDFS sharelib、启动服务并用
oozie admin -status验证。全套流程已在 Ubuntu 22.04(主机名oozie)实测通过,最终 workflow0000000-261014183638552-oozie-root-W与 coordinator0000001-261014183638552-oozie-root-C均跑至 SUCCEEDED。
⚠️ 先读:退役状态与版本认知
Apache Oozie 已于 2025 年 2 月退役、2025 年 4 月完成迁入 Apache Attic(官方页面原文:"Oozie became a Top Level Project in August 2012, retired in February 2025 and the move to the Attic was completed in April 2025.",见 https://attic.apache.org/projects/oozie.html)。5.2.1(2021-02-25 发布)是终版,官方归档 https://archive.apache.org/dist/oozie/5.2.1/ 上只有 2.7M 的源码包 oozie-5.2.1.tar.gz,没有官方二进制发行包——因此本文的主线是「源码构建」。这直接带来四个与旧教程不同的关键认知:
- 发行包必须自建:官方 ENG_Building 原文 "The simplest way to build Oozie is to run the mkdistro.sh script",且 "IMPORTANT: Profile hadoop-3 must be activated if building against Hadoop 3";
- sharelib 是构建产物:
oozie-sharelib-5.2.1.tar.gz随构建的发行包自带(官方 AG_Install 原文称其 "bundled with the distribution"),不存在可下载的官方 sharelib 包; - ext-2.2.zip 从未由 Apache 发布:WebUI 依赖的 ExtJS 2.2 需自行获取,实测存活来源为 Cloudera gplextras 归档;
- 5.x 内嵌 Jetty(9.3.20.v20170531),无需 Tomcat,无
prepare-war子命令:oozie-setup.sh实测子命令仅sharelib create/upgrade、db create/upgrade/postupgrade、export/import。
💡 说明:本文所有命令与回显均来自真实环境逐条实测,禁止照抄时替换版本号。凡出现「⚠️ 坑」小节,都是实测真实发生的问题,按「现象 → 定位 → 解决」沉淀,遇到同类报错可直接照做。
一、环境信息
本文所有命令与回显均在以下环境实测采集。
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04(/etc/apt/sources.list 使用阿里云源) |
| 主机名 / IP | oozie / 172.17.0.15(内网静态规划,Hadoop 与 Oozie 配置均用主机名) |
| 登录账号 | root |
| Oozie | 5.2.1 源码构建(-Phadoop-3 -Dhadoop.version=3.3.6),安装目录 /opt/oozie-5.2.1 |
| Hadoop | 3.3.6 伪分布式,/opt/hadoop-3.3.6(软链 /opt/hadoop) |
| MySQL | 8.0.46(apt 包 mysql-server,库 oozie) |
| JDK | OpenJDK 1.8.0_504(openjdk-8-jdk,/usr/lib/jvm/java-8-openjdk-amd64) |
| Maven | 3.6.3(apt 源自带) |
| 关键端口 | Oozie 11000、HDFS RPC 9000、YARN RM 8032、MySQL 3306 |
| 下载目录 | /opt/downloads |
| 源码目录 | /opt/oozie-src |
💡 说明:Oozie 与 Hadoop、MySQL 装在同一台机器(伪分布式单机),这是 Oozie 存量环境最常见的最小形态。生产多节点部署时,Oozie Server 单独一台,通过
oozie.service.HadoopAccessorService.hadoop.configurations指向 Hadoop 配置目录即可,其余步骤完全一致。
二、前置条件
本章完成 apt 换源、JDK 8、Maven、SSH 免密与全套基础工具,这些是后续 Hadoop 启动与 Oozie 源码构建的硬前提。
2.1 apt 换源与证书修复
先确认使用 https 阿里云源(生产建议),若 apt-get update 报证书错误,按下方两步修复(⚠️ 坑:最小安装的系统常缺 CA 证书库,https 源握手必失败)。
sed -i 's|https://mirrors.aliyun.com|http://mirrors.aliyun.com|g' /etc/apt/sources.list \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates wget curl \
&& sed -i 's|http://mirrors.aliyun.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list
命令说明:先把源临时降为 http 明文(不需要证书),apt-get update 刷新包列表并安装 ca-certificates 证书库与 wget/curl,再换回 https。
实测中该步骤对应的两条真实报错(修复前):
W: https://mirrors.aliyun.com/ubuntu/dists/jammy/InRelease Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown. Could not handshake: Error in the certificate verification. [IP: 119.167.132.30 443]
W: Some index files failed to download. They have been ignored, or old ones used instead.
E: Unable to locate package lsof
第二条错误是包列表为空(证书失败导致索引没下载成功)的连锁反应;修好证书后重跑即可。
验证方式:修复后重跑 apt-get update,输出中不再出现上方 W: Certificate verification failed 证书告警;随后 2.2 节的安装命令可正常定位并安装全部软件包(此前包列表为空时报的 E: Unable to locate package lsof 一并消失)。
2.2 安装基础工具与 JDK8
一条命令装齐本指南全部依赖(含 MySQL 8 与构建工具):
DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jdk maven wget curl unzip git \
openssh-client openssh-server mysql-server mysql-client procps net-tools rsync lsof vim less tree jq
命令说明:openjdk-8-jdk 是 Oozie 5.2.1 构建与运行的实际使用版本;maven 用于源码构建;openssh-server 供 Hadoop 启动脚本 SSH 连接本机;mysql-server/mysql-client 是第五章的元数据库;procps 提供 ps、net-tools 提供 netstat。
⚠️ 坑:Ubuntu 22.04 的
openjdk-8-jdk会同时拉入 openjdk-11 作为依赖,且系统默认java指向 11,必须显式切回 8(见 2.3),否则 Maven 构建与 Hadoop/Oozie 启动行为不可控。
2.3 JDK 8 设为默认并配置 JAVA_HOME
逐条执行以下两条切换命令(每条只针对一个 alternatives 目标):
update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
update-alternatives --set javac /usr/lib/jvm/java-8-openjdk-amd64/bin/javac
写入环境变量到 /etc/profile.d/jdk8.sh(并同步进 /root/.bashrc):
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
验证 JDK 版本:
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, sharing)
验证 Maven 版本:
mvn -version
Apache Maven 3.6.3
(输出节选,实测要点:Java version 行应为 1.8.0_504;Maven 版本行如上。)
2.4 SSH 免密(Hadoop 启动脚本依赖)
Hadoop 的 start-dfs.sh/start-yarn.sh 通过 SSH 连接本机拉起守护进程,必须先打通 root 免密。逐条执行:
ssh-keygen -t rsa -N '' -f /root/.ssh/id_rsa -q
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
确保 sshd 在运行(若系统已用 systemd 托管 openssh-server,通常已在运行;本环境实测采用前台方式直接启动,每行只启动一个服务):
mkdir -p /var/run/sshd && /usr/sbin/sshd
验证免密登录(执行后无报错退出即代表打通):
ssh -o StrictHostKeyChecking=no localhost true
2.5 构建期 Maven 本地仓库目录
构建会把大量依赖下载到 /root/.m2,确认磁盘余量充足(本环境构建后 .m2 与源码目录合计占用约 5GB,加上发行包与 Hadoop 安装共约 10GB):
df -h /root /opt
(输出节选,实测要点:/opt 所在文件系统 Avail 应大于 20GB,避免构建中途写满。)
三、版本选型与下载
本章确定各组件版本组合,从官方源/加速源下载全部物料并校验。关键差异:Oozie 5.2.1 只能选源码构建,因此版本选型的核心是「构建 profile 与目标 Hadoop 版本一致」。
3.1 版本选型对照
| 组件 | 版本 | 选型理由 |
|---|---|---|
| Oozie | 5.2.1(终版) | 退役前最后版本,支持 workflow 1.0 / coordinator 0.2 schema 与内嵌 Jetty |
| Hadoop | 3.3.6 | 3.x 稳定线,构建时以 -Dhadoop.version=3.3.6 传入并激活 -Phadoop-3 |
| MySQL | 8.0.46(apt 包版本 8.0.46-0ubuntu0.22.04.4) | 替代官方默认 Derby,生产常用;配 MySQL Connector/J 8.0.33 |
| JDK | OpenJDK 1.8.0_504 | Oozie 5.2.1 构建/运行的目标 JVM,Hadoop 3.3.6 亦完全兼容 |
| Maven | 3.6.3 | 构建期使用,apt 自带版本实测可用 |
选型解读:Oozie 版本固定为 5.2.1 后,Hadoop 版本在 3.x 内可调,但必须与构建参数 -Dhadoop.version 严格一致——运行期 Oozie webapp 的客户端 jar 来自构建结果与目标集群的混合补齐(见第七、八章),版本错配会引发ClassNotFoundException 连锁。MySQL/PostgreSQL 二选一均可(Derby 仅建议测试),本文选 MySQL 8 并用官方推荐的时区参数。
3.2 下载清单(URL / 大小 / 校验)
| 组件 | URL | 字节数 | 校验 |
|---|---|---|---|
| Hadoop 3.3.6 | https://mirrors.aliyun.com/apache/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz | 730,107,476(与官方 Content-Length 一致) | 字节数核对 |
| Oozie 5.2.1 源码 | https://archive.apache.org/dist/oozie/5.2.1/oozie-5.2.1.tar.gz | 2,815,973 | sha512 见 3.3 |
| ext-2.2.zip | https://archive.cloudera.com/gplextras/misc/ext-2.2.zip | 6,800,612 | Last-Modified: Thu, 22 Feb 2018 15:08:40 GMT |
| MySQL Connector/J 8.0.33 | https://maven.aliyun.com/repository/public/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar | 2,481,560 | sha256 e2a3b2fc726a1ac64e998585db86b30fa8bf3f706195b78bb77c5f99bf877bd9 |
清单解读:Hadoop 走国内加速源(官方源 https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/ 亦可);Oozie 源码只有官方归档一处;ext-2.2.zip 的 SourceForge 原始发布地址(downloads.sourceforge.net/project/extjs)已 404,Cloudera gplextras 归档实测存活(HTTP 200);MySQL 驱动从 Maven 加速源取。
3.3 校验 Oozie 源码包 sha512
官方 oozie-5.2.1.tar.gz.sha512 文件内容:
03A8A782 08F441AE 4BDE4CBE D0DF4353 8BB0E1FC E25BB53C
4DF90AB9 83851698 1CFE20B7 CBB28C6F 207243BD AB88A61D
16CBEC84 B2CA9ECA DBC9FD3F A7AB790A
本地计算比对(实测输出同一串值的小写形式,与官方一致):
cd /opt/downloads && sha512sum oozie-5.2.1.tar.gz
(输出节选,实测要点:结果去掉文件名后与上方官方串逐段一致即通过。)
3.4 下载命令
逐条执行(保存到 /opt/downloads):
mkdir -p /opt/downloads && cd /opt/downloads
wget https://archive.apache.org/dist/oozie/5.2.1/oozie-5.2.1.tar.gz https://archive.apache.org/dist/oozie/5.2.1/oozie-5.2.1.tar.gz.sha512 https://archive.cloudera.com/gplextras/misc/ext-2.2.zip
wget https://mirrors.aliyun.com/apache/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz
wget https://maven.aliyun.com/repository/public/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar
下载完成后核对大小(实测要点:Hadoop 包 730,107,476 字节;与上表逐项一致):
ls -l /opt/downloads
⚠️ 坑(实测):曾出现两个 wget 进程同时写
hadoop-3.3.6.tar.gz(第一次后台下载实际已启动但误判未启动又重启了一次),进度「回退」(96MB 变 50MB)、文件互相覆盖。解决:kill全部 wget 进程 → 删除半成品 → 单进程重新下载,最终以 730,107,476 字节与 Content-Length 一致收尾。教训:并行下载同名文件务必用唯一临时名,或严格串行。
四、前置组件一:Hadoop 3.3.6 伪分布式
Oozie 的动作最终跑在 Hadoop 上,本章把 Hadoop 3.3.6 伪分布式装好、启动并用 wordcount 冒烟验证。四个 XML 配置文件内容均为实测生效值。
4.1 解压与环境变量
cd /opt && tar -xzf downloads/hadoop-3.3.6.tar.gz && ln -sfn /opt/hadoop-3.3.6 /opt/hadoop
写入 /etc/profile.d/hadoop.sh(并同步进 /root/.bashrc):
export HADOOP_HOME=/opt/hadoop
export PATH=/opt/hadoop/bin:/opt/hadoop/sbin:$PATH
配置 hadoop-env.sh(追加到 /opt/hadoop/etc/hadoop/hadoop-env.sh 末尾):
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
export HADOOP_HOME=/opt/hadoop
配置说明:Hadoop 3 以 root 启动守护进程时必须显式设置 *_USER 系列变量,否则启动脚本报 "but there is no HDFS_NAMENODE_USER defined";JAVA_HOME 必须写进 hadoop-env.sh,否则 hadoop version 报 ERROR: JAVA_HOME is not set and could not be found.。
验证版本(先完成 hadoop-env.sh 再执行):
hadoop version
Hadoop 3.3.6
Source code repository https://github.com/apache/hadoop.git -r 1be78238728da9266a4f88195058f08fd012bf9c
Compiled by ubuntu on 2023-06-18T08:22Z
4.2 core-site.xml
/opt/hadoop/etc/hadoop/core-site.xml 完整内容(实测生效值):
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://oozie:9000</value>
</property>
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.http.staticuser.user</name>
<value>root</value>
</property>
</configuration>
逐项说明:
fs.defaultFS=hdfs://oozie:9000:NameNode RPC 地址,主机名oozie与 Oozie 侧 job.properties 的nameNode保持一致;hadoop.proxyuser.root.hosts/groups=*:Oozie 必备项——Oozie 以 root 系统用户代理最终用户(root)访问 HDFS/YARN,无此两项 Oozie 提交作业时会报代理用户未授权;hadoop.http.staticuser.user=root:WebUI 匿名访问时展示的用户。
4.3 hdfs-site.xml
/opt/hadoop/etc/hadoop/hdfs-site.xml 完整内容:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/opt/hadoop/data/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/opt/hadoop/data/datanode</value>
</property>
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
</configuration>
逐项说明:单机伪分布式 dfs.replication=1;NameNode/DataNode 数据目录显式落到 /opt/hadoop/data/(默认在 hadoop.tmp.dir 下,显式指定便于备份);dfs.permissions.enabled=false 简化单机测试(生产必须开启并规范用户);dfs.webhdfs.enabled=true 供 WebUI/HttpFS 路径访问。
4.4 mapred-site.xml
/opt/hadoop/etc/hadoop/mapred-site.xml 完整内容:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=/opt/hadoop</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=/opt/hadoop</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=/opt/hadoop</value>
</property>
<property>
<name>yarn.app.mapreduce.am.resource.mb</name>
<value>768</value>
</property>
<property>
<name>mapreduce.map.memory.mb</name>
<value>512</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>512</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx400m</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx400m</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>oozie:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>oozie:19888</value>
</property>
</configuration>
逐项说明:mapreduce.framework.name=yarn 让 MR 作业提交到 YARN(Oozie launcher 作业也走这条路径);三个 HADOOP_MAPRED_HOME env 是 AM/Map/Reduce 进程内找到 Hadoop 类库的关键;内存参数(AM 768MB、Map/Reduce 各 512MB、进程内 JVM 堆 400m)为小内存单机的实测稳定值;JobHistory 地址供作业历史查询(Oozie 的 launcher 日志依赖它)。
4.5 yarn-site.xml
/opt/hadoop/etc/hadoop/yarn-site.xml 完整内容:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>oozie</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>4096</value>
</property>
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>4</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>256</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>4096</value>
</property>
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.nodemanager.env-whitelist</name>
<value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
</property>
</configuration>
逐项说明:shuffle 服务是 MR 作业必需;yarn.resourcemanager.hostname=oozie 与 Oozie job.properties 的 resourceManager=oozie:8032 对应;NodeManager 资源上限 4096MB/4 vcore、单任务分配上限 256~4096MB,为单机实测稳定值;关闭虚拟内存检查(vmem-check-enabled=false)避免小内存机器上任务进程被杀;开启日志聚合让 Oozie 页面能取到 launcher 日志。
4.6 格式化 NameNode
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
/opt/hadoop/bin/hdfs namenode -format -force
关键回显(输出节选,实测首尾):
2026-10-14 17:23:59,291 INFO namenode.NameNode: STARTUP_MSG:
STARTUP_MSG: host = oozie/172.17.0.15
STARTUP_MSG: java = 1.8.0_504
2026-10-14 17:24:00,309 INFO namenode.NameNode: Formatting using clusterid: CID-89bfabe0-01a8-4584-911c-025e67b2c8d7
2026-10-14 17:24:01,741 INFO namenode.NameNode: SHUTDOWN_MSG:
要点:出现 Formatting using clusterid: CID-… 且以 SHUTDOWN_MSG 正常退出即为成功(format 是一次性动作,完成后进程退出属正常)。
4.7 启动 HDFS 与 YARN
逐个启动(每条命令单独执行,Hadoop 3 的脚本经 SSH 拉起各守护进程):
/opt/hadoop/sbin/start-dfs.sh
/opt/hadoop/sbin/start-yarn.sh
/opt/hadoop/sbin/mr-jobhistory-daemon.sh start historyserver
实测回显(输出节选):
Starting namenodes on [oozie]
oozie: Warning: Permanently added 'oozie' (ED25519) to the list of known hosts.
Starting datanodes
Starting secondary namenodes [oozie]
Starting resourcemanager
Starting nodemanagers
WARNING: Use of this script to start the MR JobHistory daemon is deprecated.
WARNING: Attempting to execute replacement "mapred --daemon start" instead.
验证进程(实测回显):
jps
9248 Jps
10224 JobHistoryServer
10049 NodeManager
9684 SecondaryNameNode
9494 DataNode
9384 NameNode
9945 ResourceManager
六个守护进程(NameNode/DataNode/SecondaryNameNode/ResourceManager/NodeManager/JobHistoryServer)全部在列即为启动成功。
4.8 WordCount 冒烟测试
准备输入并执行(逐条执行):
/opt/hadoop/bin/hdfs dfs -mkdir -p /user/root/wordcount/input
/opt/hadoop/bin/hdfs dfs -put /opt/hadoop/NOTICE.txt /user/root/wordcount/input/
/opt/hadoop/bin/hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar \
wordcount /user/root/wordcount/input /user/root/wordcount/output
关键回显(输出节选,实测首尾):
2026-10-14 17:25:05,764 INFO impl.YarnClientImpl: Submitted application application_1791998675123_0001
File System Counters
验证输出(实测回显):
/opt/hadoop/bin/hdfs dfs -cat /user/root/wordcount/output/part-r-00000
(BIS), 1
(ECCN) 1
(TSU) 1
(http://www.apache.org/). 1
(see 1
验证 YARN 应用最终状态:
/opt/hadoop/bin/yarn application -status application_1791998675123_0001
Application-Name : word count
Final-State : SUCCEEDED
wordcount 跑出统计结果且 Final-State : SUCCEEDED,说明 HDFS + YARN + MR 全链路可用,Oozie 的运行底座就绪。
五、前置组件二:MySQL 8 安装与 oozie 库初始化
Oozie 默认用内嵌 Derby,仅适合测试且不支持多服务共享;本文按生产常用方式改用 MySQL 8 元数据库。
💡 技术拓展:Oozie 支持的元数据库不止 MySQL 一种,官方支持的同类选择对比——
数据库 特点 适用场景 Derby Java 内嵌、零配置,随 Oozie 进程 单机快速验证 HSQLDB 轻量内嵌,同为 Java 库 简单测试 MySQL 独立服务、运维生态成熟 本文采用,生产常见选择 PostgreSQL 独立服务、事务能力强 生产可选 Oracle / SQL Server 商业数据库 已有商业 DB 存量的企业 本文选 MySQL 8 的理由:apt 直接可装、运维经验普及、Oozie 官方文档明确给出 MySQL JDBC 时区参数方案。
5.1 安装 MySQL 8
2.2 节的 apt 命令已包含 mysql-server mysql-client,安装版本为 8.0.46-0ubuntu0.22.04.4,安装过程自动初始化 /var/lib/mysql(#ib_16384_0.dblwr、auto.cnf 等初始化文件在位)。
5.2 启动 MySQL 并验证
本环境按手动方式前台启动(命令与回显均实测;若服务器启用 systemd,也可用 systemctl start mysql 一行托管,本文以手动方式为准):
mkdir -p /var/run/mysqld && chown mysql:mysql /var/run/mysqld
nohup mysqld --user=mysql > /var/log/mysql-manual.log 2>&1 &
命令说明:MySQL 8 启动需要 /var/run/mysqld 套接字目录且属主为 mysql;nohup 后台拉起并落日志。
状态验证(实测回显):
mysqladmin --protocol=socket -uroot status
Uptime: 9 Threads: 2 Questions: 2 Slow queries: 0 Opens: 119 Flush tables: 3 Open tables: 38 Queries per second avg: 0.222
⚠️ 坑(实测):
--protocol=socket与-h127.0.0.1不能同时使用,否则报ERROR 2047 (HY000): Wrong or unknown protocol——socket 协议走本地套接字文件,-h走 TCP,两者互斥。验证 TCP 直接用-h127.0.0.1 -P3306即可(见 5.4)。
5.3 建库建用户
以 root 进入本机 socket 会话执行(密码策略:演示环境用户 oozie、口令 oozie123;显式 mysql_native_password 规避老驱动兼容问题;% 与 localhost 两条用户都要建):
mysql --protocol=socket -uroot
CREATE DATABASE oozie CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'oozie'@'%' IDENTIFIED WITH mysql_native_password BY 'oozie123';
CREATE USER 'oozie'@'localhost' IDENTIFIED WITH mysql_native_password BY 'oozie123';
GRANT ALL PRIVILEGES ON oozie.* TO 'oozie'@'%';
GRANT ALL PRIVILEGES ON oozie.* TO 'oozie'@'localhost';
FLUSH PRIVILEGES;
执行后核验(实测回显):
SHOW DATABASES;
Database
information_schema
mysql
oozie
performance_schema
sys
SELECT user, host, plugin FROM mysql.user WHERE user = 'oozie';
user host plugin
oozie % mysql_native_password
oozie localhost mysql_native_password
5.4 TCP 连接验证
用 oozie 账号走 TCP 实测连通(实测回显):
mysql -uoozie -poozie123 -h127.0.0.1 -P3306 -e "SELECT @@version, @@default_authentication_plugin, @@time_zone, @@character_set_server;"
@@version @@default_authentication_plugin @@time_zone @@character_set_server
8.0.46-0ubuntu0.22.04.4 caching_sha2_password SYSTEM utf8mb4
5.5 JDBC URL 约定
Oozie 侧将使用官方 AG_Install 建议的时区参数(官方原文:"you can have Oozie use GMT with MySQL without setting MySQL's timezone to GMT by adding 'useLegacyDatetimeCode=false&serverTimezone=GMT' arguments to the JDBC URL"):
jdbc:mysql://127.0.0.1:3306/oozie?useLegacyDatetimeCode=false&serverTimezone=GMT
说明:该参数组合让 Oozie 内部统一用 GMT 存取时间,规避 MySQL 服务器时区与夏令时对 Coordinator 触发时间的影响,是官方文档对 Coordinator 稳定性的明确建议。
六、Oozie 5.2.1 源码构建
本章从官方源码构建出可部署的发行包。方案说明:Oozie 官方推荐用源码内 bin/mkdistro.sh 包装脚本构建,其内部等价于直接调用 Maven(脚本执行 mvn clean package assembly:single,含 -DgenerateDocs,且无 .git 目录时自动置 VC_REV="unavailable")。两种方式对比:
| 方案 | 命令形态 | 特点 | 本文采用 |
|---|---|---|---|
| A 官方包装 | bin/mkdistro.sh -DskipTests -Phadoop-3 -Dhadoop.version=3.3.6 | 脚本封装,参数透传,日志中转一层 | 可用 |
| B 直调 Maven | mvn clean package assembly:single … | 与 A 完全等价,参数与失败重试(-rf)控制更直接 | 采用(实测 8 次尝试最终成功) |
⚠️ 注意:构建必须激活
-Phadoop-3并以-Dhadoop.version指定 3.x 版本。源码根pom.xml默认<hadoop.version>2.6.0</hadoop.version>(面向 Hadoop 2);hadoop-3profile 定义在webapp/pom.xml(追加hadoop-common/hadoop-hdfs-client依赖),Hadoop 版本由-Dhadoop.version传递。
6.1 解压源码
cd /opt/downloads
mkdir -p /opt/oozie-src && tar -xzf oozie-5.2.1.tar.gz -C /opt/oozie-src --strip-components=1
sha512 校验通过后再解压(见 3.3,实测要点:sha512sum 结果与官方 .sha512 文件一致)。
6.2 Maven 加速源配置
写入 /root/.m2/settings.xml(实测配置):
<settings>
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
</settings>
配置说明:mirrorOf=* 全量代理所有仓库(含依赖 pom 里声明的已死仓库地址),绝大多数依赖走国内加速源;但它无法补齐 Central 上根本不存在的构件——这正是 6.4 的 txw2 问题根源。
6.3 第一轮构建:txw2 死版本依赖失败(⚠️ 坑一)
先按直觉直接构建:
cd /opt/oozie-src
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
bin/mkdistro.sh -DskipTests -Phadoop-3 -Dhadoop.version=3.3.6
实测失败于 oozie-fluent-job-api 模块,真实报错:
[ERROR] Failed to execute goal on project oozie-fluent-job-api: Could not resolve dependencies for project
org.apache.oozie:oozie-fluent-job-api:jar:5.2.1: Could not transfer artifact
org.glassfish.jaxb:txw2:pom:2.4.0-b180608.0325 from/to releases.java.net (http://maven.java.net/content/repositories/releases/):
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
定位:fluent-job/fluent-job-api/pom.xml 的 xjc 插件 com.github.davidmoten:jax-maven-plugin:0.1.6 传递依赖 com.sun.xml.ws:policy:2.7.5 → txw2:2.4.0-b180608.0325,而该版本从未发布到 Maven Central(只存在于已停服的 java.net 仓库)。核对 Central:https://repo1.maven.org/maven2/org/glassfish/jaxb/txw2/ 只有 2.3.x / 2.4.0-b180725.0644 / 2.4.0-b180830.0438。全量加速源也补不齐不存在的构件。
解决:本地植入死链构件——用 Central 上真实存在的 2.4.0-b180830.0438 jar,以死链版本号 2.4.0-b180608.0325 装入本地仓库。先从 Central 下载真实存在的构件(逐条执行):
cd /opt/downloads
wget https://repo1.maven.org/maven2/org/glassfish/jaxb/txw2/2.4.0-b180830.0438/txw2-2.4.0-b180830.0438.jar
wget https://repo1.maven.org/maven2/org/glassfish/jaxb/jaxb-bom/2.4.0-b180830.0438/jaxb-bom-2.4.0-b180830.0438.pom
wget https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-bom-ext/2.4.0-b180830.0438/jaxb-bom-ext-2.4.0-b180830.0438.pom
再以死链版本号植入本地仓库(三条命令逐条执行):
mvn -q install:install-file -Dfile=/opt/downloads/txw2-2.4.0-b180830.0438.jar \
-DgroupId=org.glassfish.jaxb -DartifactId=txw2 -Dversion=2.4.0-b180608.0325 -Dpackaging=jar
mvn -q install:install-file -Dfile=/opt/downloads/jaxb-bom-ext-2.4.0-b180830.0438.pom \
-DgroupId=com.sun.xml.bind -DartifactId=jaxb-bom-ext -Dversion=2.4.0-b180830.0438 -Dpackaging=pom
mvn -q install:install-file -Dfile=/opt/downloads/jaxb-bom-2.4.0-b180830.0438.pom \
-DgroupId=org.glassfish.jaxb -DartifactId=jaxb-bom -Dversion=2.4.0-b180830.0438 -Dpackaging=pom
说明:install:install-file 生成最小 pom 入库、不拖入 BOM 依赖链;三件中 txw2 是必须的,jaxb-bom/jaxb-bom-ext 在 Central 存在但加速源缺失,一并植入最稳妥。
6.4 不要给插件钉版:jax-maven-plugin NPE(⚠️ 坑二)
在植入之上若进一步「顺手」在插件 <dependencies> 里钉住 txw2:2.4.0-b180830.0438,构建会在插件执行期报 NPE(实测真实报错):
[ERROR] Failed to execute goal com.github.davidmoten:jax-maven-plugin:0.1.6:xjc (default) on project oozie-fluent-job-api: NullPointerException
java.lang.NullPointerException
at java.util.stream.ReferencePipeline$3$1.accept (ReferencePipeline.java:193)
at com.github.davidmoten.jaxws.BaseMojo.createCommand (BaseMojo.java:178)
定位(最小探针工程二分实测):仅声明 jaxb2-basics:1.11.1 时插件正常;一旦给插件钉上 txw2 真实版本就必现 NPE。原因是插件对自己声明的 <dependencies> 做 legacy 传递解析,钉版 pom(parent=jaxb-bom → jaxb-bom-ext)引入了 file 为 null 的 BOM 节点。
解决:去掉钉版,仅保留 6.3 的本地植入,-rf :oozie-fluent-job-api 从失败处恢复构建:
mvn clean package assembly:single -DskipTests -Phadoop-3 -Dhadoop.version=3.3.6 -rf :oozie-fluent-job-api
⚠️ 附带发现:官方
fluent-job-api/pom.xml的 xjc 参数里有拼写错误<arhument>email-action-0.2.xsd</arhument>(应为 argument),导致 email XSD 从未参与代码生成——官方正式发行构建同样如此,不影响使用,无需修改。
6.5 tools 测试类与 Hadoop 3.3.6 API 不兼容:修补 TestECPolicyDisabler(⚠️ 坑三)
依赖解决后构建继续,失败于 oozie-tools 的测试编译(实测真实报错):
[ERROR] COMPILATION ERROR :
[ERROR] /opt/oozie-src/tools/src/test/java/org/apache/oozie/tools/TestECPolicyDisabler.java:[50,31]
types found in 3.3.6 are not compatible:
error: TestECPolicyDisabler.MockDistributedFileSystem is not abstract and does not override
abstract method getErasureCodingPolicy(Path) in TestECPolicyDisabler.MockDistributedFileSystem
定位:Hadoop 3.3.6 中 DistributedFileSystem.getErasureCodingPolicy() 返回类型由 SystemErasureCodingPolicies.ReplicationPolicy 改为 org.apache.hadoop.hdfs.protocol.ErasureCodingPolicy,且 SystemErasureCodingPolicies.setSystemPolicy() 与 ReplicationPolicy 枚举已被移除。-DskipTests 只跳过测试执行、不跳测试编译。
错误回避尝试(不可行,实测):改用 -Dmaven.test.skip=true 让测试完全不编译,结果构建到最后一步 oozie-distro 组装时失败:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:3.1.0:single (distro) on project oozie-distro:
Failed to create assembly: Error adding file to archive: ... core/target/oozie-core-5.2.1-tests.jar isn't a valid file.
因为 distro 组装会打包各模块 *-tests.jar,测试不编译就没有测试 jar。结论:构建组合必须是 -DskipTests + 修补 tools 测试类,二者缺一不可。
解决:最小修补 tools/src/test/java/org/apache/oozie/tools/TestECPolicyDisabler.java,共四处(保持其余不动):
getErasureCodingPolicy相关 import 改为org.apache.hadoop.hdfs.protocol.ErasureCodingPolicy(原SystemErasureCodingPolicies.ReplicationPolicy);- 抽象方法签名改为
public abstract ErasureCodingPolicy getErasureCodingPolicy(Path path); SystemErasureCodingPolicies.setSystemPolicy(ReplicationPolicy.DEFAULT);一行注释掉;- mock 中
thenReturn(ReplicationPolicy.DEFAULT)/thenReturn(ReplicationPolicy.OTHER)及ReplicationPolicy类型 mock 相应改为thenReturn(null)/ErasureCodingPolicy类型 mock。
6.6 最终构建命令与回显
修补后全量构建(最终成功命令,逐字实测):
cd /opt/oozie-src
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export MAVEN_OPTS="-Xmx3g -XX:MaxMetaspaceSize=1g"
mvn clean package assembly:single -DskipTests -Phadoop-3 -Dhadoop.version=3.3.6 \
-Dbuild.time=2026.10.14-00:00:00GMT -Dvc.revision=unavailable -Dvc.url=unavailable -DgenerateDocs
参数说明:-DskipTests 跳测试执行但保留测试 jar 编译(见 6.5);-Dbuild.time 固定构建时间戳(源码无 .git 时版本信息取 unavailable,显式传入避免告警);MAVEN_OPTS 给构建 JVM 加大堆(多模块编译内存峰值高)。
实测回显(输出节选,实测首尾;行内点线为 Maven 对齐符原样):
[INFO] Reactor Summary for Apache Oozie Main 5.2.1:
[INFO]
[INFO] Apache Oozie Fluent Job API ......................... SUCCESS [ 25.022 s]
(……中间模块省略……)
[INFO] Apache Oozie Distro ................................. SUCCESS [ 27.977 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
构建产物(实测 561,212,677 字节):
/opt/oozie-src/distro/target/oozie-5.2.1-distro.tar.gz 561,212,677 字节
💡 说明:构建耗时约数分钟(多核 12C 环境);
-DgenerateDocs会生成文档,若只求产物可省略。整个构建期需要访问已死仓库的构件仅 2 个(org.glassfish.jaxb:txw2:2.4.0-b180608.0325与com.sun.xml.bind:jaxb-bom-ext:2.4.0-b180830.0438),6.3 的植入已全部覆盖。
七、Oozie 部署与初始化
本章解压发行包、配置元数据库连接、初始化 DB schema、上传 sharelib,并完成 5.x 特有的「合 libext」步骤。
7.1 解压发行包并认识目录结构
cd /opt && tar -xzf /opt/oozie-src/distro/target/oozie-5.2.1-distro.tar.gz
ls oozie-5.2.1/
实测回显:
bin conf docs.zip embedded-oozie-server libtools oozie-client-5.2.1.tar.gz
oozie-core oozie-examples.tar.gz oozie-sharelib-5.2.1.tar.gz release-log.txt
结构解读:bin/ 是部署与运维脚本;conf/ 是服务端配置;embedded-oozie-server/ 是内嵌 Jetty 服务器(dependency/ lib/ oozie-server-5.2.1.jar webapp/,webapp 已预展开、WEB-INF/lib/ 含 264 个 jar 与 console/);oozie-sharelib-5.2.1.tar.gz 与 oozie-examples.tar.gz 是构建产物自带的共享库与示例(不需要另行下载);oozie-client-5.2.1.tar.gz 是独立客户端包。
确认 oozie-setup.sh 的真实子命令(实测回显,注意没有 prepare-war):
/opt/oozie-5.2.1/bin/oozie-setup.sh --help
usage: oozie-setup.sh
sharelib create -fs <name node> [-locallib <path>]
sharelib upgrade -fs <name node>
db create|upgrade|postupgrade -run [-sqlfile <file>]
export <destination file> [-threads <number>]
import <source file> [-threads <number>]
7.2 准备 libext:ExtJS 2.2 与 MySQL 驱动
mkdir -p /opt/oozie-5.2.1/libext
cp /opt/downloads/ext-2.2.zip /opt/oozie-5.2.1/libext/
cp /opt/downloads/mysql-connector-j-8.0.33.jar /opt/oozie-5.2.1/libext/
依据(官方 AG_Install 5.2.1 原文):"If a directory libext/ is present in Oozie installation directory, the oozie-setup.sh script will include all JARs in Jetty's webapp/WEB_INF/lib/ directory. … If the ExtJS ZIP file is present in the libext/ directory, it will be added to the Jetty's webapp/ directory as well. The ExtJS library file name be ext-2.2.zip."——即 libext 里的普通 jar 合入 webapp,ext-2.2.zip(文件名必须一字不差)解入 webapp 作为 WebUI 前端。
7.3 补齐顶层 lib/ 目录(5.x 发行形态坑)
先做本步再建库,原因见 7.4 的失败现场。5.2.1 发行包顶层没有 oozie.war,而 bin/ooziedb.sh 仍按 4.x 逻辑从 war 包取 classpath,因此要把 webapp 依赖灌进顶层 lib/:
mkdir -p /opt/oozie-5.2.1/lib
cp /opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/*.jar /opt/oozie-5.2.1/lib/
7.4 配置 conf/oozie-site.xml
/opt/oozie-5.2.1/conf/oozie-site.xml 完整内容(实测生效值):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- MySQL 元数据库(替代官方默认 Derby) -->
<property>
<name>oozie.service.JPAService.jdbc.driver</name>
<value>com.mysql.cj.jdbc.Driver</value>
<description>JDBC driver class. MySQL Connector/J 8.x uses com.mysql.cj.jdbc.Driver</description>
</property>
<property>
<name>oozie.service.JPAService.jdbc.url</name>
<value>jdbc:mysql://127.0.0.1:3306/oozie?useLegacyDatetimeCode=false&serverTimezone=GMT</value>
<description>官方 AG_Install 建议:GMT 时区避免夏令时导致的 Coordinator 问题</description>
</property>
<property>
<name>oozie.service.JPAService.jdbc.username</name>
<value>oozie</value>
</property>
<property>
<name>oozie.service.JPAService.jdbc.password</name>
<value>oozie123</value>
</property>
<!-- Oozie 服务器访问 Hadoop 集群的配置目录 -->
<property>
<name>oozie.service.HadoopAccessorService.hadoop.configurations</name>
<value>*=/opt/hadoop/etc/hadoop</value>
</property>
<property>
<name>oozie.base.url</name>
<value>http://oozie:11000/oozie</value>
</property>
<property>
<name>oozie.system.id</name>
<value>oozie-root</value>
</property>
<property>
<name>oozie.service.AuthorizationService.authorization.enabled</name>
<value>false</value>
</property>
</configuration>
逐项说明:
oozie.service.JPAService.jdbc.driver=com.mysql.cj.jdbc.Driver:MySQL Connector/J 8.x 的驱动类名(5.x 的com.mysql.jdbc.Driver已弃用);jdbc.url:连接第五章建的oozie库,带官方建议的 GMT 时区参数(XML 内&转义为&);jdbc.username/password=oozie/oozie123:与 5.3 建的账号一致;HadoopAccessorService.hadoop.configurations=*=/opt/hadoop/etc/hadoop:Oozie 按用户通配加载 Hadoop 配置目录,这是服务端能找到 HDFS/YARN 地址的前提;oozie.base.url:服务对外地址(11000 端口);oozie.system.id=oozie-root:作业 ID 的标识段(实测作业 ID…-oozie-root-W/C即来源于此);authorization.enabled=false:演示环境关闭鉴权(生产开启并配 Kerberos/ACL,退役组件尤其要配合网络层加固)。
7.5 初始化 DB schema(含失败现场)
直接执行建库(预期会失败,失败现场保留如下):
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
/opt/oozie-5.2.1/bin/ooziedb.sh create -sqlfile /opt/oozie-5.2.1/oozie-create.sql -run
实测失败报错(若跳过了 7.3):
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException
Caused by: java.lang.ClassNotFoundException: org.apache.commons.cli.ParseException
定位:bin/ooziedb.sh 按 4.x 逻辑从 ${BASEDIR}/oozie.war 解包 jar 组 classpath,而 5.2.1 发行包顶层没有 oozie.war(webapp 预展开在 embedded-oozie-server/webapp/),classpath 为空。解决:即 7.3 的 cp …webapp/WEB-INF/lib/*.jar lib/。补齐后重跑:
/opt/oozie-5.2.1/bin/ooziedb.sh create -sqlfile /opt/oozie-5.2.1/oozie-create.sql -run
实测成功回显(输出节选):
Create SQL schema DONE
Create OOZIE_SYS record DONE
Verify OOZIE_SYS record DONE
Oozie DB has been created for Oozie version '5.2.1'
日志中还能确认驱动与连接生效(输出节选):
244 oozie-mysql INFO [main] openjpa.jdbc.JDBC - Connected to MySQL version 8.8 using JDBC driver MySQL Connector/J version mysql-connector-j-8.0.33 (Revision: 7d6b0800528b6b25c68b52dc10d6c1c8429c100c).
MySQL 侧核验(实测回显,12 张表全部生成):
mysql -uoozie -poozie123 -h127.0.0.1 -P3306 -e "SHOW TABLES FROM oozie;"
BUNDLE_ACTIONS
BUNDLE_JOBS
COORD_ACTIONS
COORD_JOBS
OOZIE_SYS
OPENJPA_SEQUENCE_TABLE
SLA_EVENTS
SLA_REGISTRATION
SLA_SUMMARY
VALIDATE_CONN
WF_ACTIONS
WF_JOBS
7.6 上传 sharelib 到 HDFS
/opt/oozie-5.2.1/bin/oozie-setup.sh sharelib create -fs hdfs://oozie:9000
关键回显(输出节选,实测):
Found Hadoop that supports Erasure Coding. Trying to disable Erasure Coding for path: /user/root/share/lib
Done
the destination path for sharelib is: /user/root/share/lib/lib_20261014181925
HDFS 侧验证(实测回显):
/opt/hadoop/bin/hdfs dfs -ls /user/root/share/lib/
drwxr-xr-x - root supergroup 0 2026-10-14 18:19 /user/root/share/lib/lib_20261014181925
说明:sharelib 目标目录带构建时间戳(lib_20261014181925),升级 sharelib 时新旧版本目录并存;Oozie 自动对 sharelib 路径关闭纠删码以保证小文件读取兼容性。
7.7 合并 libext 到 webapp(5.x 版的「prepare-war」)
⚠️ 坑(实测):oozie-setup.sh 带子命令(sharelib/db/export/import)执行完直接退出,不会触发 libext 合并。必须不带任何命令再运行一次:
/opt/oozie-5.2.1/bin/oozie-setup.sh
实测回显:
INFO: Adding extension: /opt/oozie-5.2.1/libext/mysql-connector-j-8.0.33.jar
INFO: Oozie is ready to be started
验证合并效果(实测回显,两项都在即为成功):
ls /opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/mysql-connector-j-8.0.33.jar
/opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/mysql-connector-j-8.0.33.jar
ls -d /opt/oozie-5.2.1/embedded-oozie-server/webapp/ext-2.2
/opt/oozie-5.2.1/embedded-oozie-server/webapp/ext-2.2
八、启动与验证
本章启动 Oozie 服务、处理启动期依赖坑、并做三层验证:CLI 状态、REST API、WebUI。
8.1 启动服务
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
/opt/oozie-5.2.1/bin/oozied.sh start
实测回显:
Setting OOZIE_HOME: /opt/oozie-5.2.1
Sourcing: /opt/oozie-5.2.1/conf/oozie-env.sh
setting CATALINA_OPTS='$CATALINA_OPTS -Xmx2048m -XX:+HeapDumpOnOutOfMemoryError'
DB schema exists
Oozie server started - PID: 18904.
要点:DB schema exists 说明服务端已检测到 7.5 建好的 schema;启动脚本回显的 CATALINA_OPTS 就是 Oozie 服务端 JVM 参数的实际生效值(内嵌 Jetty 沿用 CATALINA_OPTS 命名),来自 conf/oozie-env.sh 机制——如需调整堆大小,编辑 /opt/oozie-5.2.1/conf/oozie-env.sh 中的 CATALINA_OPTS(实测默认 -Xmx2048m -XX:+HeapDumpOnOutOfMemoryError,小内存机器可降到 -Xmx512m 一档),修改后重启并用 ps -ef | grep [j]oozie(JVM 堆参数)或启动回显核对生效值。
8.2 启动期依赖补齐(实测排障链)
首次启动后 oozied.sh start 可能因 webapp 对 Hadoop 3 客户端依赖不全而失败,以下四个问题是同一条链上的连环坑(根因:-Phadoop-3 profile 在 webapp 模块只声明了 hadoop-common/hdfs-client),按发生顺序逐个处理。每次修改后都按 8.3 的流程重启。
问题 1:MySQL 驱动找不到
Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.mysql.cj.jdbc.Driver'
定位:Jetty 进程的 system classpath 是 -cp ${JETTY_DIR}/*:dependency/*:${BASEDIR}/lib/*:libtools/*,而 7.3 复制 lib/ 发生在 7.7 合并之前时 lib/ 里没有驱动。解决(lib/ 与 webapp/WEB-INF/lib 两处都要有):
cp /opt/downloads/mysql-connector-j-8.0.33.jar /opt/oozie-5.2.1/lib/
cp /opt/downloads/mysql-connector-j-8.0.33.jar /opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/
问题 2:JobConf 类缺失(MySQL 连接成功后的下一坑)
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/mapred/JobConf
定位:Hadoop 3.3.6 的 JobConf 不在 hadoop-common(unzip -l hadoop-common-3.3.6.jar 中无此类),而在 hadoop-mapreduce-client-core;-Phadoop-3 构建的 webapp 依赖集缺该 jar。解决:
cp /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar /opt/oozie-5.2.1/lib/
cp /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar /opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/
问题 3:YarnClient 类缺失(启动正常、提交后卡 PREP)
Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.yarn.client.api.YarnClient
定位:服务端提交 launcher 作业需要 yarn-client;webapp 缺 hadoop-yarn-client 及配套 mapreduce 客户端 jar。解决:
cp /opt/hadoop/share/hadoop/yarn/hadoop-yarn-client-3.3.6.jar /opt/oozie-5.2.1/lib/
cp /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-common-3.3.6.jar /opt/oozie-5.2.1/lib/
cp /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.3.6.jar /opt/oozie-5.2.1/lib/
cp /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-app-3.3.6.jar /opt/oozie-5.2.1/lib/
cp /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-hs-3.3.6.jar /opt/oozie-5.2.1/lib/
(以上 5 个 jar 同步复制一份到 /opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/,逐个 cp 执行,两处保持一致。)
问题 4:websocket 类缺失(YARN client 初始化需要)
java.lang.NoClassDefFoundError: org/eclipse/jetty/websocket/api/WebSocketException
定位:YARN client 初始化路径引用 websocket 类,Hadoop 发行包自带 share/hadoop/yarn/lib/websocket-*.jar(9.4.51,共 5 个)。解决:
cp /opt/hadoop/share/hadoop/yarn/lib/websocket-*.jar /opt/oozie-5.2.1/lib/
cp /opt/hadoop/share/hadoop/yarn/lib/websocket-*.jar /opt/oozie-5.2.1/embedded-oozie-server/webapp/WEB-INF/lib/
四个问题全部补齐并重启后,服务端可正常接受提交(作业运行验证见第九章之后的实战篇,本篇 8.4 即可确认服务健康)。
8.3 重启与残留 PID 清理
每次补 jar 后按此流程重启(逐条执行):
/opt/oozie-5.2.1/bin/oozied.sh stop
rm -f /opt/oozie-5.2.1/embedded-oozie-server/oozie.pid
/opt/oozie-5.2.1/bin/oozied.sh start
⚠️ 坑(实测):服务端进程异常退出时,PID 文件
/opt/oozie-5.2.1/embedded-oozie-server/oozie.pid可能残留僵尸 PID,导致下次start提示已在运行;删除该 PID 文件后再 start 即可(实测每次 stop/start 都建议顺手清理)。
8.4 服务健康验证(CLI + REST)
export OOZIE_URL=http://localhost:11000/oozie
/opt/oozie-5.2.1/bin/oozie admin -status
实测回显:
System mode: NORMAL
REST API 验证(实测回显):
curl -s http://localhost:11000/oozie/v2/admin/status
{"systemMode":"NORMAL"}
8.5 WebUI 验证(三项实测)
curl -s -o /dev/null -w "%{http_code}" http://localhost:11000/oozie/index.jsp
200
curl -s http://localhost:11000/oozie/index.jsp | grep -o "<title>[^<]*</title>"
<title>Oozie Web Console</title>
curl -s -o /dev/null -w "HTTP %{http_code}, %{size_download} bytes" http://localhost:11000/oozie/ext-2.2/ext-all.js
HTTP 200, 538956 bytes
三项全过即 ExtJS 与控制台就位;若第三项 404,说明 7.7 的 ext-2.2 合并未生效(WebUI 白屏,仅剩工具栏)。至此安装完成:System mode: NORMAL + 11000 端口服务可访问。
九、升级与卸载
升级:Oozie 无增量升级包,采用「新目录并行 + schema/sharelib 迁移」方式。同大版本内升级(如 5.2.0 → 5.2.1):停止旧服务 → 解压新版本发行包到新目录 → 复制 conf/oozie-site.xml 与 conf/oozie-env.sh → 用新版本 ooziedb.sh create/upgrade/postupgrade -run 处理 schema(oozie-setup.sh --help 实测支持 db create|upgrade|postupgrade)→ oozie-setup.sh sharelib upgrade -fs <nameNode> 上传新 sharelib → 启动新版本并验证。跨大版本(4.x → 5.x)需重建发行形态(war → 内嵌 Jetty)并全量回归,退役组件建议以「迁移替代品」替代升级。
卸载(按依赖反向清理,逐条执行):
/opt/oozie-5.2.1/bin/oozied.sh stop
/opt/hadoop/sbin/mr-jobhistory-daemon.sh stop historyserver
/opt/hadoop/sbin/stop-yarn.sh
/opt/hadoop/sbin/stop-dfs.sh
清理数据与程序(逐条执行,删除前确认无保留需求):
mysql -uoozie -poozie123 -h127.0.0.1 -P3306 -e "DROP DATABASE oozie;"
mysql -uoozie -poozie123 -h127.0.0.1 -P3306 -e "DROP USER 'oozie'@'%'; DROP USER 'oozie'@'localhost';"
/opt/hadoop/bin/hdfs dfs -rm -r /user/root/share
rm -rf /opt/oozie-5.2.1 /opt/oozie-src /opt/hadoop-3.3.6 /opt/hadoop
卸载验证:
curl -s http://localhost:11000/oozie/v2/admin/status
预期服务已停止、连接被拒绝;jps 中不再有 NameNode/DataNode/ResourceManager 等 Java 进程。
十、常见问题(FAQ)
Q1:apt-get update 报证书校验失败(Certificate verification failed / Could not handshake)?
A:最小安装缺 CA 证书库。按 2.1 两步法:源临时改 http → 装 ca-certificates → 换回 https。连锁的 E: Unable to locate package lsof 也随之消失。
Q2:官方站点为什么没有 oozie-sharelib-5.2.1.tar.gz 和 ext-2.2.zip 下载?
A:5.2.1 只发布源码包(2.7M)。sharelib tarball 是构建产物随发行包自带;ext-2.2.zip 从未由 Apache 发布,从 Cloudera gplextras 归档取(见 3.2 清单)。
Q3:构建报 txw2:2.4.0-b180608.0325 无法解析(PKIX path building failed)?
A:该版本从未进 Maven Central,只存在于已停服的 java.net 仓库。按 6.3 用 install:install-file 把 Central 上真实存在的 2.4.0-b180830.0438 jar 以死链版本号植入本地仓库。
Q4:植入后又在 jax-maven-plugin 处报 NullPointerException?
A:那是给插件 <dependencies> 钉了 txw2 版本触发的(插件 legacy 解析 BOM 链时 file 为 null)。去掉钉版、只保留 install-file 植入即可,见 6.4。
Q5:TestECPolicyDisabler 编译错误 / 用 -Dmaven.test.skip=true 后 distro 组装失败?
A:前者是 Hadoop 3.3.6 API 变更导致测试类不兼容(-DskipTests 不跳测试编译),需按 6.5 四处最小修补;后者是 distro 组装需要各模块 tests.jar(测试不编译就没有),不能用 maven.test.skip=true,正确组合是 -DskipTests + 修补。
Q6:ooziedb.sh create 报 NoClassDefFoundError: org/apache/commons/cli/ParseException?
A:5.x 发行包顶层没有 oozie.war,而 ooziedb.sh 仍按 war 取 classpath。执行 7.3:mkdir -p lib && cp embedded-oozie-server/webapp/WEB-INF/lib/*.jar lib/ 后重跑。
Q7:跑完 sharelib create 后 webapp 里没有 MySQL 驱动、也没有 ext-2.2?
A:oozie-setup.sh 带子命令时执行完直接退出、不合并 libext。必须单独无参运行一次 oozie-setup.sh,见 7.7。
Q8:启动后报 Cannot load JDBC driver class 'com.mysql.cj.jdbc.Driver' / NoClassDefFoundError: JobConf / 提交后卡 PREP 报 ClassNotFoundException: YarnClient / 再报 WebSocketException?
A:这是同一根因(-Phadoop-3 webapp 依赖不全)的连环四坑,按 8.2 顺序补:MySQL 驱动 → hadoop-mapreduce-client-core → hadoop-yarn-client + mapreduce 客户端 jar → websocket jar,两处目录(lib/ 与 webapp/WEB-INF/lib/)都要有,补完重启。
Q9:oozied.sh start 提示已在运行但服务实际没起?
A:残留 PID 文件(embedded-oozie-server/oozie.pid)。按 8.3:stop → rm -f PID 文件 → start。
Q10:mysql --protocol=socket -h127.0.0.1 报 ERROR 2047 (HY000): Wrong or unknown protocol?
A:socket 协议与 TCP 主机参数互斥。socket 验证只带 --protocol=socket -uroot;TCP 验证只带 -h127.0.0.1 -P3306,见 5.2/5.4。
Q11:java -version 显示 11 而不是 8?
A:Ubuntu 22.04 装 openjdk-8-jdk 会同时带入 11 并默认指向 11。按 2.3 用 update-alternatives --set 逐项切回,并在 JAVA_HOME(profile)、hadoop-env.sh、Oozie 启动前三处都显式 export JDK8 路径。
Q12:两个 wget 下载同一个文件导致进度回退? A:并行下载同名文件互相覆盖。kill 全部 wget → 删半成品 → 单进程重下,并核对字节数与 Content-Length 一致(见 3.4 坑)。
Q13:Oozie 为什么需要在 Hadoop 的 core-site.xml 配 hadoop.proxyuser.root.hosts/groups?
A:Oozie 以其运行系统用户(本文为 root)代理最终用户访问 HDFS/YARN,Hadoop 侧必须把该用户登记为代理用户,否则提交作业报代理授权失败。实测配置见 4.2。
Q14:WebUI 打开白屏只剩工具栏?
A:ExtJS 未就位。检查 curl -s -o /dev/null -w "%{http_code}" http://localhost:11000/oozie/ext-2.2/ext-all.js 是否 200(实测正常为 HTTP 200, 538956 bytes);404 则回查 7.2/7.7(libext 有无 ext-2.2.zip、无参 oozie-setup.sh 是否执行过)。
十一、参考链接
- Apache Attic — Oozie(退役公告页):https://attic.apache.org/projects/oozie.html
- Oozie 5.2.1 源码归档:https://archive.apache.org/dist/oozie/5.2.1/
- Oozie 5.2.1 官方文档:https://oozie.apache.org/docs/5.2.1/
- AG_Install(libext/ExtJS/sharelib/JDBC 说明):https://oozie.apache.org/docs/5.2.1/AG_Install.html
- ENG_Building(mkdistro 与 hadoop-3 profile):https://oozie.apache.org/docs/5.2.1/ENG_Building.html
- Hadoop 3.3.6 官方文档:https://hadoop.apache.org/docs/r3.3.6/
- Hadoop 3.3.6 下载(国内加速源):https://mirrors.aliyun.com/apache/hadoop/common/hadoop-3.3.6/
- ext-2.2.zip 实测存活来源:https://archive.cloudera.com/gplextras/misc/ext-2.2.zip
- MySQL Connector/J 8.0.33(Maven 加速源):https://maven.aliyun.com/repository/public/com/mysql/mysql-connector-j/8.0.33/
- 本专栏配套:《Apache Oozie 介绍与核心概念》《Apache Oozie 5.2.1 Workflow 与 Coordinator 实战详解》