- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- Error 错误
- events 事件触发器
- fs 文件系统
- FFI 外部函数接口
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- sqlite 轻型数据库
- stream 流
- stream/iter 可迭代流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- zlib/iter 可迭代压缩
Node.js v26.2.0 文档
- Node.js v26.2.0
- 目录
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- Error 错误
- events 事件触发器
- fs 文件系统
- FFI 外部函数接口
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- sqlite 轻型数据库
- stream 流
- stream/iter 可迭代流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- zlib/iter 可迭代压缩
- 其他版本
调试器#>
🌐 Debugger
Node.js 包含一个命令行调试工具。Node.js 调试器客户端并不是一个功能齐全的调试器,但可以进行简单的逐步执行和检查。
🌐 Node.js includes a command-line debugging utility. The Node.js debugger client is not a full-featured debugger, but simple stepping and inspection are possible.
🌐 The debugger supports two modes of operation: interactive mode and non-interactive probe mode.
交互模式#>
🌐 Interactive mode
$ node inspect [--port=<port>] [<node-option> ...] [<script> [<script-args>] | <host>:<port> | -p <pid>]
要使用它,请使用 inspect 参数启动 Node.js,然后跟上要调试的脚本路径。
🌐 To use it, start Node.js with the inspect argument followed by the path to the
script to debug.
$ node inspect myscript.js
< Debugger listening on ws://127.0.0.1:9229/621111f9-ffcb-4e82-b718-48a145fa5db8
< For help, see: https://nodejs.cn/learn/getting-started/debugging
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
ok
Break on start in myscript.js:2
1 // myscript.js
> 2 global.x = 5;
3 setTimeout(() => {
4 debugger;
debug>
调试器会自动在第一个可执行行处中断。若希望运行到第一个断点(由 debugger 语句指定),请将环境变量 NODE_INSPECT_RESUME_ON_START 设置为 1。
🌐 The debugger automatically breaks on the first executable line. To instead
run until the first breakpoint (specified by a debugger statement), set
the NODE_INSPECT_RESUME_ON_START environment variable to 1.
$ cat myscript.js
// myscript.js
global.x = 5;
setTimeout(() => {
debugger;
console.log('world');
}, 1000);
console.log('hello');
$ NODE_INSPECT_RESUME_ON_START=1 node inspect myscript.js
< Debugger listening on ws://127.0.0.1:9229/f1ed133e-7876-495b-83ae-c32c6fc319c2
< For help, see: https://nodejs.cn/learn/getting-started/debugging
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
< hello
<
break in myscript.js:4
2 global.x = 5;
3 setTimeout(() => {
> 4 debugger;
5 console.log('world');
6 }, 1000);
debug> next
break in myscript.js:5
3 setTimeout(() => {
4 debugger;
> 5 console.log('world');
6 }, 1000);
7 console.log('hello');
debug> repl
Press Ctrl+C to leave debug repl
> x
5
> 2 + 2
4
debug> next
< world
<
break in myscript.js:6
4 debugger;
5 console.log('world');
> 6 }, 1000);
7 console.log('hello');
8
debug> .exit
$
repl 命令允许远程评估代码。next 命令会执行到下一行。输入 help 查看其他可用命令。
🌐 The repl command allows code to be evaluated remotely. The next command
steps to the next line. Type help to see what other commands are available.
在未输入命令而按下 enter 时,将会重复上一条调试命令。
🌐 Pressing enter without typing a command will repeat the previous debugger
command.
监视器#>
🌐 Watchers
在调试时可以查看表达式和变量的值。在每个断点处,监视器列表中的每个表达式都会在当前上下文中进行求值,并在断点的源代码列表之前立即显示。
🌐 It is possible to watch expression and variable values while debugging. On every breakpoint, each expression from the watchers list will be evaluated in the current context and displayed immediately before the breakpoint's source code listing.
要开始观察一个表达式,输入 watch('my_expression')。命令 watchers 会显示当前有效的观察者。要移除一个观察者,输入 unwatch('my_expression')。
🌐 To begin watching an expression, type watch('my_expression'). The command
watchers will print the active watchers. To remove a watcher, type
unwatch('my_expression').
命令参考资料#>
🌐 Command reference
步进#>
🌐 Stepping
cont,c:继续执行next,n:执行下一步step,s:步骤out,o:走出去pause:暂停运行代码(类似开发者工具中的暂停按钮)
断点#>
🌐 Breakpoints
setBreakpoint(),sb():在当前行设置断点setBreakpoint(line)、sb(line):在特定行设置断点setBreakpoint('fn()')、sb(...):在函数体的第一条语句上设置断点setBreakpoint('script.js', 1),sb(...):在script.js的第一行设置断点setBreakpoint('script.js', 1, 'num < 4'),sb(...):在script.js的第一行设置条件断点,只有当num < 4计算结果为true时才会中断clearBreakpoint('script.js', 1),cb(...):清除script.js第 1 行的断点
也可以在尚未加载的文件(模块)中设置断点:
🌐 It is also possible to set a breakpoint in a file (module) that is not loaded yet:
$ node inspect main.js
< Debugger listening on ws://127.0.0.1:9229/48a5b28a-550c-471b-b5e1-d13dd7165df9
< For help, see: https://nodejs.cn/learn/getting-started/debugging
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
Break on start in main.js:1
> 1 const mod = require('./mod.js');
2 mod.hello();
3 mod.hello();
debug> setBreakpoint('mod.js', 22)
Warning: script 'mod.js' was not loaded yet.
debug> c
break in mod.js:22
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
>22 exports.hello = function() {
23 return 'hello from module';
24 };
debug>
也可以设置一个条件断点,仅当给定表达式计算结果为 true 时才会中断:
🌐 It is also possible to set a conditional breakpoint that only breaks when a
given expression evaluates to true:
$ node inspect main.js
< Debugger listening on ws://127.0.0.1:9229/ce24daa8-3816-44d4-b8ab-8273c8a66d35
< For help, see: https://nodejs.cn/learn/getting-started/debugging
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
Break on start in main.js:7
5 }
6
> 7 addOne(10);
8 addOne(-1);
9
debug> setBreakpoint('main.js', 4, 'num < 0')
1 'use strict';
2
3 function addOne(num) {
> 4 return num + 1;
5 }
6
7 addOne(10);
8 addOne(-1);
9
debug> cont
break in main.js:4
2
3 function addOne(num) {
> 4 return num + 1;
5 }
6
debug> exec('num')
-1
debug>
信息#>
🌐 Information
backtrace,bt:打印当前执行帧的回溯list(5):列出脚本源代码及其上下文(前后各5行)watch(expr):将表达式添加到监视列表unwatch(expr):从观察列表中移除表情unwatch(index):从监视列表中移除特定索引的表达式watchers:列出所有观察者及其值(在每个断点自动列出)repl:在调试脚本的上下文中打开调试器的 REPL 进行评估exec expr,p expr:在调试脚本的上下文中执行一个表达式并打印其值profile:开始 CPU 性能分析会话profileEnd:停止当前的 CPU 分析会话profiles:列出所有已完成的 CPU 分析会话profiles[n].save(filepath = 'node.cpuprofile'):将 CPU 分析会话保存为 JSON 文件到磁盘takeHeapSnapshot(filepath = 'node.heapsnapshot'):拍摄堆快照并以 JSON 格式保存到磁盘
执行控制#>
🌐 Execution control
run:运行脚本(在调试器启动时自动运行)restart:重启脚本kill:结束脚本
其他#>
🌐 Various
scripts:列出所有已加载的脚本version:显示 V8 的版本
探测模式#>
🌐 Probe mode
node inspect 支持通过标志 --probe 在应用中以非交互方式探测运行时值。
目前,探针模式仅支持从命令行指定的入口点脚本启动新进程。
🌐 Currently, probe mode only supports launching a new process from the entry point script specified on the command line.
探测模式会设置一个或多个源代码断点,每当执行到断点时评估指定的表达式,并在会话结束时(无论是正常完成、错误还是超时)打印所有已评估表达式的最终报告。这使开发者能够进行类似 printf 的调试,而无需修改应用代码并在之后进行清理。它还支持用于工具的结构化 JSON 输出。
🌐 The probe mode sets one or more source breakpoints, evaluates specified expressions whenever the execution reaches a breakpoint, and prints one final report of all the evaluated expressions when the session ends (either on normal completion, error, or timeout). This allows developers to perform printf-style debugging without having to modify the application code and clean up afterwards. It also supports structured JSON output for tool use.
$ node inspect --probe <file>:<line>[:<col>] --expr <expr>
[--probe <file>:<line>[:<col>] --expr <expr> ...]
[--json] [--preview] [--timeout=<ms>] [--port=<port>]
[--] [<node-option> ...] <script> [<script-args> ...]
--probe <file>:<line>[:<col>]:探针的源位置。当执行到达该位置时,提供的表达式会被评估并打印在输出中。<file>匹配要探测的脚本的 URL 后缀。<line>和<col>的数字是从 1 开始计数的。当省略<col>时,探针绑定到该行的第一个可执行列。--expr <expr>:JavaScript 表达式,在执行达到前面指定的--probe位置时进行评估。必须紧跟它所属的--probe之后。--timeout=<ms>:整个探测会话的全局实时时钟截止时间。默认值为30000。这可以用来探测可以被外部终止的长时间运行的应用。--json:如果使用,将打印结构化的 JSON 报告,而不是默认的文本报告。--preview:如果使用,非原始值将包括对象类 JSON 探针值的 CDP 属性预览。--port=<port>:选择本地检查端口,探测会话将在该端口监听。默认为0,表示请求一个随机端口。--是可选的,除非子级需要它自己专用的 Node.js 标志。
--probe 和 --expr 参数的附加规则:
🌐 Additional rules about the --probe and --expr arguments:
--probe <file>:<line>[:<col>]和--expr <expr>是严格配对的。每个--probe必须紧跟着正好一个--expr。--timeout、--json、--preview和--port是整个探测会话的全局探测选项。它们可以出现在探测对之前或之间,但不能出现在--probe与其匹配的--expr之间。- 如果需要向子脚本传递额外的 Node.js 执行参数,必须使用
--将探针选项与子脚本的 Node.js 选项分开。
示例:
🌐 Example:
$ node inspect --probe app.js:10 --expr "user"
--probe src/utils.js:5:15 --expr "config.options"
--json --preview -- --no-warnings app.js --arg-for-app=foo
探针输出格式#>
🌐 Probe output format
当探测会话结束时,探测过程会打印所有探测命中和结果的最终报告。
🌐 When the probe session ends, the probing process prints a final report of all the probe hits and results.
考虑这个脚本:
🌐 Consider this script:
// cli.js
let maxRSS = 0;
for (let i = 0; i < 2; i++) {
const { rss } = process.memoryUsage();
maxRSS = Math.max(maxRSS, rss);
}
没有 --json,默认情况下输出将以人类可读的文本格式打印:
🌐 Without --json, by default the output is printed in a human-readable text format:
$ node inspect --probe cli.js:5 --expr 'rss' cli.js
Hit 1 at file:///path/to/cli.js:5:3
rss = 54935552
Hit 2 at file:///path/to/cli.js:5:3
rss = 55083008
Completed
传递给 --probe 的原始 <file>:<line>[:<col>] 可能会被解析到不同的位置以确保它可暂停,或者它可以匹配多个已加载的脚本,因此实际的评估位置有助于消除结果的歧义。
原始结果会直接打印,而对象和数组在可用时会使用 Chrome 开发者工具协议预览数据。其他非原始值会回退到 Chrome 开发者工具协议 description 字符串。表达式失败会记录为 [error] ... 行,并且不会导致整体会话失败。如果需要更丰富的文本格式,可以将表达式封装在 JSON.stringify(...) 或 util.inspect(...) 中。
🌐 Primitive results are printed directly, while objects and arrays use Chrome
DevTools Protocol preview data when available. Other non-primitive values
fall back to the Chrome DevTools Protocol description string.
Expression failures are recorded as [error] ... lines and do not fail
the overall session. If richer text formatting is needed, wrap the expression
in JSON.stringify(...) or util.inspect(...).
当使用 --json 时,输出形状如下:
🌐 When --json is used, the output shape looks like this:
$ node inspect --json --probe cli.js:5 --expr 'rss' cli.js
{"v":2,"probes":[{"expr":"rss","target":{"suffix":"cli.js","line":5}}],"results":[{"probe":0,"event":"hit","hit":1,"location":{"url":"file:///path/to/cli.js","line":5,"column":3},"result":{"type":"number","value":55443456,"description":"55443456"}},{"probe":0,"event":"hit","hit":2,"location":{"url":"file:///path/to/cli.js","line":5,"column":3},"result":{"type":"number","value":55574528,"description":"55574528"}},{"event":"completed"}]}
{
"v": 2, // Probe JSON schema version.
"probes": [
{
"expr": "rss", // The expression paired with --probe.
"target": {
// The user's probe specification. `suffix` is the raw <file> passed
// to --probe and is matched as a path-separator-anchored suffix
// against every loaded script's URL. `column` is present only if the
// user supplied `:col`. The actual evaluation location may differ
// from the target and will be reported in each hit's `location` field.
"suffix": "cli.js",
"line": 5
}
}
],
"results": [
{
"probe": 0, // Index into probes[].
"event": "hit", // Hit events are recorded in observation order.
"hit": 1, // 1-based hit count for this probe.
"location": {
// The actual location where the execution is paused to evaluate
// the expression of the probe. This may differ from the probe's
// target due to pausability adjustments or multiple matches.
"url": "file:///path/to/cli.js",
"line": 5,
"column": 3
},
"result": {
"type": "number",
"value": 55443456,
"description": "55443456"
}
// If the expression throws, "error" is present instead of "result".
},
{
"probe": 0,
"event": "hit",
"hit": 2,
"location": { "url": "file:///path/to/cli.js", "line": 5, "column": 3 },
"result": {
"type": "number",
"value": 55574528,
"description": "55574528"
}
},
{
"event": "completed"
// The final entry is always a terminal event, for example:
// 1. { "event": "completed" }
// 2. { "event": "miss", "pending": [0, 1] }
// 3. {
// "event": "timeout",
// "pending": [0],
// "error": {
// "code": "probe_timeout",
// "message": "Timed out after 30000ms waiting for probes: app.js:10"
// }
// }
// 4. {
// "event": "error",
// "pending": [0],
// "error": {
// "code": "probe_target_exit",
// "exitCode": 1,
// "stderr": "[Error: boom]",
// "message": "Target exited with code 1 before probes: app.js:10"
// }
// }
}
]
}
被探测进程的输出和退出代码#>
🌐 Output and exit codes from the probed process
探测模式仅将最终探测报告打印到 stdout,并且在其他情况下会屏蔽子进程的 stdout/stderr。当探测会话结束时,node inspect 通常以代码 0 退出,并将最终报告打印到 stdout。如果子进程在探测会话结束前以非零代码退出,最终报告会记录一个终止 error 事件,以及退出代码和捕获到的子进程 stderr。在这种情况下,探测进程本身仍然以代码 0 退出。
🌐 Probe mode only prints the final probe report to stdout, and otherwise silences
stdout/stderr from the child process. When the probing session ends,
node inspect typically exits with code 0 and prints a final report to
stdout. If the child process exits with a non-zero code before the
probe session ends, the final report records a terminal error event along
with the exit code and captured child stderr. The probing process itself
still exits with code 0 in this case.
无效的参数以及严重的启动或连接失败可能导致探测进程以非零代码退出,并在标准错误输出中打印错误信息,而不会生成最终的探针报告。
🌐 Invalid arguments and fatal launch or connect failures may cause the probing process to exit with a non-zero code and print an error message to stderr without a final probe report.
在同一执行点探测多个表达式#>
🌐 Probing multiple expressions at the same execution point
当多个 --probe/--expr 对共享相同的 --probe 时,这些表达式将在命令行中出现的顺序在同一次暂停上进行评估。
🌐 When multiple --probe/--expr pairs share the same --probe, the
expressions will be evaluated on the same pause in the order they appear
on the command line.
// app.js
const x = { x: 42 }; // line 2
const y = { y: 35 }; // line 3
const z = { ...x, ...y }; // line 4
$ node inspect --probe app.js:4 --expr 'x' --probe app.js:4 --expr 'y' -- app.js
打印
🌐 Prints
Hit 1 at file:///path/to/app.js:4:1
x = {x: 42}
Hit 1 at file:///path/to/app.js:4:1
y = {y: 35}
Completed
$ node inspect --probe app.js:4 --expr 'x' --probe app.js:4 --expr 'y' --json --preview -- app.js
打印
🌐 Prints
{"v":2,"probes":[{"expr":"x","target":{"suffix":"app.js","line":4}},{"expr":"y","target":{"suffix":"app.js","line":4}}],"results":[{"probe":0,"event":"hit","hit":1,"location":{"url":"file:///path/to/app.js","line":4,"column":1},"result":{"type":"object","description":"Object","preview":{"type":"object","description":"Object","overflow":false,"properties":[{"name":"x","type":"number","value":"42"}]}}},{"probe":1,"event":"hit","hit":1,"location":{"url":"file:///path/to/app.js","line":4,"column":1},"result":{"type":"object","description":"Object","preview":{"type":"object","description":"Object","overflow":false,"properties":[{"name":"y","type":"number","value":"35"}]}}},{"event":"completed"}]}
选择探头位置#>
🌐 Selecting the probe location
当执行到探测位置时,这些表达式会在探测位置的词法作用域中进行求值。避免在由 let 或 const 声明的变量的声明位置进行探测,因为这会导致 ReferenceError,这是由于在变量的暂时性死区(TDZ)中访问该变量所引起的。
🌐 The expressions are evaluated in the lexical scope of the probe location when
execution reaches it. Avoid probing a variable declared by let or const at its
declaration site, as this leads to a ReferenceError caused by
accessing the variable in its temporal dead zone (TDZ).
// app.js
const x = 42; // line 2
console.log(x); // line 3
$ node inspect --probe app.js:1 --expr 'x' app.js
Hit 1 at file:///path/to/app.js:1:1
[error] x = ReferenceError: Cannot access 'x' from debugger
...
Completed
相反,在变量已经被初始化的位置进行探测:
🌐 Instead, probe at a location where the variable is already initialized:
$ node inspect --probe app.js:3 --expr 'x' app.js
Hit 1 at file:///path/to/app.js:3:1
x = 42
Completed
<file> 参数会作为每个已加载脚本 URL 的路径后缀进行匹配,并以路径分隔符为锚点。仅传递文件名会匹配每个具有该文件名的已加载脚本,这类似于本地调试器通常匹配断点的方式,而传递部分路径则会缩小匹配范围。给定:
🌐 The <file> argument is matched as a path suffix of every loaded
script URL, anchored on a path separator. Passing only a basename
matches every loaded script with that basename, similar to how native
debuggers typically match breakpoints, while passing a partial path
narrows the match. Given:
project/
- src/utils.js
- lib/utils.js
--probe utils.js:10 绑定到 两个 文件,并为每个匹配项生成一次命中。
每个命中都带有自己的 location 字段,用于标识表达式实际执行的位置,因此使用者可以准确地将结果归属到两个文件中的一个。为了在绑定时消除歧义,请指定一个只匹配目标文件的完整路径:
$ node inspect --probe src/utils.js:10 --expr 'x' main.js # matches only src/utils.js
高级用法#>
🌐 Advanced usage
Node.js 的 V8 检查器集成#>
🌐 V8 inspector integration for Node.js
V8 Inspector 集成允许将 Chrome DevTools 附加到 Node.js 实例以进行调试和分析。它使用 Chrome 开发者工具协议。
🌐 V8 Inspector integration allows attaching Chrome DevTools to Node.js instances for debugging and profiling. It uses the Chrome DevTools Protocol.
可以通过在启动 Node.js 应用时传递 --inspect 标志来启用 V8 Inspector。也可以通过该标志指定自定义端口,例如 --inspect=9222 将在端口 9222 上接受 DevTools 连接。
🌐 V8 Inspector can be enabled by passing the --inspect flag when starting a
Node.js application. It is also possible to supply a custom port with that flag,
e.g. --inspect=9222 will accept DevTools connections on port 9222.
使用 --inspect 标志会在调试器连接之前立即执行代码。这意味着代码会在你开始调试之前就开始运行,如果你想从一开始就进行调试,这可能不太理想。
🌐 Using the --inspect flag will execute the code immediately before debugger is connected.
This means that the code will start running before you can start debugging, which might
not be ideal if you want to debug from the very beginning.
在这种情况下,你有两种选择:
🌐 In such cases, you have two alternatives:
--inspect-wait标志:这个标志会在执行代码前等待调试器附加。这使你可以从执行开始就进行调试。--inspect-brk标志:与--inspect不同,这个标志会在调试器附加后立即在代码的第一行中断。这在你希望从一开始就逐步调试代码,而不在调试前执行任何代码时非常有用。
因此,在决定使用 --inspect、--inspect-wait 还是 --inspect-brk 时,需要考虑你是希望代码立即开始执行、在执行前等待调试器附加,还是在第一行就中断以进行逐步调试。
🌐 So, when deciding between --inspect, --inspect-wait, and --inspect-brk, consider whether you want
the code to start executing immediately, wait for debugger to be attached before execution,
or break on the first line for step-by-step debugging.
$ node --inspect index.js
Debugger listening on ws://127.0.0.1:9229/dc9010dd-f8b8-4ac5-a510-c1a114ec7d29
For help, see: https://nodejs.cn/learn/getting-started/debugging
(在上面的示例中,URL 末尾的 UUID dc9010dd-f8b8-4ac5-a510-c1a114ec7d29 是动态生成的,在不同的调试会话中会有所不同。)