SSH与Mongoose环境下async()执行后程序不自动退出的问题及优化
为什么我的SSH+MongoDB脚本执行后无法自动退出?如何改进?
我写了一段JS脚本,用来通过SSH隧道连接MongoDB并创建文档,代码如下:
(async function run() { try { //connect to SSH server await tunnel(config) console.log(`connected ssh`) } catch (e) { console.log(e) } try{ //connect to mongodb mongoose.connect('mongodb://localhost:27000/china_macro'); var db = await mongoose.connection console.log(`connected DB`) } catch(e){console.log(e)} await mongooseModel.create({ year: 2015 }) console.log(`finish`) })().catch(e=>{console.log(e)})
执行完成后,程序不会自行退出,必须手动按Ctrl+C才能停止,请问这是什么原因?我可以对代码做哪些改进?
问题原因
这个问题我之前也碰到过,核心是你的脚本没有主动释放持有的资源,导致Node.js的事件循环中还有活跃任务,进程没法自动终止:
- MongoDB长连接未关闭:Mongoose默认会维持数据库长连接,哪怕完成了文档创建,连接依然处于打开状态,占用着事件循环资源。
- SSH隧道未主动终止:你建立的SSH隧道在完成操作后没有被关闭,这个持续的连接也会阻止进程退出。
改进方案
你需要在所有业务操作完成后,主动关闭MongoDB连接和SSH隧道,让Node.js事件循环清空,从而自动退出进程。具体修改步骤如下:
- 保存SSH隧道实例:把
tunnel返回的实例存下来,方便后续调用关闭方法。 - 关闭MongoDB连接:在文档创建完成后,调用
mongoose.disconnect()关闭所有Mongoose连接。 - 关闭SSH隧道:调用隧道实例的
close()方法(不同SSH库可能命名略有差异,比如destroy())终止隧道连接。 - 统一错误处理:确保错误场景下也能释放资源,避免资源泄漏。
修改后的完整代码
(async function run() { let sshTunnel = null; try { // 保存SSH隧道实例,用于后续关闭 sshTunnel = await tunnel(config); console.log(`connected ssh`); // 直接await mongoose.connect的Promise,比等待connection对象更可靠 await mongoose.connect('mongodb://localhost:27000/china_macro'); console.log(`connected DB`); // 创建目标文档 await mongooseModel.create({ year: 2015 }); console.log(`finish`); // 先关闭MongoDB连接 await mongoose.disconnect(); console.log(`disconnected DB`); // 再关闭SSH隧道 if (sshTunnel) { // 若你的SSH库关闭方法不是Promise,需要包装成Promise确保异步完成 await sshTunnel.close(); console.log(`closed ssh tunnel`); } } catch (e) { console.error('Error occurred:', e); // 错误场景下也要尝试清理资源 try { await mongoose.disconnect(); if (sshTunnel) await sshTunnel.close(); } catch (cleanupErr) { console.error('Cleanup error:', cleanupErr); } } })().catch(e => console.error('Top-level error:', e));
额外提示
- 如果你使用的SSH隧道库(比如
tunnel-ssh)的关闭方法不返回Promise,记得用new Promise包装一下,确保等待关闭操作完成后再让进程退出。 - Mongoose的
connect方法本身就返回Promise,直接await这个方法比监听connection对象的状态更简洁可靠。
内容的提问来源于stack exchange,提问作者Franci
相关产品推荐
相关产品推荐

