You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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事件循环清空,从而自动退出进程。具体修改步骤如下:

  1. 保存SSH隧道实例:把tunnel返回的实例存下来,方便后续调用关闭方法。
  2. 关闭MongoDB连接:在文档创建完成后,调用mongoose.disconnect()关闭所有Mongoose连接。
  3. 关闭SSH隧道:调用隧道实例的close()方法(不同SSH库可能命名略有差异,比如destroy())终止隧道连接。
  4. 统一错误处理:确保错误场景下也能释放资源,避免资源泄漏。

修改后的完整代码

(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:31:40