最近看 node 源码,记录一下怎么调试
Debugger 调试
Debugger 是 Node.js (当前版本 v12)自带的独立于运行进程之外的一个监听客户端,基于 v8 inspect 实现。
debugger 一个 node inspect myScript.js
可以看到 debugger 会起一个监听进程,默认情况下侦听 127.0.0.1:9229,并且有一个 uuid 标识。
debugger 相关命令:
cont
, c
: Continue execution next
, n
: Step next step
, s
: Step in out
, o
: Step out pause
: Pause running code (like pause button in Developer Tools)
如果代码执行完了可以用 debug>restart
重启脚本
run
: Run script (automatically runs on debugger’s start) restart
: Restart script kill
: Kill script
设置断点的方法
1、通过 debug>
提示符使用 setBreakpoint
( sb
) https://nodejs.org/api/debugger.html#debugger_breakpoints 函数:setBreakpoint(module_file_name, line_number)
。
2、代码中加 debugger
获取所有断点
清除断点
查看变量值
watch 变量 watch('expr')
, expr 是变量名,watch 接收参数 字符串
修改变量值
vscode 调试
原理还是先运行node进程,再使用 VS Code 去连接 Node 进程,具体做法可以通过在 vscode中添加一个 launch.json 文件
https://code.visualstudio.com/docs/editor/debugging
https://code.visualstudio.com/docs/nodejs/nodejs-debugging
node --inspect myScript.js
注意是 **--inspect
**
打开 Chrome 并在地址栏中输入 about:inspect
chrome devtool 没法调 worker threads。调 worker threads 可以用 ndb
火焰图
speedscope
https://github.com/jlfwong/speedscope/wiki/Importing-from-Node.js
Nodejs 源码调试
首先看 build.md
,编译node debug版本的执行文件,因为发行版本的 node 是不支持调试的,所以我们需要自己通过源码构建一份可调试的 node
支持的平台(有多个级别)
- t1:包括所有测试的工具链,测试必须通过
- t2:包括所有测试的工具链,测试必须通过,工具链的 issue 必须修复才会发布
- Experimental:测试不通过不会阻碍发布
重点关注下:
Unix
gcc
and g++
>= 6.3 or newer, or - GNU Make 3.81 or newer
- Python (see note above)
- Python 2.7
- Python 3.5, 3.6, 3.7, and 3.8.
CentOS 下配好依赖
Mac
- Xcode Command Line Tools >= 10 for macOS
- Python (see note above)
- Python 2.7
- Python 3.5, 3.6, 3.7, and 3.8.
项目构建通过 make
进行管理,源码中已经有了 configure
文件
./configure --debug
之后会生成两份二进制文件 一分在 out/Release/node
一份在 out/Debug/node
为了方便构建,建了一个 debug-build.sh
并给他可执行的权限再执行:
mac 需要留下足够空间,编译构建比较耗资源,如果只执行 ./configure
(只生成 out/Release/node
)需要10g,./configure --debug
会干掉 20g (我的剩余空间从 39g 到 19g)
同时也比较耗时间。
build.md
说构建后给out目录下的 node 可执行文件设置 firewall rules,避免测试时不断弹出连接网络的提示,并可以在项目根目录下 创建 node 符号执行 。
但我还没遇到。
调试 js
创建一个用于调试的项目,随便写点,作为入口的:
用编译好的 node来执行:
会看到
然后打开 vscode
vscode 启动 debug 需要配置 launch.json, 其中 request 支持两种:
- launch: vscode 会打开这个程序然后进入调试,比较适合用 chrome dev tool 调
- attach:已经打开了程序,然后接通 node 的内部调试协议进行调试,比较适合用终端起
调试 c/c++ (libuv or v8)
vscode 需要先装好 c++ 插件
重新创建或添加 launch.json,type 选 cppdbg
调试总结
通过以上操作基本可以感觉到,无论哪种防范,调试思路都是一致的:
在 nodejs 侧启动一个 websocket 服务提供运行时信息,在用户调试侧再启动一个 websocket 服务客户端触发各种调试操作。两个 websocket 之间通过调试协议通信。
用 debugger 调试时,前面提到他是基于 v8-inspect 实现的,v8-inspect 的主要作用就是实现 inspect protocal 调试协议。
对源码调试时,通过 --inspect-brk
也是同样触发 v8-inspect, 实现调试协议。
而由于 v8 inspect 本身是从 chrome 中提取出来的,支持 chrome devtools protocal,所以可以通过 --inspect
触发 v8-inspect 在 chrome 上调试。