Node.js 多層子進(jìn)程啟動調(diào)試的問題解決(以 OpenClaw 為例)
問題背景
項目使用 pnpm gateway:watch:debug 啟動后,在 chrome://inspect/#devices 的 Sources 頁簽只能看到 scripts/run-node.mjs,看不到任何業(yè)務(wù)代碼文件。
根本原因
該項目的啟動鏈分三層:
watch-node.mjs(頂層 watch 進(jìn)程)
└── node --inspect --watch ... run-node.mjs(中間層,負(fù)責(zé)構(gòu)建判斷)
└── node openclaw.mjs(實際業(yè)務(wù)進(jìn)程)--inspect flag 只加在了中間層 run-node.mjs 上,真正運行業(yè)務(wù)代碼的 openclaw.mjs 沒有攜帶該 flag,所以 Chrome DevTools 看不到業(yè)務(wù)代碼。
解決思路
需要讓 --inspect 沿著進(jìn)程鏈一路傳遞到最終的業(yè)務(wù)進(jìn)程,同時避免多個進(jìn)程搶占同一調(diào)試端口。
具體改動
1.scripts/watch-node.mjs— 分離 inspect flag,不污染其他子進(jìn)程
原來的邏輯會把所有參數(shù)(包括 --inspect)直接傳給子進(jìn)程,導(dǎo)致 NODE_OPTIONS 污染所有下游進(jìn)程引發(fā)端口沖突。改為顯式分離:
const inspectFlags = deps.args.filter(
(a) => a === "--inspect" || a === "--inspect-brk"
|| a.startsWith("--inspect=") || a.startsWith("--inspect-brk="),
);
const filteredArgs = deps.args.filter((a) => !inspectFlags.includes(a));
if (inspectFlags.length > 0) {
childEnv.OPENCLAW_DEBUG_BUILD = "1";
childEnv.OPENCLAW_INSPECT_FLAGS = inspectFlags.join(" ");
}
const watchProcess = deps.spawn(execPath, [...inspectFlags, ...buildWatchArgs(filteredArgs)], ...);inspectFlags作為 Node 參數(shù)直接傳給中間進(jìn)程(不經(jīng)過 shell 環(huán)境變量)OPENCLAW_INSPECT_FLAGS存入環(huán)境變量,供下一層讀取OPENCLAW_DEBUG_BUILD=1觸發(fā)帶 sourcemap 的構(gòu)建
2.scripts/run-node.mjs— 將 inspect flag 轉(zhuǎn)發(fā)給業(yè)務(wù)進(jìn)程
const inspectNodeArgs = deps.env.OPENCLAW_INSPECT_FLAGS
? deps.env.OPENCLAW_INSPECT_FLAGS.split(" ")
.filter(Boolean)
.map((flag) => {
if (flag === "--inspect") return "--inspect=0";
if (flag === "--inspect-brk") return "--inspect-brk=0";
return flag;
})
: [];
const nodeProcess = deps.spawn(execPath, [...inspectNodeArgs, "openclaw.mjs", ...deps.args], ...);使用 --inspect=0 讓操作系統(tǒng)自動分配空閑端口,避免與父進(jìn)程的 9229 端口沖突。
3.tsdown.config.ts— debug 構(gòu)建時開啟 sourcemap
const isDebugBuild = process.env.OPENCLAW_DEBUG_BUILD === "1";
// 在 nodeBuildConfig 中:
...(isDebugBuild ? { sourcemap: true, minify: false } : {}),沒有 sourcemap,DevTools 只能看到編譯后的 JS,無法映射到 TypeScript 源文件。
4.package.json— 新增調(diào)試命令
"gateway:watch:debug": "node scripts/watch-node.mjs --inspect gateway --force"
最終效果
啟動后終端輸出:
Debugger listening on ws://127.0.0.1:XXXXX/...
在 chrome://inspect/#devices 中可以看到業(yè)務(wù)進(jìn)程的調(diào)試 target,點擊后 Sources 頁簽顯示完整的 TypeScript 源文件,可正常打斷點調(diào)試。
關(guān)鍵經(jīng)驗
- 多層子進(jìn)程調(diào)試,每層都需要
--inspect,但不能共享同一端口 - 用
--inspect=0而不是固定端口,讓 OS 自動分配,徹底避免沖突 - 不要用
NODE_OPTIONS傳 inspect flag,會污染所有子孫進(jìn)程,導(dǎo)致批量端口沖突 - sourcemap 缺失是常見遺漏,生產(chǎn)構(gòu)建通常關(guān)閉 sourcemap,調(diào)試時必須顯式開啟
到此這篇關(guān)于Node.js 多層子進(jìn)程啟動調(diào)試的問題解決(以 OpenClaw 為例)的文章就介紹到這了,更多相關(guān)OpenClaw Node.js 多層子進(jìn)程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
本文給大家介紹OpenClaw配置全流程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2026-03-18
文章講述了作者在配置環(huán)境變量時遇到的問題,以及如何通過在shell配置文件和systemd服務(wù)配置中雙重設(shè)置環(huán)境變量來解決這個問題,作者還分享了常見的錯誤及解決方法,并提出了2026-03-17



