现象:明明传了 cli,却报找不到模块
给「不可能片场」的发布流水线接 MatrixMedia 时,我习惯在子进程里复用宿主环境的环境变量。结果一调 matrixmedia.exe,Electron 没按预期进入 CLI 模式,反而退化成普通 node,抛出 Cannot find module '...\cli'。
排查后才发现,宿主环境里有一个被悄悄带进来的变量:ELECTRON_RUN_AS_NODE=1。
根因:这个变量会改变 Electron 的启动语义
bash
# 宿主环境里如果残留了这个变量
echo $ELECTRON_RUN_AS_NODE
# 1
ELECTRON_RUN_AS_NODE 是 Electron 官方支持的开关:当它被设置时,Electron 的主进程会像 node 一样直接执行脚本,而不是走自己的应用入口。这意味着两件事:
- 应用自己的模块解析路径(
app.asar/resources/app)不会被加载; - 你在命令行里写的
cli子命令,在 node 语义下只是一个普通参数,Electron 找不到对应的命令分发逻辑,于是报Cannot find module '.../cli'。
注意,这个变量往往不是你主动设的------它可能是上层编排器、容器、或者某个自动化宿主为了兼容 Electron 而预置的。它会在子进程里被原样继承,导致「在我机器上能跑,在流水线里就报错」。
修复:调 CLI 前先 unset
修复方式极其简单,但容易忘:在调用 matrixmedia 之前,把变量清掉。
bash
# 关键一步:清掉这个变量,否则 Electron 退化成 node
unset ELECTRON_RUN_AS_NODE
# 然后再调,走正常的 CLI 通道
./matrixmedia.exe --no-sandbox --disable-gpu-sandbox cli publish-article \
-p juejin --phone "不可能片场" -t "标题" \
--category 人工智能 --file "/abs/path.md"
封装:别让每个调用点都记着这件事
最稳妥的做法是把「清变量」固化进启动脚本,而不是指望每次手动 unset。我们的 mmcli.cmd 里就有一行专门干这个:
bat
@echo off
chcp 65001 >nul
set "ELECTRON_RUN_AS_NODE="
"%~dp0matrixmedia.exe" --no-sandbox --disable-gpu-sandbox cli %*
set "ELECTRON_RUN_AS_NODE=" 这一句把变量置空,等价于 unset。之后无论宿主环境带没带这个坑,子进程都不会再退化。
教训:环境变量的继承要当成隐性依赖
这条坑的代价不高(一次 unset 解决),但定位成本极高------报错信息指向「模块找不到」,和真正的根因(环境变量)隔了好几层。它提醒我:在长链路自动化里,子进程继承的每一个环境变量,都是一条需要被审计的隐性依赖。尤其当宿主是另一个会「好心」预置兼容变量的编排器时,显式清理比被动兼容更可靠。