【问题标题】:Execute multiple commands for multiple devices using ssh2shell node.js使用 ssh2shell node.js 为多个设备执行多个命令
【发布时间】:2021-05-01 13:46:02
【问题描述】:

在我的项目中,我有一组设备 ip 和一组命令。 我需要为每个设备打开新的 ssh shell,它在同一个 shell 中执行所有命令,所以它不会为每个命令打开新连接,这就是我使用 ssh2shell 包的原因。

问题是我需要等待所有这些都结束,并且它需要是异步的,所以它不会在开始与其他设备的会话之前等待每个 ip 的回答。在获得所有响应后,它将所有数据保存在某个数组中,该数组中的每个单元格都代表一个 ip 响应。

我知道它需要使用asyncawaitPromise,但我没有成功管理它。

主要代码:

function monitorDevices() {
    
    const DEVICES_IPS = [ "10.10.10.1", "20.20.20.1", "30.30.30.1" ];
    const COMMANDS    = [ "cat /var/log/messages", "cat /proc/stat", "df -h /var/log", "free -t -m" ];
    let data = [];
    DEVICES_IPS.forEach(device => {
       data.push(sshService.exec(device, COMMANDS));
    });

    console.log(data);

}

ssh服务代码:

function exec(device, commands) {

    var host = {
     server: {     
      host:      device,
      userName:  process.env.USERNAME,
      password:  process.env.PASSWORD,
     },
     commands:      commands
    };
     
    var SSH2Shell = require ('ssh2shell'),
      SSH = new SSH2Shell(host),
      callback = function(sessionText){
        // if I console.log(sessionText) here, it gives my a good result.
        return sessionText;
      }

    SSH.connect(callback);

}

谢谢!

【问题讨论】:

    标签: node.js asynchronous ssh async-await promise


    【解决方案1】:

    这就是我如何 Promise-wrap SSH2ShellSSH.connect -

    const SSH2Shell = require ('ssh2shell')
    
    function exec(device, commands) {
      const SSH = new SSH2Shell({ 
        server: {     
          host: device,
          userName: process.env.USERNAME,
          password: process.env.PASSWORD,
        },
        commands: commands
      })
      return new Promise(resolve => SSH.connect(resolve))
    }
    

    现在我们将monitorDevices 写为async 函数。只需遍历 devicesawaitsshService.execpush 即可得到 data 结果 -

    async function monitorDevices() {
      const devices =
        [ "10.10.10.1", "20.20.20.1", "30.30.30.1" ]
    
      const commands =
        [ "cat /var/log/messages", 
          "cat /proc/stat", 
          "df -h /var/log", 
          "free -t -m"
        ]
    
      const data = []
      for (const d of devices)
        data.push(await sshService.exec(d, commands))
      return data
    }
    

    要运行该函数,我们编写 -

    monitorDevices().then(console.log, console.error)
    

    我的建议是使monitorDevices 函数的devicescommands 参数-

    async function monitorDevices(devices, commands) {  // parameters
      const data = []
      for (const d of devices)
        data.push(await sshService.exec(d, commands))
      return data
    }
    

    现在它可以重复用于各种设备和命令 -

    monitorDevices
      ( [ "10.10.10.1", ... ]              // devices
      , [ "cat /var/log/messages",  ... ]  // commands
      )
      .then(console.log, console.error)
    

    最后,我们可能希望使我们的exec 函数更加健壮一些。我们可以通过连接到主机的onError 属性来添加一些错误处理 -

    function exec(device, commands) {
      return new Promise((resolve, reject) => 
        new SSH2Shell({ 
          server: {     
            host: device,
            userName: process.env.USERNAME,
            password: process.env.PASSWORD,
          },
          commands: commands,
          callback: resolve,    // <- resolve callback
          onError: reject       // <- reject error
        })
    }
    

    【讨论】:

    • 您好,首先谢谢您。其次,代码不起作用......它只给了我for循环中第一个设备的结果......我完全按照你的做法做了,除了最后一部分,因为 SSH.connect 不存在并且没有'不明白在哪里插入这个。你知道为什么它只适用于数组的第一个元素以及如何修复它吗?
    • 对不起,它不能完美运行 :( 我没有使用该模块,所以我基于 documentation for the module 的代码。SSH.connecthost.callback 配置的覆盖。如果它有效对于第一个设备,我无法想象为什么它不适用于其他设备。如果我以后有时间,我可以获取模块并尝试查找错误。如果您在此期间有任何进展,请告诉我.
    • 您的代码帮助我完成了另一个 SNMP 服务模块,所以这是件好事。关于 SSH 模块,仍然没有成功,但我还没有放弃;)感谢您的帮助!如果您确实有时间尝试一下该模块,那就太棒了。再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 2013-01-08
    相关资源
    最近更新 更多