最近在调研如何远程调试一个 nodejs 进程,大致调研路径是 Chome DevTolls -> Chrome debugging protocol -> chrome-remote-interface,本文重点介绍下 chrome-remote-interface 的简单使用。
根据其文档,这个工具主要是提供一个 js api,在连接到对应的服务端(要调试的端)后,通过 Chrome Debugging Protocol 与之交互。
所以其基本的使用分为以下几个步骤:
- 启动 nodejs 实例,并打开调试模式, eg.
node --inspect-brk=9222 for-insepct.js
- 通过 CDP 连接到远程调试实例
- 通过 CDP Client 操作远程调试实例
准备待调试的 nodejs 实例
先新建 for-inspect.js
,可以写入任意可执行的代码:
执行代码,附加 --inspect-brk=9222
调试参数:
1
| $ node --inspect-brk=9222 for-insepct.js
|
有关 inspect-brk 参数的作用可以参考 node文档,简单来说就是打开调试模式,并在代码首行断点执行,默认实例调试地址为 localhost:9229
此时,nodejs 已经在 localhost:9222
上启动了调试实例,可以通过访问 http://localhost:9222/json
查看详细信息:
1 2 3 4 5 6 7 8 9 10 11
| [ { "description": "node.js instance", "devtoolsFrontendUrl": "devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=localhost:9222/4d7174b7-e4cf-4d60-84c5-80f3eed2477d", "devtoolsFrontendUrlCompat": "devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=localhost:9222/4d7174b7-e4cf-4d60-84c5-80f3eed2477d", "faviconUrl": "https://nodejs.org/static/images/favicons/favicon.ico", "id": "4d7174b7-e4cf-4d60-84c5-80f3eed2477d", "title": "for-insepct.js", "type": "node", "url": "file:///Users/lilonglong/Desktop/long_git/chrome-devtools-analysis/for-insepct.js", "webSocketDebuggerUrl": "ws://localhost:9222/4d7174b7-e4cf-4d60-84c5-80f3eed2477d" } ]
|
可通过 Chrome 直接访问 devtoolsFrontendUrl
:
当然,可以通过上面的 Chrome 来调试 nodejs 代码,所以此方案不是重点,重点是如何通过代码来远程调试 nodejs 代码。
通过 chrome-remote-interface 远程调试 nodejs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| const CDP = require("chrome-remote-interface");
CDP(async (client) => { const { Debugger, Runtime, Network } = client; try { Debugger.on("scriptParsed", async (params) => { const { scriptId, url } = params; if (url.startsWith("file://")) { const source = await client.Debugger.getScriptSource({ scriptId }); console.log("script source", source); } });
Debugger.on("paused", (pausedEvent) => { });
await Runtime.runIfWaitingForDebugger();
await Debugger.enable(); await Runtime.enable();
const testValue = await Runtime.evaluate({ expression: "eval(1 + 1)", }); console.log("evaluate result", testValue); } catch (err) { console.error(err); } finally { client.close(); } }).on("error", (err) => { console.error(err); });
|
执行结果:
Reference