DolphinScheduler 3.2.2 集成 SeaTunnel 任务启动失败问题排查与解决方案

一、问题背景
在使用 Apache DolphinScheduler 3.2.2 调度 SeaTunnel 数据同步任务时,发现任务在 DolphinScheduler 中执行失败。
SeaTunnel 本身安装正常,手动在服务器上执行 SeaTunnel 命令也能够正常运行,但是通过 DolphinScheduler 的:
bash ./bin/start-all.sh
启动集群后,再执行 SeaTunnel 任务会出现以下错误:
18_132.sh: 行 4: /bin/seatunnel.sh: 没有那个文件或目录
经过排查发现:
- 手动启动 Worker 时,SeaTunnel 任务可以正常执行;
- 使用
start-all.sh启动 DolphinScheduler 后,SeaTunnel 任务执行失败; - SeaTunnel 安装目录实际存在;
- DolphinScheduler Worker 的
SEATUNNEL_HOME环境变量在不同启动方式下存在差异。
最终定位到问题根因:
DolphinScheduler 的
dolphinscheduler-daemon.sh在启动 Worker 时,会使用bin/env/dolphinscheduler_env.sh覆盖 Worker 自己的conf/dolphinscheduler_env.sh。
因此,仅修改:
worker-server/conf/dolphinscheduler_env.sh
并不能保证通过 start-all.sh 启动后仍然生效。
二、环境信息
本次环境主要信息如下:
| 项目 | 配置 |
|---|---|
| DolphinScheduler | 3.2.2 |
| SeaTunnel | 本地部署 |
| 操作系统 | Linux / Ubuntu |
| Java | OpenJDK 17 |
| DolphinScheduler目录 | /usr/local/server/dolphinscheduler |
| SeaTunnel目录 | /usr/local/server/seatunnel |
| Worker目录 | /usr/local/server/dolphinscheduler/worker-server |
| Worker端口 | 1234 |
SeaTunnel 实际安装位置:
/usr/local/server/seatunnel
正常情况下需要:
SEATUNNEL_HOME=/usr/local/server/seatunnel
这样 DolphinScheduler 执行 SeaTunnel 时:
${SEATUNNEL_HOME}/bin/seatunnel.sh
才能正确解析为:
/usr/local/server/seatunnel/bin/seatunnel.sh
三、故障现象
DolphinScheduler 执行 SeaTunnel 任务时,日志出现:
18_132.sh: 行 4: /bin/seatunnel.sh: 没有那个文件或目录
从任务执行命令来看:
${SEATUNNEL_HOME}/bin/seatunnel.sh \
--config /tmp/dolphinscheduler/exec/process/default/185039101090048/185039137408256_2/18/132/seatunnel_18_132.conf \
--deploy-mode cluster
正常情况下:
${SEATUNNEL_HOME}
↓
/usr/local/server/seatunnel
↓
/usr/local/server/seatunnel/bin/seatunnel.sh
但是实际错误变成:
${SEATUNNEL_HOME}
↓
空
↓
/bin/seatunnel.sh
因此可以初步判断:
问题不是 SeaTunnel 的
seatunnel.sh不存在,而是 DolphinScheduler Worker 执行任务时没有获得SEATUNNEL_HOME。
四、首先确认 SeaTunnel 本身是否正常
先检查 SeaTunnel:
ls -l /usr/local/server/seatunnel/bin/seatunnel.sh
如果能够看到:
/usr/local/server/seatunnel/bin/seatunnel.sh
说明 SeaTunnel 文件本身存在。
然后测试:
/usr/local/server/seatunnel/bin/seatunnel.sh --help
如果能够正常输出 SeaTunnel 帮助信息,则说明:
- SeaTunnel 安装正常;
- Java 基础环境基本正常;
seatunnel.sh本身可以执行。
进一步测试环境变量:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
$SEATUNNEL_HOME/bin/seatunnel.sh --help
如果正常,则进一步证明问题集中在:
DolphinScheduler Worker → 环境变量
而不是 SeaTunnel 本身。
五、第一次排查:修改 Worker 环境文件
DolphinScheduler Worker 使用:
/usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
因此最初的解决方法是在该文件中增加:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
检查:
grep -n "SEATUNNEL_HOME" \
/usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
如果存在:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
再手动执行 Worker:
/usr/local/server/dolphinscheduler/worker-server/bin/start.sh
此时 SeaTunnel 任务可以正常运行。
这说明:
worker-server/conf/dolphinscheduler_env.sh中增加SEATUNNEL_HOME是有效的。
但是问题并没有彻底解决。
六、为什么手动启动可以,start-all.sh 却不行?
这是本次问题最关键的地方。
手动启动:
/usr/local/server/dolphinscheduler/worker-server/bin/start.sh
与:
bash ./bin/start-all.sh
实际上不是完全相同的启动路径。
6.1 手动启动路径
手动启动大致为:
worker-server/bin/start.sh
↓
读取
worker-server/conf/dolphinscheduler_env.sh
↓
读取 SEATUNNEL_HOME
↓
启动 Worker
因此手动启动时:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
能够正常生效。
七、start-all.sh 的实际启动流程
检查:
/usr/local/server/dolphinscheduler/bin/start-all.sh
可以发现 Worker 并不是直接调用:
worker-server/bin/start.sh
而是:
bash bin/dolphinscheduler-daemon.sh start worker-server
也就是说:
start-all.sh
↓
dolphinscheduler-daemon.sh
↓
worker-server/bin/start.sh
真正关键的是中间这一层:
dolphinscheduler-daemon.sh
八、发现真正的根因:环境文件会被覆盖
查看:
cat /usr/local/server/dolphinscheduler/bin/dolphinscheduler-daemon.sh
其中存在:
function overwrite_server_env() {
local server=$1
local server_env_file="${DOLPHINSCHEDULER_HOME}/${server}/conf/dolphinscheduler_env.sh"
if [ -f "${BIN_ENV_FILE}" ]; then
echo "Overwrite ${server}/conf/dolphinscheduler_env.sh using bin/env/dolphinscheduler_env.sh."
cp "${BIN_ENV_FILE}" "${server_env_file}"
else
echo "Start server ${server} using env config path ${server_env_file}, because file ${BIN_ENV_FILE} not exists."
fi
}
其中:
BIN_ENV_FILE="${DOLPHINSCHEDULER_HOME}/bin/env/dolphinscheduler_env.sh"
而 Worker 启动时执行:
overwrite_server_env "${command}"
因此实际发生的是:
/usr/local/server/dolphinscheduler/bin/env/dolphinscheduler_env.sh
↓
↓ cp
↓
/usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
也就是说:
worker-server/conf/dolphinscheduler_env.sh并不是最终的配置源。
它会在 DolphinScheduler 使用 dolphinscheduler-daemon.sh 启动 Worker 时被覆盖。
九、完整问题链路
整个问题可以表示为:
DolphinScheduler
│
▼
start-all.sh
│
▼
dolphinscheduler-daemon.sh
│
▼
overwrite_server_env()
│
│
┌────────────┴────────────┐
│ │
▼ ▼
bin/env/dolphinscheduler_env.sh worker-server/conf/
dolphinscheduler_env.sh
│ ▲
│ │
└────────── cp ──────────┘
│
▼
worker-server/bin/start.sh
│
▼
读取 dolphinscheduler_env.sh
│
▼
SEATUNNEL_HOME 是否存在?
│
┌──────────────┴──────────────┐
│ │
是 否
│ │
▼ ▼
/usr/local/server/ ${SEATUNNEL_HOME}
seatunnel 为空
│ │
▼ ▼
/usr/local/server/seatunnel/ /bin/seatunnel.sh
bin/seatunnel.sh │
▼
❌ 失败
十、正确解决方案
10.1 不应该只修改 Worker 配置文件
之前修改:
/usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
虽然可以让手动启动生效,但是:
start-all.sh
启动时会重新覆盖该文件。
因此不推荐只修改这里。
10.2 修改统一环境配置
正确配置文件应该是:
/usr/local/server/dolphinscheduler/bin/env/dolphinscheduler_env.sh
首先检查:
grep -n "SEATUNNEL_HOME" \
/usr/local/server/dolphinscheduler/bin/env/dolphinscheduler_env.sh
如果没有结果,则增加:
echo 'export SEATUNNEL_HOME=/usr/local/server/seatunnel' >> \
/usr/local/server/dolphinscheduler/bin/env/dolphinscheduler_env.sh
然后确认:
tail -n 10 \
/usr/local/server/dolphinscheduler/bin/env/dolphinscheduler_env.sh
应该能够看到:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
十一、重新启动 DolphinScheduler
修改统一配置之后,需要重新启动服务。
进入:
cd /usr/local/server/dolphinscheduler
停止:
bash ./bin/stop-all.sh
检查 Worker:
ps -ef | grep WorkerServer | grep -v grep
确认旧 Worker 已经停止后,再执行:
bash ./bin/start-all.sh
十二、验证配置是否被正确复制
启动完成以后,首先检查:
grep -n "SEATUNNEL_HOME" \
/usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
应该看到:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
这是因为:
bin/env/dolphinscheduler_env.sh
↓
dolphinscheduler-daemon.sh
↓
overwrite_server_env()
↓
worker-server/conf/dolphinscheduler_env.sh
已经完成了正确的配置复制。
十三、进一步检查 Worker 进程环境
仅检查配置文件还不够,最好检查实际运行中的 Worker JVM 环境。
先找到 Worker PID:
ps -ef | grep WorkerServer | grep -v grep
例如得到:
dolphin+ 153245 ... org.apache.dolphinscheduler.server.worker.WorkerServer
然后:
PID=153245
cat /proc/$PID/environ | tr '\0' '\n' | \
grep -E 'SEATUNNEL_HOME|DOLPHINSCHEDULER_HOME|JAVA_HOME'
正常应该至少包含:
SEATUNNEL_HOME=/usr/local/server/seatunnel
这样才能证明:
SEATUNNEL_HOME不仅写入了配置文件,而且真正进入了 Worker 进程环境。
十四、最终验证 SeaTunnel 任务
重新执行 DolphinScheduler 中的 SeaTunnel 任务。
任务命令:
${SEATUNNEL_HOME}/bin/seatunnel.sh \
--config /tmp/dolphinscheduler/exec/process/default/.../seatunnel_18_132.conf \
--deploy-mode cluster
此时应该被正确解析为:
/usr/local/server/seatunnel/bin/seatunnel.sh \
--config /tmp/dolphinscheduler/exec/process/default/.../seatunnel_18_132.conf \
--deploy-mode cluster
不再出现:
/bin/seatunnel.sh: 没有那个文件或目录
十五、建议增加一项启动检查
为了以后避免类似问题,可以在部署完成后执行:
echo "===== DolphinScheduler Environment ====="
echo "DOLPHINSCHEDULER_HOME=$DOLPHINSCHEDULER_HOME"
echo "SEATUNNEL_HOME=$SEATUNNEL_HOME"
echo "JAVA_HOME=$JAVA_HOME"
echo "===== SeaTunnel ====="
ls -l "$SEATUNNEL_HOME/bin/seatunnel.sh"
如果:
SEATUNNEL_HOME=
或者:
ls: cannot access .../seatunnel.sh
就不要继续执行任务,应先修复环境变量。
十六、另一个独立问题:Java 17 的 InaccessibleObjectException
在排查过程中还发现了另外一个异常:
java.lang.reflect.InaccessibleObjectException:
Unable to make field private final int java.lang.ProcessImpl.pid accessible:
module java.base does not "opens java.lang" to unnamed module
这个问题与:
/bin/seatunnel.sh: 没有那个文件或目录
不是同一个问题。
前者属于:
DolphinScheduler
↓
Java 17
↓
反射访问 JDK 内部字段
↓
Java Module System
↓
InaccessibleObjectException
后者属于:
DolphinScheduler Worker
↓
SEATUNNEL_HOME
↓
环境变量没有传递
↓
/bin/seatunnel.sh
因此排查时应该分开处理。
十七、Java 17 问题的处理方向
当前 Worker 使用:
Java 17
而 DolphinScheduler 相关代码中存在:
java.lang.ProcessImpl.pid
等反射访问。
后续可以检查 Worker 的:
/usr/local/server/dolphinscheduler/worker-server/bin/jvm_args_env.sh
以及实际启动参数:
ps -ef | grep WorkerServer | grep -v grep
重点确认是否需要增加类似:
--add-opens=java.base/java.lang=ALL-UNNAMED
对于另外出现的:
java.lang.invoke.SerializedLambda.capturingClass
则可能涉及:
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED
不过这属于第二阶段问题。
建议先确认 SeaTunnel 调度链路恢复正常,再单独处理 Java 17 反射兼容问题。
十八、排查过程中最容易犯的错误
错误一:只修改 worker-server 配置
例如:
vim /usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
增加:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
然后认为问题已经解决。
实际上:
start-all.sh
↓
dolphinscheduler-daemon.sh
↓
overwrite_server_env()
会覆盖这个文件。
错误二:只测试手动启动
worker-server/bin/start.sh
正常并不代表:
start-all.sh
正常。
因为两种启动路径不同。
因此排查 DolphinScheduler 服务环境问题时,应优先验证实际生产启动方式。
错误三:看到 /bin/seatunnel.sh 就认为 SeaTunnel 没安装
实际上:
/bin/seatunnel.sh
这个路径本身就暴露了问题。
如果正确配置:
SEATUNNEL_HOME=/usr/local/server/seatunnel
最终路径应该是:
/usr/local/server/seatunnel/bin/seatunnel.sh
因此:
/bin/seatunnel.sh
实际上说明:
${SEATUNNEL_HOME}没有展开出有效值。
十九、推荐的最终配置结构
建议把 DolphinScheduler 与 SeaTunnel 的环境配置统一管理:
/usr/local/server/dolphinscheduler/
│
├── bin/
│ ├── start-all.sh
│ ├── stop-all.sh
│ ├── dolphinscheduler-daemon.sh
│ │
│ └── env/
│ └── dolphinscheduler_env.sh ← ★统一配置源
│
├── worker-server/
│ ├── bin/
│ │ └── start.sh
│ │
│ └── conf/
│ └── dolphinscheduler_env.sh ← daemon启动时覆盖
│
└── ...
统一配置:
# SeaTunnel
export SEATUNNEL_HOME=/usr/local/server/seatunnel
这样:
start-all.sh
↓
dolphinscheduler-daemon.sh
↓
bin/env/dolphinscheduler_env.sh
↓
worker-server/conf/dolphinscheduler_env.sh
↓
worker-server/bin/start.sh
↓
Worker JVM
↓
SeaTunnel Task
整个链路的环境变量才能保持一致。
二十、总结
本次问题最终可以归纳为:
表面错误
/bin/seatunnel.sh: 没有那个文件或目录
直接原因
SEATUNNEL_HOME 为空
深层原因
通过:
start-all.sh
启动 DolphinScheduler 时:
dolphinscheduler-daemon.sh
会执行:
overwrite_server_env "${command}"
将:
bin/env/dolphinscheduler_env.sh
复制覆盖:
worker-server/conf/dolphinscheduler_env.sh
而 SEATUNNEL_HOME 之前只配置在 Worker 自己的配置文件中,所以被覆盖后丢失。
正确解决方案
将:
export SEATUNNEL_HOME=/usr/local/server/seatunnel
配置到:
/usr/local/server/dolphinscheduler/bin/env/dolphinscheduler_env.sh
然后重新执行:
cd /usr/local/server/dolphinscheduler
bash ./bin/stop-all.sh
bash ./bin/start-all.sh
最后验证:
grep -n "SEATUNNEL_HOME" \
/usr/local/server/dolphinscheduler/worker-server/conf/dolphinscheduler_env.sh
以及:
PID=$(pgrep -f 'org.apache.dolphinscheduler.server.worker.WorkerServer' | head -1)
cat /proc/$PID/environ | tr '\0' '\n' | \
grep SEATUNNEL_HOME
预期:
SEATUNNEL_HOME=/usr/local/server/seatunnel
核心经验:在 DolphinScheduler 中,通过 start-all.sh 启动服务时,应优先修改 bin/env/ 下的统一环境配置,而不是只修改各 Server 自己的 conf/ 环境文件。



