【问题标题】:How Node.js silently crashes without any information?Node.js 如何在没有任何信息的情况下静默崩溃?
【发布时间】:2020-01-20 18:35:35
【问题描述】:

应用程序在打开大量 SFTP 连接时静默死机。我使用各种process 事件处理程序,唯一触发的是process.on('exit',...

我正在为 SFTP ssh2-sftp-client 使用一个 npm 包,它在下面使用 ssh2 包。

这是一个最小的可重现代码

const Client = require('ssh2-sftp-client')
const inspect = require('util').inspect

const sftpClient = new Client();

sftpClient.on('error', (err) => {
  console.log('SFTP client emitted ERROR: ' + inspect(err))
})
sftpClient.on('end', () => {
  console.log('SFTP client emitted END')
})
sftpClient.on('finish', () => {
  console.log('SFTP client emitted FINISH')
})
sftpClient.on('close', () => {
  console.log('SFTP client emitted CLOSE')
})

const options = {
  host: '',
  port: '22',
  username: '',
  password: ''
};

// below infinite loop is to simulate large number of 
// connections in my production code
(async () => {
  while (true) {
    try {
      await new Promise(resolve => setTimeout(() => resolve(sftpClient.connect(options)), 1000))
    } catch {
      console.log('boom')
    }
  }
})()

process.on('exit', code => console.log(`Catched!. Exit code: ${code}`))

process.on('uncaughtException', (err, origin) => {
  console.error('Unhandled exception. Please handle!', err.stack || err)
  console.error(`Origin: ${JSON.stringify(origin)}`)
})

process.on('unhandledRejection', (err, promise) => {
  console.error('Unhandled promise rejection. Please handle!', promise, err.stack || err)
})

process.on('warning', (warning) => {
  console.warn(warning.name)
  console.warn(warning.message)
  console.warn(warning.stack)
})

process.on('rejectionHandled', (promise) => {
  console.log('rejectionHandled event triggered')
})

如您所见,除非出现错误,否则它不应逃脱无限循环。 事实上,它在某些迭代中不会,但最终它会逃脱 (通常在 。我看到的唯一日志是

SFTP client emitted END
Catched!. Exit code: 0

在 SFTP 服务器端,sshd_config 文件存在以下限制

MaxSessions 1
MaxStartups 1

我正在使用:

  • Node.js 12
  • ssh2-sftp-client 4.1.0

简而言之,问题:

Node 如何在没有任何错误事件/堆栈跟踪和退出代码 0 的情况下崩溃?

更新 #1

在 cmets 中建议对进程进行核心转储并对其进行分析。

如何在退出代码 0 上进行核心转储?

如果我进行核心转储,我应该在那里寻找什么?

更新 #2

在存储库中创建了一个问题 https://github.com/theophilusx/ssh2-sftp-client/issues/168

【问题讨论】:

  • 你想用那个循环来完成什么?这看起来不正确。
  • 我有一个应用程序以同样的方式死掉。当然,在那个应用程序中,我关闭了我打开的内容。此代码是该问题的最小可重现示例。这样任何人都可以复制代码,运行它并查看问题。
  • @TudorConstantin 这正是我正在经历的。但是在 Node.js 12 和最新版本的包上。将此信息添加到问题中。谢谢你的问题。
  • 看看 ssh2 js 模块中的this code section。在您安装的版本中添加一些额外的消息,看看这是否是崩溃源...
  • @Liam 23 cmets,因为没有人可以回答。这不会使问题过于宽泛。

标签: javascript node.js asynchronous sftp ssh-tunnel


【解决方案1】:

此特定问题是由远程服务器断开 TCP 连接和 SSH2 库仅引发“结束”事件而没有“错误”事件的组合引起的。这已被标记为 ssh2 中的错误,并列在该模块的问题中。

与此同时,已向 ssh2-sftp-client 添加了解决方法。本质上,在连接阶段添加了一个额外的“结束”侦听器,如果引发结束事件,这将导致连接承诺被拒绝。该软件包的新版本 (v4.2.0) 已发布,其中包含此修复。

关于背景信息 - 追踪此问题时难以获得一致结果的部分原因是由于许多 SFTP 服务器(如 openSSH)的 MaxStartups 设置。此设置可以是 max:drop:full 形式的元组,其中 max 是允许的未经身份验证的最大连接数(尚未完成握手和身份验证过程的连接), drop - 在达到最大值并已满后开始丢弃的连接百分比= 开始丢弃所有连接尝试的未经身份验证的连接数。默认值通常是 10:30:60,这意味着允许 10 个未经身份验证的连接,一旦超过 10 个就开始丢弃其中的 30%,一旦出现 60 个未经身份验证的连接,则丢弃所有尝试。 drop 值意味着一旦存在超过 10 个未经身份验证的连接,尝试将有 30% 的时间被丢弃,这会产生一个有点随机的结果,即每次运行测试时,可能会丢弃不同的连接。服务器通常会在不提供任何附加信息的情况下断开连接 - 您可能会或可能不会因对等错误而重置,这取决于服务器如何进行丢弃(通常,您只收到结束事件,仅此而已 - 不会引发错误) .

【讨论】:

    猜你喜欢
    • 2016-03-19
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2016-05-23
    • 2014-10-30
    相关资源
    最近更新 更多