如何调试Node.js中async_hooks的创建,排查进程崩溃问题
调试Node.js async_hooks挂起问题的方法
针对你遇到的FILEHANDLE关联async_hooks崩溃问题,以下是几种直接有效的调试手段,帮你定位挂起资源的源头:
用async_hooks模块手动追踪资源生命周期
直接利用Node.js内置的async_hooks模块,在异步资源初始化和销毁时记录调用栈,重点追踪FILEHANDLE类型的资源:const async_hooks = require('async_hooks'); const fs = require('fs'); const logPath = '/tmp/async_filehandle_trace.log'; // 清空日志文件(可选) fs.writeFileSync(logPath, ''); const hook = async_hooks.createHook({ init(asyncId, type, triggerAsyncId, resource) { if (type === 'FILEHANDLE') { const stack = new Error('FILEHANDLE created').stack; fs.appendFileSync(logPath, `[INIT] Async ID: ${asyncId}, Trigger ID: ${triggerAsyncId}\n${stack}\n\n`); } }, destroy(asyncId) { fs.appendFileSync(logPath, `[DESTROY] Async ID: ${asyncId}\n\n`); } }); hook.enable();运行程序后,对比日志中
[INIT]和[DESTROY]的记录,没有对应销毁记录的asyncId就是未释放的资源,其调用栈会直接告诉你创建源头。注意:这个方法会有一定性能开销,仅在调试环境使用。启用Node.js内置的异步资源追踪参数
启动Node.js时添加命令行参数,直接输出异步资源的创建/销毁日志:node --trace-async-resources your-app.js:打印所有异步资源的生命周期事件,过滤FILEHANDLE相关的输出即可找到对应创建栈。node --trace-sync-io your-app.js:如果问题是同步IO阻塞导致异步资源未释放,这个参数会记录所有同步IO操作,帮助定位阻塞点。
生成诊断报告获取崩溃上下文
让Node.js在崩溃时生成包含完整运行时信息的诊断报告:node --diagnostic-report-on-uncaught-exception your-app.js崩溃后会在当前目录生成一个
.json格式的诊断报告,其中async_hooks字段会列出所有活跃的异步资源,包括每个资源的类型、调用栈和关联信息,直接定位未释放的FILEHANDLE来源。用Chrome DevTools追踪异步栈
- 启动程序时开启调试:
node --inspect your-app.js - 打开Chrome浏览器访问
chrome://inspect,点击"Configure"添加本地调试端口(默认9229),然后连接到你的Node.js进程 - 在Sources面板的设置中开启Async stack traces选项
- 触发崩溃后,查看Call Stack面板,会显示异步操作的完整调用链,找到FILEHANDLE的创建源头
- 启动程序时开启调试:
排查文件句柄泄漏
因为错误明确关联FILEHANDLE,优先检查文件操作是否未正确关闭:- 在代码中定时调用
console.log(process.getActiveResourcesInfo()),查看活跃的FILEHANDLE数量和详情 - 用系统命令
lsof -p <你的进程PID>查看进程当前打开的所有文件句柄,排查是否有大量未关闭的文件(比如日志文件、临时文件)
- 在代码中定时调用
内容的提问来源于stack exchange,提问作者Gajus
相关产品推荐
相关产品推荐

