作者:阮一峰。原文发表于 2018 年 3 月 20 日:《Node 调试工具入门教程》。本文在完整核对原文后整理,保留示例的讲解顺序,并将版本变化与安全修订单独标明。
JavaScript 程序复杂起来之后,只靠输出日志不容易看清函数调用与变量变化。Node 可以开放 Inspector 接口,让 Chrome DevTools 连接到正在运行的 Node 进程。浏览器在这里充当调试客户端,执行服务端代码的仍然是 Node。原文介绍的核心能力是:设置断点、在暂停处检查变量、临时修改状态,然后继续执行。

一、准备一个便于观察的 Web 服务
在单独的本地练习目录中生成 package.json,安装 Koa 与 koa-route。原文使用的命令如下,行首命令提示符已省略:
mkdir debug-demo
cd debug-demo
npm init -y
npm install --save koa koa-route
安装说明:这组命令会从包注册表下载依赖,且没有固定版本;它并不重建作者在 2018 年的环境。实际练习前应核对 Node 与依赖支持范围,保留锁文件,并在不含生产凭证的练习目录操作。本文未运行这些命令。
新建 app.js。两个路由分别响应根路径和姓名参数:
const Koa = require('koa');
const router = require('koa-route');
const app = new Koa();
const main = ctx => {
ctx.type = 'text/plain';
ctx.response.body = 'Hello World';
};
const welcome = (ctx, name) => {
ctx.type = 'text/plain';
ctx.response.body = 'Hello ' + name;
};
app.use(router.get('/', main));
app.use(router.get('/:name', welcome));
app.listen(3000, '127.0.0.1');
console.log('listening on http://127.0.0.1:3000');
与原文的区别:原文调用 app.listen(3000),没有限制 HTTP 监听地址;这里显式绑定 127.0.0.1,让示例只接受本机连接。两个响应还显式设置为纯文本,防止把用户提供的 name 当作 HTML 呈现。这是安全修订,不是声称原文已经具备这些防护,也不是完整的生产服务设计。
CommonJS 的 require() 是原文写法;若练习项目声明了 "type": "module",需要使用匹配的模块形式,或将示例保存在 .cjs 文件中。路由的目标没有改变:访问根路径得到问候语,访问 /alice 时将 alice 传给 welcome。
二、启动 Inspector 并连接 Chrome
node --inspect=127.0.0.1:9229 app.js
原文命令为 node --inspect app.js。按照当前 Node 官方说明,默认地址本来就是 127.0.0.1:9229;这里写全,是为了把调试端口边界直接呈现给读者。业务 HTTP 流量走 3000,调试协议走 9229,两者不是同一个服务。
在浏览器中打开 http://127.0.0.1:3000,教程预期返回 Hello World。然后打开 chrome://inspect,确认目标主机和端口在 Configure 列表中,在 Remote Target 中找到 Node 进程并点击 inspect。原文还给出 about:inspect 以及普通 DevTools 左上角绿色 Node 图标这两种入口;它们属于历史界面描述,当前使用时以实际 Chrome 版本为准。
原文中的 Node 专用 DevTools 主要包含 Console、Memory、Profiler、Sources 四个面板。Console 用于表达式求值,Memory 用于内存检查,Profiler 用于性能分析,Sources 用于查看源代码和控制执行。本教程聚焦 Sources;面板的名称、分组和可用功能会随版本调整。
三、在请求处理函数里设断点
进入 Sources,找到 app.js,点击下面赋值语句左侧的行号:
ctx.response.body = 'Hello ' + name;
原文写的是第 11 行。加入纯文本响应设置后,行号已经改变,因此应按语句定位,不要机械照抄行号。断点通常使程序在执行这条语句之前暂停。
访问 http://127.0.0.1:3000/alice。如果断点被命中,页面会等待服务器响应,DevTools 则显示暂停状态。这时切换到 Console,输入 name,教程预期得到 alice。这里读取的是所选暂停栈帧中的变量,不是浏览器页面上的全局变量。
返回 Sources,可在右侧看到 Watch、Call Stack、Scope、Breakpoints 等区域。Watch 用来持续观察表达式;Call Stack 表示函数调用链;Scope 列出当前作用域能访问的值;Breakpoints 汇总断点。展开 Scope 中的 Local,可以找到本次请求的 name,Global 则显示全局作用域内容。
按原文的实验,双击 Local 里的 name,把 alice 临时改成 bob,再点击继续执行。赋值语句恢复运行时读取了修改后的变量,因此教程预期页面显示 Hello bob。这是对进程内存中当前状态的修改,不等同于修改磁盘上的源文件;下一次请求仍由它自己的参数决定。
练习结束后,在启动 Node 的终端按 Ctrl+C 终止该练习进程。暂停 Node 主线程会影响该进程的请求处理,调试器也能修改状态和执行表达式,所以这套练习应放在本地隔离环境,不应用生产流量演示。
四、短脚本来不及连接时,先在入口暂停
Web 服务会持续监听,而一些 Node 脚本运行完任务就退出。原文先用一个 30 秒定时器说明如何给连接调试器留出时间:
node --inspect=127.0.0.1:9229 -e "setTimeout(function() { console.log('yes'); }, 30000)"
-e 把后面的字符串作为 JavaScript 执行。Inspector 仍在 9229 端口等待连接,定时器到期时输出 yes。但是把业务代码塞进定时器并不适合作为日常调试方法,也会改变原来的时间行为。
更直接的方式是在用户代码开始执行之前暂停:
node --inspect-brk=127.0.0.1:9229 app.js
--inspect-brk 同时启用 Inspector 和启动暂停。连接 DevTools 后,可以先设置后续断点,再恢复执行。它与单独的 --inspect 的关键区别是“何时暂停”,并不是另起一个 HTTP 服务。
五、进程已经启动,却忘记加调试参数
原文先正常运行 node app.js,再通过 ps ax | grep app.js 查找 PID。示例输出里 30464 对应 Node,另一个 PID 对应搜索命令本身。这个数字仅属于作者当时的机器,不能复制到另一台机器上操作。
原文接着使用内部接口:
# 历史示例,仅用于理解原文,不作为推荐操作
node -e 'process._debugProcess(30464)'
版本补充:process._debugProcess 以下划线开头,是内部接口,不应当作跨版本稳定 API。在本地练习里,能重新启动时优先使用公开的 --inspect 或 --inspect-brk 参数。
原文还给出向目标进程发送 SIGUSR1 的办法:
# Unix 类系统上的原文示意:30464 必须换成已核实的自有测试进程 PID
kill -SIGUSR1 30464
这个命令不是 Windows 通用命令。当前 Node 官方文档仍介绍了以 SIGUSR1 启动 Inspector 的能力,也列出了可以禁用它的 --disable-sigusr1 参数;能否附加取决于平台、版本与进程配置。信号发给错误 PID 会作用于错误进程,因此本文只保留历史方法说明,没有发送任何信号。
六、调试端口本身就是权限边界
根据 Node 官方调试指南,能够连接 Inspector 的客户端可以在 Node 进程中执行任意代码。不要把调试端口绑定到 0.0.0.0 或公开 IP;只绑定回环地址也不能防住同一台机器上其他不可信进程。调试器没有为不可信公网客户端准备的登录保护。
本篇静态检查没有发现硬编码密码或令牌。实际需要修订的是 HTTP 监听范围、用户输入的呈现类型,以及旧内部接口和固定 PID 的照搬风险。未发现其他问题不代表示例没有漏洞;本文没有进行依赖漏洞扫描、运行测试或网络验证。
来源与版权
原作者:阮一峰;原文网址与日期见文首。原文页注明“自由转载—非商用—非衍生—保持署名”,链接为 CC BY-NC-ND 3.0。本次整理经单独授权;原页面的非衍生公开许可本身不作为本次改编授权的替代。新增说明和安全修订均已在相应位置标明。
原文参考文章:Jacopo Daeli 的 Debugging Node.js with Google Chrome、Paul Irish 的 Debugging Node.js with Chrome DevTools,以及 Remy Sharp 的 Last minute node debugging。这些是作者的延伸参考,不是本次执行测试的证据。












暂无评论内容