blog
blog copied to clipboard
VSCode 调试 Egg 完美版 - 进化史
背景
VSCode 早期版本,对 Node Cluster 的调试支持一直不是很友好,譬如:
- 开发期重启进程后,不支持重新 attach。
- Cluster 重启后 debugPort 会自增,VSCode 也不支持 attach 新端口。
- Egg 的 多进程模型 多了 Agent 处理公关事务,在开发期也有 3 个进程(master, agent, worker)。
那些折腾过的历史
黑暗时代
早在 2016 年时就开始的折腾:#14 和 #15 ,没有太好的办法。
青铜时代
然后 @okoala 写了 egg-development-proxyworker
主要思路是在 agent 里面启动一个 socket proxy 来动态代理 worker 的调试端口。
很巧妙的解决了自动重启后调试端口变化问题,但缺点是要开发者手动安装插件,并配置 vscode。
此时只能说达到可用的阶段。
黄金时代
接着,我写了 egg-bin debug 把 proxy 功能内置了,实现原理参见当时的 RFC 提案
并且提供了 vscode-eggjs 扩展来方便配置。
解决了:
- 自动 attach 重启后的 worker 新端口
- 自动生成 launch.json
对于一般应用开发者基本上已经非常易用了,但还存在以下问题:
- vscode 的
launch.json对同时 attach 多个的支持不是很友好,虽然有compounds。 - 默认只 attach worker,并且不支持启动期的断点,如果要
brk的话要手动 attach 3 次,非常麻烦。
而今天,[email protected] 正式支持了 Automatically attach debugger to Node.js subprocesses
因此我们之前的做法可以大幅简化了,没解决的问题也基本解决了,可以称为 完美版 了。
完美版的人生
文档已经更新:使用 VSCode 进行调试
安装 vscode-eggjs,并初始化调试配置(如果之前有则需删除 launch.json 文件)

然后简单的一个 F5 搞定~
简析
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Egg",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "npm",
"windows": { "runtimeExecutable": "npm.cmd" },
// 启动我们的 egg-bin debug 并默认是 brk
"runtimeArgs": [ "run", "debug", "--", "--inspect-brk" ],
// 日志输出到 Terminal,否则启动期的日志看不到
"console": "integratedTerminal",
"protocol": "auto",
// 进程重启后自动 attach
"restart": true,
// 因为无需再 proxy,故改回原来的 9229 端口
"port": 9229,
// 自动 attach 子进程
"autoAttachChildProcesses": true
}
]
}
其他
vscode 扩展生成的配置里面,还支持了单元测试的断点,配置如下:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Egg Test",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"test-local",
"--",
"--inspect-brk"
],
"protocol": "auto",
"port": 9229,
"autoAttachChildProcesses": true,
"disableOptimisticBPs": false,
}
]
}
完美版.最终版1
VSCode 1.22 支持了 Automatically Attach to Node.js processes,也就是如果你开启了这个的话,无需配置什么 launch.json,直接在 terminal 执行 npm run debug --inspect-brk 就会自动 attach 了。
补充
Egg 的调试,跟 Node 没啥区别,因此一定要了解 Node 的基础调试知识。
其中,--inspect-brk 是指在进程第一行就暂停,等待 attach,因此:
- master 先启动,在第一行会停住,需要你 attach master,才会往下走
- 接着 master 启动 agent,也是在第一行停住,需要 attach agent 才会往下走
- 最后 agent 启动完成后,worker 才开始启动,一样也是在第一行停住,需要 attach agent 才会往下走
上面这几个 attach,由于上面我们提到的 VSCode 的支持,只需要开启配置,即可无感知的一键 attach。 虽然如此,但作为开发者,大家还是需要理解 Node 的调试原理。
TODO: 补充 egg cluster 背景,重启时消息流向图(messenger, debug)
+--------+
| Parent | (egg-scripts/egg-bin)
+--------+
|
|
v
+--------+ +-------+
| Master | --------> | Agent |
+--------+ +-------+
/ | \
/ | \
/ | \
v v v
+----------+ +----------+ +----------+
| Worker 1 | | Worker 2 | | Worker 3 |
+----------+ +----------+ +----------+
先删除原有的 .vscode 文件

