Electron + pnpm 在鸿蒙应用里跑起来

上篇《把 Electron 应用搬进鸿蒙的 8 个坑》结尾,我留了个「绕不过去的坎」:鸿蒙应用域里,spawn 一个 node / pnpm 子进程,会被 seccomp 直接 SIGSYS 杀掉。

当时我把它归为「平台级无解」。今天这篇要打自己的脸:那个坎不是无解,换个思路就过去了。 插件市场的一键安装,现在已经在鸿蒙真机上跑通。

这篇文章讲清三件事:为什么 spawn 必死、怎么用「进程内 pnpm」绕过去、真机上又踩了哪三个坑。如果你也在鸿蒙上折腾 Node 生态的包管理,这套思路可以直接抄。

一、问题:为什么 spawn 一个 node 就死

先把这个「坎」的硬度说清楚。

我在鸿蒙 2in1 真机上、应用进程里、同一个 SELinux 域下,实测了一组命令:

命令 结果
node -v ✅ v24.13.0
node -e "console.log(1)" ❌ Signal 31(SIGSYS)
node --jitless -e "..." ❌ SIGSYS
npm -v ❌ SIGSYS
python3 -c "print('ok')" ✅

看懂这组数据,关键在于三个「不是」:

  • 不是「不能执行代码」------python3 连同多线程都正常跑;
  • 不是「node 坏了」 ------node -v 能正常打印版本;
  • 也不是文件沙箱、权限、路径问题------放宽文件策略后结果不变。

真正的原因是:应用域里 fork 出的子进程,只要尝试分配「JIT 可执行内存」,就会被内核 seccomp 策略投递 SIGSYS。V8 一创建 isolate(真正开始编译执行 JS),必死。

而 pnpm、npm、corepack------全都是 node 脚本。所以「把 pnpm 装到 PATH 上让市场调用」这条路,跟 pnpm 装在哪、PATH 怎么配,一点关系都没有,天生走不通。

二、排查:三个假象,一个真凶

排查过程我踩了三个坑,前两个都是假象,差点把我带沟里。

假象一:pnpm@12 装不上。

报错 pnpm does not ship a prebuilt binary for openharmony-arm64。因为 pnpm 从 v12 起改成了 Rust 原生分发壳,平台白名单里压根没有 openharmony。解法是退回纯 JS 的 pnpm@11 / 10------但这只是「装上了」,离「能用」还差十万八千里。

假象二:PATH 不生效。

写 ~/.profile 没用,因为鸿蒙终端是 zsh,只读 ~/.zshenv。这个坑花了不少时间,解决后 pnpm 在终端里能跑了,应用里还是不行。

真凶:就是上面那组 SIGSYS 实测。

终端(真实 shell)能跑 node/pnpm,应用域里的子进程却全崩------差别就在 seccomp 只针对应用域 fork 出的子进程。

三、洞察:SIGSYS 只杀子进程,不杀主进程

卡住我的那堵墙,其实有个缺口:

SIGSYS 只杀「fork 出的子进程」。而 Electron 主进程自身,就是 Node 22.17,能正常跑 JS。

既然主进程能跑 JS,那我不 spawn 子进程,把 pnpm 的 JS 直接 import 进主进程里跑,不就把 seccomp 绕开了?

这就是整个方案的立足点------「进程内 pnpm」。思路一换,墙就没了。

四、方案:把 pnpm 塞进主进程,用 worker 线程跑

方案定了,落地有三个关键决策。

决策一:版本退回 pnpm@10.34.6。

pnpm@11 是纯 ESM,但它依赖 node:sqlite,而 Electron/Node 运行时没有这个 binding,import 直接报 No such binding: sqlite。所以退回 pnpm@10.34.6(纯 CJS、不碰 node:sqlite)。

决策二:丢进 worker 线程,而不是直接 import。

直接 import pnpm 有个坑:pnpm 的 main 是「火忘式」异步、从不调 process.exit,你根本没法知道它装完了没;更危险的是,它内部可能调 process.exit,在进程内跑会直接杀掉 Electron 主进程。

解法是把它丢进 worker_threads.Worker,一次解决三件事:

  • 完成检测:worker 事件循环排空 → 退出,退出码就是 pnpm 的退出码;
  • process.exit 隔离:只会退出 worker,不杀主进程;
  • ESM 缓存 :每次 new Worker 都是全新模块图,不用管缓存击穿。

