调试器

Node.js 内置了功能强大的调试工具,该工具可通过 TCP 协议或者内建的调试客户端进行调用。使用时,需要以 debug 参数启动 Node.js,后跟要调试的脚本文件路径,调试器启动后会显示一个提示符 debug>

  1. $ node debug myscript.js
  2. < debugger listening on port 5858
  3. connecting... ok
  4. break in /home/indutny/Code/git/indutny/myscript.js:1
  5. 1 x = 5;
  6. 2 setTimeout(() => {
  7. 3 debugger;
  8. debug>

Node.js 的调试器客户端现在还不能支持完整的调试命令,仅支持简单的步进和检查。

debugger; 语句插入到脚本之中,相当于在特定代码行设置了断点。假设我们有如下所示的一段代码:

  1. // myscript.js
  2. x = 5;
  3. setTimeout(() => {
  4. debugger;
  5. console.log('world');
  6. }, 1000);
  7. console.log('hello');

调试器启动欧,在代码的第四行设置了一个断点,所以程序执行会出现暂停:

  1. $ node debug myscript.js
  2. < debugger listening on port 5858
  3. connecting... ok
  4. break in /home/indutny/Code/git/indutny/myscript.js:1
  5. 1 x = 5;
  6. 2 setTimeout(() => {
  7. 3 debugger;
  8. debug> cont
  9. < hello
  10. break in /home/indutny/Code/git/indutny/myscript.js:3
  11. 1 x = 5;
  12. 2 setTimeout(() => {
  13. 3 debugger;
  14. 4 console.log('world');
  15. 5 }, 1000);
  16. debug> next
  17. break in /home/indutny/Code/git/indutny/myscript.js:4
  18. 2 setTimeout(() => {
  19. 3 debugger;
  20. 4 console.log('world');
  21. 5 }, 1000);
  22. 6 console.log('hello');
  23. debug> repl
  24. Press Ctrl + C to leave debug repl
  25. > x
  26. 5
  27. > 2+2
  28. 4
  29. debug> next
  30. < world
  31. break in /home/indutny/Code/git/indutny/myscript.js:5
  32. 3 debugger;
  33. 4 console.log('world');
  34. 5 }, 1000);
  35. 6 console.log('hello');
  36. 7
  37. debug> quit

通过 REPL 命令可以远程执行调试代码,其中 next 命令是单步调试命令,输入 help 可以查看完整的调试命令。

监视器

在调试过程中,可以同时监视表达式和变量的值。在每一处断点,监视器都会计算监视目标(表达式和变量)的值。输入 watch('my_expression') 即可监视表达式,输入 watchers 输出当前所有的监视器,输入 unwatch('my_expression') 对表达式取消监视。

命令

步进

  • contc,继续执行
  • nextn,单步执行
  • steps,step in
  • outo,step out
  • pause,暂停

断点

  • setBreakpoint()sb() -,当前行设置断点
  • setBreakpoint(line)sb(line),在 line 行设置断点
  • setBreakpoint('fn()')sb(...),在函数里的第一行设置断点
  • setBreakpoint('script.js', 1)sb(...),在脚本文件的第一行设置断点
  • clearBreakpoint('script.js', 1)cb(...),清除脚本文件第一行的断点

下面代码演示了如何在未加载的文件中设置断点:

  1. $ ./node debug test/fixtures/break-in-module/main.js
  2. < debugger listening on port 5858
  3. connecting to port 5858... ok
  4. break in test/fixtures/break-in-module/main.js:1
  5. 1 var mod = require('./mod.js');
  6. 2 mod.hello();
  7. 3 mod.hello();
  8. debug> setBreakpoint('mod.js', 23)
  9. Warning: script 'mod.js' was not loaded yet.
  10. 1 var mod = require('./mod.js');
  11. 2 mod.hello();
  12. 3 mod.hello();
  13. debug> c
  14. break in test/fixtures/break-in-module/mod.js:23
  15. 21
  16. 22 exports.hello = () => {
  17. 23 return 'hello from module';
  18. 24 };
  19. 25
  20. debug>

信息显示

  • backtracebt,显示当前执行帧的回溯信息
  • list(5),显示脚本代码的五行上下文,即 debugger; 之前的五行和之后的五行
  • watch(expr),添加对表达式 expr 的监视
  • unwatch(expr),移除对表达式 expr 的监视
  • watchers,显示所有的监视器和相应的值
  • repl,启动调试器的 REPL 环境,并使用调试脚本的上下文信息处理代码逻辑
  • exec expr,在脚本文件的上下文中调试表达式

执行控制

  • run,执行脚本(脚本在调试器启动时会自执行)
  • restart,重新执行脚本
  • kill,杀死正在执行的脚本

其他

  • scripts,显示已加载脚本的列表
  • version,显示 V8 的版本

高级用法

此外还有两种方式可以打开调试器:一种方法是使用 --debug 参数开启调试器,另一种方法是像 Node.js 进程传递 SIGUSR1 信号。

Node.js 进程使用上述方式进入调试模式后,可以使用 Node.js 的调试器通过 PID 或 URI 调试该进程:

  • node debug -p <pid>,通过 PID 连接到进程
  • node debug <URI>,- 通过类似 localhost:5858 的 URI 连接到进程