在启动调试之前,我先需要执行npm run debug 吗?
不需要,你去看下 vscode 自己的调试指南就懂了
@atian25 我安装了 vscode-eggjs 在 DEBUG 模式,没有对应的 EGG 选项。
环境都是最新版的。

vscode 的激活时机好像有问题,你试下随便打开一个 js,输入下 egg

能看到这个的话,再回去调试页面看看
@atian25 EGG 选项出来了,但是 configurations 是空的。

那可能是 vscode 这块的 API 变了。 手动拷贝下我上面贴的 config 吧
npm run test-local 支持测试单个文件吗?
支持, npm run test-local -- --grep= 支持所有的 mocha 参数,可以看下 egg-bin 的 READM
或者 npx egg-bin test --grep=
VSCode 1.22 新增 Auto Attach 功能,在 Terminal 里面 npm run debug 后,会自动 attach,不需要你 F5 或上面那堆 launch.json 配置啥的
以Egg Debug启动的时候,会报This socket has been ended by the other party错误。昨天升级新vscode后出现的。
然而,先手动执行egg-bin debug,然后使用Egg Attach to remote,可以正常attach上去。
vscode 新版的 bug,暂时还没时间看,需要跟 vscode 那边反馈
vscode 新版无法调试,先手动执行egg-bin debug,然后使用Egg Attach to remote,虽然正常attach上去了,但是无法打断点。。。
@caohongtao 你是用的typescript吗?attach后能打断点吗?
几个月以来我都是用的下面这套配置,包括最近的ts版本,调试体验良好。
也试过最新的官方推荐配置和Auto Attach 方式,都不太好用。本着有保底的办法、外加偷懒的心态,也就没深究了😅。
这个配置其实就是之前某个版本的eggjs vscode插件的配置写法,有需要的同学可以参考一下,希望有帮助。
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Egg Debug",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"debug"
],
"console": "integratedTerminal",
"restart": true,
"protocol": "auto",
"port": 9999
},
{
"type": "node",
"request": "launch",
"name": "Egg Debug with brk",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"debug",
"--",
"--inspect-brk"
],
"protocol": "inspector",
"port": 9229
},
{
"type": "node",
"request": "launch",
"name": "Egg Test",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"test-local",
"--",
"--inspect-brk"
],
"protocol": "auto",
"port": 9229
},
{
"type": "node",
"request": "attach",
"name": "Egg Attach to remote",
"localRoot": "${workspaceRoot}",
"remoteRoot": "/usr/src/app",
"address": "localhost",
"protocol": "auto",
"port": 9999
}
]
}
赞,我这边好像需要 npm run debug,然后手动点击一下 Egg Attach to remote 才行
会出现