决策三:扁平布局,绕开 symlink / hardlink 禁令。

pnpm 默认 node-linker=isolated,会在 node_modules 里建 symlink、在 store 里建 hardlink------鸿蒙沙箱两者都禁。所以必须:

  • nodeLinker: hoisted:生成扁平 node_modules,无 symlink、无 .pnpm 虚拟 store;
  • packageImportMethod: copy:从 store 拷贝文件而非 hardlink;
  • storeDir 指向沙箱内可写目录。

五、真机上的三个修复

设计想得再周全,真机一跑还是崩出三个问题,逐个修:

# 问题 现象 修复
P1 pnpm@11 依赖 node:sqlite import 抛 No such binding: sqlite 引擎退回 pnpm@10.34.6
P2 Electron 的 process.execPath 只读 pnpm 配置里无条件 process.execPath = node → 抛 Cannot assign to read only property worker import 前把 process.execPath 设成 no-op setter(保留真实值)
P3 鸿蒙禁 symlink,pnpm 仍建 .bin 软链 EACCES: symlink ... -> .bin/... → 安装失败 worker 里把 fs.symlink 在 EACCES/EPERM 时回退为 copy ,.bin 落成真实文件

三个修复都不复杂,但每一个都是「真机才暴露、设计时想不到」的坑。

六、结果:一键安装,真机跑通

修完这三个,端到端通了。市场一键安装 / 卸载插件,全程:

  • 无 node / pnpm 子进程------日志里的 pid 就是应用主进程;
  • 无 symlink------profile 的 node_modules 递归扫描 symlinkCount = 0;
  • 零 ELF、零二进制证书、零额外 ACL。

装了个插件试水,exit=0, hot=true, live------装上即热加载。

写在最后

回头看,这个「绕不过去的坎」其实不是坎,是个思路问题:

你以为「跑 pnpm」只能 spawn 子进程,但鸿蒙的 seccomp 只杀子进程、不杀主进程------换个「进程内」的角度,墙就没了。

如果你也在鸿蒙上折腾 Node 生态的包管理,这套「worker 线程进程内跑 pnpm + hoisted + symlink→copy」的思路,可以直接抄。

代码已开源,欢迎 star:

下一篇我写 App 上架合规踩坑:被 AppGallery 打回 12 条整改,从商标撞名到 ArkWeb 合规。关注我,别错过。

感谢各位关注,欢迎访问我的 GitHub 主页:https://fellow99.github.io/

相关推荐
记得开心一点嘛2 小时前
Trellora:基于 Electron、React 和本地知识库的 AI 知识工作台
人工智能·react.js·electron
熊猫钓鱼>_>3 小时前
从闲置平板到家里的“控制大脑“:鸿蒙智慧中控面板完整实战
运维·人工智能·华为·自动化·电脑·ai编程·harmonyos
EatFan3 小时前
从 CUDA 到昇腾:一张对照表拆解 DeepSeek 最新开源组件(TileLang / DeepGEMM / DeepEP / TileKernels)
开源·cuda·deepseek·deepgemm·tilelang·华为昇腾
500843 小时前
React Native for OpenHarmony 实战:三方库 react-native-url-polyfill 的鸿蒙化适配指南
javascript·react native·react.js·性能优化·electron·harmonyos
skywalk81633 小时前
deepseek harness 官方已经更新到新版:v0.2.1-alpha.1 Pre-release请把咱们的FreeBSD版本也同步更新到新版本!
人工智能·freebsd·实践·deepseek·harness
不可能片场3 小时前
内容运营自动化 用相似度拦住撞车选题
前端·electron
凉冬寒4 小时前
从 npm 版 dsh 迁移到 DSH 桌面版:彻底告别 dsh web
deepseek
熊猫钓鱼>_>6 小时前
从2D平铺到3D沉浸:我用HarmonyOS 7端侧AI做了一个全程数据不出设备的空间化私密相册
前端·人工智能·3d·华为·华为云·harmonyos·鸿蒙
m0_738185826 小时前
Flutter 鸿蒙化实战:foundation_fluttify 适配 OpenHarmony,Fluttify 桥接层
flutter·华为·harmonyos·鸿蒙