//----下面这个问题我也遇到了。。------------------------- 手动执行egg-bin debug,然后使用Egg Attach to remote,虽然正常attach上去了,但是无法打断点。。。
npm run debug,然后使用vscode Egg Attach to remote 可以。但是真的很容易断开啊,随便改的东西就需要重新执行
你连接 9999 端口就不会断了
等会 egg-cluster 这个 PR 合并发布后,就可以解决了。
vscode 最新版对 --debug-port 不再支持了,8.x 后换为 --inspect-port
PS: 最近较忙,其实这种问题,遇到的同学,提炼一个最小可复现案例,跟 vscode 一反馈,早就能解决了。 https://github.com/Microsoft/vscode/issues/49865 就这么简单。
--debug-port没找到在哪,我看了一下你提交给微软的那个链接,发现--debug-port是写在代码里的是吧?我也不确定,也不知道在哪改,然后只能用npm更新到最新的eggjs,启动调试后没有那个错误弹窗了,但是无法成功启动。我的sequelize初始化成功了,没更新egg前会在sequelize这些初始化前弹窗然后卡死。
PS G:\Nodejs Development\Project> cd 'g:\Nodejs Development\Project'; & 'C:\Program Files\nodejs\npm.cmd' 'run' 'debug' '--' '--inspect-brk'
[email protected] debug G:\Nodejs Development\Project egg-bin debug "--inspect-brk"
Debugger listening on ws://127.0.0.1:9229/97b90d18-5e76-4a7c-a9de-25d3d047b4d5 For help see https://nodejs.org/en/docs/inspector Debugger attached. 2018-05-16 14:16:51,847 INFO 22160 [master] node version v8.11.1 2018-05-16 14:16:51,850 INFO 22160 [master] egg version 2.8.1 Debugger listening on ws://127.0.0.1:5800/337d2144-61ce-4263-82d4-71cd9ae3ddfb For help see https://nodejs.org/en/docs/inspector Debugger attached. sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules\sequelize\lib\sequelize.js:242:13 2018-05-16 14:16:55,586 INFO 10620 [model] SELECT 1+1 AS result (7ms) 2018-05-16 14:16:55,589 INFO 22160 [master] agent_worker#1:10620 started (3730ms) Debugger listening on ws://127.0.0.1:9230/ea613009-c647-4a6f-98cf-d14d76c6746d For help see https://nodejs.org/en/docs/inspector 9230 opened Debug Proxy online, now you could attach to 9999 without worry about reload. DevTools → chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=tru e&ws=127.0.0.1:9999/ws_proxy Debugger attached. sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules\sequelize\lib\sequelize.js:242:13 2018-05-16 14:16:58,876 INFO 12060 [model] SELECT 1+1 AS result (0ms) 2018-05-16 14:16:59,856 ERROR 12060 nodejs.ECONNREFUSEDError: connect ECONNREFUSED 127.0.0.1:6379 at Object._errnoException (util.js:1022:11) at _exceptionWithHostPort (util.js:1044:20) at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1198:14) code: 'ECONNREFUSED' errno: 'ECONNREFUSED' syscall: 'connect' address: '127.0.0.1' port: 6379 name: 'ECONNREFUSEDError' pid: 12060 hostname: DESKTOP-6GQG52D // 然后一直重复 ECONNREFUSEDError
ECONNREFUSEDError 明显是你的数据库配置地址不对。
egg-cluster 已经发布了,升级安装下依赖即可
hey, please retry after reinstall dependencies and please never lock it.
$ # reinstall deps and never lock it.
$ rm -rf node_modules yarn.lock package-lock.json
$ npm i --no-package-lock
@atian25 非常感谢你及时的回复。sequelize没问题,原因是没开启redis服务o(╥﹏╥)o
请问,node_modules里的模块为什么有时候可以打断点,有时候不行?
@shiyun 是不是跟加载时机有关?如果你用最新的方式的话,应该是有 --inspect-brk 的,这样的话应该是可以断点到的。
@atian25 是用的最新的方式,用--inspect断点不到,后面改成--inspect-brk也样断点不到,问了好几个朋友都遇到这样的问题,没找到解决办法。 提示信息是: "未验证的断点,已设置断点但还未绑定"
@shiyun 你是用 cnpm 的么?刚跟 vscode 那边的人交流了,好像是软链方式会导致他们找不到,已经提 issue 待修复,着急的话先换回 npm
Updated: 如果要 debug 启动期的代码,换回 npm 方式即可。
https://github.com/Microsoft/vscode/issues/51588
调试配置里面 没有egg ,在js里输入egg,再去调试配置里就有了,但是生成的config为空,npm run debug后没有自动attach,环境: vscode: 1.25.1 os: macos10.13.6 yarn: 1.5.1 node: 10.7.0 typescript: 3.0.1
@yuu2lee4 直接复制文档中那段即可
刚安装的,debug配置项里没有egg,js里输入egg也没有任何的关联。。然后把vs安装了最新版,还是没有用,需要配置什么吗?
~ 试了下,js里还是没有开启联想,但是选择node的debug环境并手动复制config进去,还是可以跑。 那这个插件好像跟没装一样了。。
vscode同时起两个egg调试服务的时候,9229端口会冲突啊,我改了端口,没有用?
@galleonsZcc 你先直接拷贝文档里面的就好了,vscode 那边升级了,旧的方式不行了,我晚点修复下。
@dryqiao 你要改两个的,一个是 npm run debug -- --inspect-brk=端口号,然后再改那个 port 的。(一个是告诉 node 在指定端口调试,一个是告诉 vscode 去连接这个端口)
谢谢@StephenSeraph ,你的代码Egg Debug配置有效,Egg Debug with brk配置和当前版本的vscode-eggjs配置一样,用不了。是vscode的bug?
请教请教大神@atian25 些问题, 1.vscode-eggjs生成的配置runtimeArgs里,"--" 是什么,空的参数吗 2.另外看到brk的解释是:Break before user code starts,这种说的是什么使用场景 3.attach和launch的使用场景也不理解,何种情况使用哪种 4.我看启动后的log很多,但看不懂是什么意思,是不是启动成功了,或者是否按照想要的方式启动的也不能判断,能帮忙解释下log吗(前两天用vscode-eggjs的默认配置启动debug总是失败,但没有失败提示)
@IEfucker
vscode-eggjs生成的配置runtimeArgs里,"--" 是什么,空的参数吗
看我这篇回答: https://www.zhihu.com/question/267095526/answer/318608937
attach和launch的使用场景也不理解,何种情况使用哪种
debug 其实是 2 个操作:
- 给程序传参,告诉它开启一个端口,等到被调试
- 调试器(devtools,vscode)去 attach 这个端口,从而通过 protocol 告诉程序,要在哪些地方断点。
另外看到brk的解释是:Break before user code starts,这种说的是什么使用场景
指的是在 Node 的第一行就断点,而不是等开发者 attach,也就是上面那个问题合成一步,从而可以断点到两步之间的一些逻辑。
vscode同时起两个egg调试服务的时候,9229端口会冲突啊,我改了端口,没有用?
@galleonsZcc 你先直接拷贝文档里面的就好了,vscode 那边升级了,旧的方式不行了,我晚点修复下。
@dryqiao 你要改两个的,一个是
npm run debug -- --inspect-brk=端口号,然后再改那个 port 的。(一个是告诉 node 在指定端口调试,一个是告诉 vscode 去连接这个端口)
同时修改两个端口后,又会报Starting inspector on 127.0.0.1:5800 failed: address already in use
https://github.com/eggjs/egg-cluster/blob/master/lib/master.js#L191
配置下环境变量
@atian25 感谢提供配置,可以在vscode调试eggjs了,vscode用的最新版1.28.2
package.json 增加
"scripts": {
"debug": "egg-bin debug"
}
launch.json在configurations里增加
{
"name": "Launch Egg",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "npm",
"windows": { "runtimeExecutable": "npm.cmd" },
// 启动我们的 egg-bin debug 并默认是 brk
"runtimeArgs": [ "run", "debug", "--", "--inspect-brk" ],
// 日志输出到 Terminal,否则启动期的日志看不到
"console": "integratedTerminal",
"protocol": "auto",
// 进程重启后自动 attach
"restart": true,
// 因为无需再 proxy,故改回原来的 9229 端口
"port": 9229,
// 自动 attach 子进程
"autoAttachChildProcesses": true
}
感谢提供调试配置。
我试了一下利用 ts + egg.js 的组合,然后只需要简单npm run debug 命令就行。再简单一点就是按 npm-scripts里面的 debug,达到一键开始 debug 之旅。
请问在WSL里执行 npm run debug,再通过 chrome devtools 调试有试过吗?我遇到的问题是无法命中egg项目里自己写的代码的断点。chrome 70, egg 2.10.0, node 10.5.0
按我的判断跟 egg 本身关系不大。这种只能自己排查,跟环境有关。但只要你对 devtools 断点有理解,一般查起来很快。
- 试着删除目录,再重新安装依赖,不要锁版本。
hey, please retry after reinstall dependencies and please never lock it.
$ # reinstall deps and never lock it.
$ rm -rf node_modules yarn.lock package-lock.json
$ npm i --no-package-lock
-
然后看下 debug 的日志输出,看看 debug 端口都是哪几个
-
然后你的 chrome devtool 去 attach 这几个看看。(或者用 vscode 的 attach 功能试试)
@shiyun node_modules 里的模块 debugger 的问题你解决了吗?
今天vscode推送了1.32.1版本,升级以后Debug会卡住。去掉--inspect-brk可以启动成功,但无法打断点,报Breakpoint set but not yet bound。
—————————————— 手动打开auto attach解决了。
@mistypig 我无法复现。
另外,如果你不需要在启动期断点的话,其实可以不用加 --inspect-brk 的。
Version 1.32.1 (1.32.1)


@mistypig https://github.com/eggjs/egg/issues/3534#issuecomment-471857293
如何忽略进入node_module文件夹?
请大家务必务必注意,现在的调试,就是 Node 自己的多进程调试,egg 并没有做什么处理。所以,大部分的问题,需要你们了解 VSCode 和 Node 本身在调试这块的知识。
更新下最新的一些信息:
- 单元测试那个,需要加一个
"disableOptimisticBPs": false,才能正确的在 test 文件中断点。https://github.com/Microsoft/vscode/issues/37199 - WebStorm 2019 后, DEBUG_NODE_OPTIONS 这个变量丢失了,不过还是目前看来是不影响断点。
如何忽略进入node_module文件夹?
https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_skipping-uninteresting-code-node-chrome
请问在 win10 下,vscode 版本为1.34.0,在打开 autoAttach设置,使用 wsl 作为默认terminal的情况下,npm run debug --inspect-brk 可以在chrome里正常调试,好像没有 attach, 不能在vscode里调试,这个问题如何解决?
@whwnow 如果 autoAttach 开了但没有 attach,那就要找 VSCode 官方提 issue 了。
为何每次vscode debug egg项目,第一次打开都会停留在egg源码某个文件的'use strict'这一行
@Zuckonit 去掉 --inspect-brk,并阅读下正文最后一段,理解下 Node 的调试原理。
用了vscode的egg插件,配置默认带了--inspect-brk,或许这个不应该加到默认配置
@atian25 我找到解决方案了,在wsl中需要额外安装插件才可以 auto attach 。参考官方这个文档:https://code.visualstudio.com/docs/remote/wsl
@atian25 我找到解决方案了,在wsl中需要额外安装插件才可以 auto attach 。参考官方这个文档:https://code.visualstudio.com/docs/remote/wsl
喔,你说最新的那个 Remote Development 吧
对,是那个
vscode同时起两个egg调试服务的时候,9229端口会冲突啊,我改了端口,没有用?
@galleonsZcc 你先直接拷贝文档里面的就好了,vscode 那边升级了,旧的方式不行了,我晚点修复下。 @dryqiao 你要改两个的,一个是
npm run debug -- --inspect-brk=端口号,然后再改那个 port 的。(一个是告诉 node 在指定端口调试,一个是告诉 vscode 去连接这个端口)同时修改两个端口后,又会报Starting inspector on 127.0.0.1:5800 failed: address already in use
这个后来咋解决了?
有个环境变量,可以翻下 egg-cluster 的 master.js 源码搜下
vscode调试断点灰色的解决:
### 检查auto attach是否开启,最新版本vscode,1.42.1版本,开启auto attach后右下角显示
并且命令窗口下有

我这边最新版这个功能默认是个disable的状态,需要在设置中开启

开启后可以直接命令egg-bin debug开启调试,我觉得每次输入命令麻烦就还是用F5,launch.json配置如下,并且可以直接重启调试:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run", "debug"
],
"console": "integratedTerminal",
"protocol": "auto",
"port": 9229,
"restart": true
}
]
}
我可以用,大家可以试试可用否。