【问题标题】:Nodejs ssh2 run multiple command only one terminalNodejs ssh2仅在一个终端上运行多个命令
【发布时间】:2014-09-17 08:00:19
【问题描述】:

我在项目中编写 ssh2 模块时遇到了麻烦。我试图在一个终端上运行多个命令来统治远程 Linux 系统。例如“bc”命令为您提供了一个基本的计算器,您可以运行它进行基本操作。但是这种进程在你使用时需要保持清醒(它会接受两个或更多输入,并会给出响应)。

我需要创建一个类似 websocket 和 ssh 的系统。当 websocket 接收到命令时,ssh 节点需要执行这个消息,并且 Module 需要通过 websocket.send() 发送它的响应

我正在使用 Node.js websocket,ssh2 客户端。

这是我的代码:

#!/usr/bin/node
var Connection = require('ssh2');
var conn = new Connection();

var command="";
var http = require('http');
var WebSocketServer = require('websocket').server;
var firstcom=true;
conn.on('ready', function() {
                console.log('Connection :: ready');
               // conn.shell(onShell);

            }); 

var onShell = function(err, stream) { 

                  //  stream.write(command+'\n');

                    stream.on('data', function(data) {
                        console.log('STDOUT: ' + data);
                    });

                    stream.stderr.on('data', function(data) {
                    console.log('STDERR: ' + data);

                   });

          }



var webSocketsServerPort=5000;
var ssh2ConnectionControl=false;

var server = http.createServer(function (req, res) {
  //blahbalh
}).listen(webSocketsServerPort, function() {
    console.log((new Date()) + " Server is listening on port:: " + webSocketsServerPort);
});

//console.log((new Date()) + 'server created');

wsServer = new WebSocketServer({
    httpServer: server,
 //   autoAcceptConnections: false
});

wsServer.on('request', function(request) {
    console.log((new Date()) + ' Connection from origin ' + request.origin + '.');
    var wsconnection = request.accept('echo-protocol', request.origin);
    console.log((new Date()) + ' Connection accepted.');

    if(!ssh2ConnectionControl){
      conn.connect({
                host: 'localhost',
                port: 22,
                username: 'attilaakinci',
                password: '1'
              });
      ssh2ConnectionControl=true;
        console.log('SSH Connected.');       
    } 

    wsconnection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
            command=message.utf8Data;

            //if(firstcom){
            //  conn.shell(onShell);
            //  firstcom=false;
            //}else{
              conn.exec(message.utf8Data,onShell);

            //}

            wsconnection.send(message.utf8Data);
        }
        else{
            console.log('Invalid message');
        }
    });

    wsconnection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + wsconnection.remoteAddress + ' disconnected.');
    });
});

【问题讨论】:

  • 这段代码在不同的shell上执行命令我在检查终端进程ID时意识到了这种情况。所以我失去了 ssh 连接的使用。我需要在同一个终端上执行它们。请帮我解决这个问题。非常感谢..

标签: javascript node.js shell ssh websocket


【解决方案1】:

这是一个老问题,但我想提供一种使用 sh2shell 的替代方法,它通过 mscdex 包装 ssh2.shell,上面使用过。下面的例子只涉及建立 ssh 连接、运行命令和处理结果。

使用 ssh2shel 可以在同一个 shell 会话中的先前命令的上下文中连续运行任意数量的命令,然后返回每个命令的输出(onCommandComplete 事件)和/或在断开连接时使用回调函数。 有关示例和大量信息,请参阅the ssh2shell readme。还有tested scripts 用于工作代码示例。

var host = {
    //ssh2.client.connect options
    server: {     
        host:         120.0.0.1,
        port:         22,
        userName:     username,
        password:     password
    },
    debug:          false,
    //array of commands run in the same session
    commands:       [
        "echo $(pwd)",
        command1,
        command2,
        command3
    ],      
    //process each command response
    onCommandComplete:   function( command, response, sshObj) {
        //handle just one command or do it for all of the each time
        if (command === "echo $(pwd)"){      
            this.emit("msg", response);
        }
    }
};

//host object can be defined earlier and host.commands = [....] set repeatedly later with each reconnection.

var SSH2Shell = require ('ssh2shell');

var SSH = new SSH2Shell(host),
    callback = function( sessionText ){
        console.log ( "-----Callback session text:\n" + sessionText);
        console.log ( "-----Callback end" );
    }

SSH.connect(callback)

要查看进程级别发生的情况,请将 debug 设置为 true。

【讨论】:

    【解决方案2】:

    如果你想要一个真正的交互式 shell,你应该使用 conn.shell() 而不是 conn.exec()conn.exec() 通常用于执行单行命令,因此它不会在 conn.exec() 调用之间保持“shell 状态”(例如工作目录等)。

    您还应该注意 SSH 服务器设置的可能限制,即每个连接允许多少并发 shell/exec 请求。我认为 OpenSSH 服务器上的默认限制是 10。

    【讨论】:

    • 我也试过这种方法。当我使用 shell 命令时,每个命令都会在不同的终端上执行,并且我会丢失正在进行的进程。我找到了一个解释,它说 shell 命令在服务器上启动了一个交互式 shell 会话。我需要在 一个 shell 会话 中执行此操作。 shell command explanation on github
    • 共享单个交互式 shell 会话的问题是您将混合来自其他 websocket 连接的输入/输出。这真的是你想要的吗?如果 websocket 消息不包含整个命令,这可能会导致问题。即使那样,您仍然可能会在输出中获得意外行为。
    • 对于bc 之类的东西,您可以保持conn.exec() 流与websocket 连接相关联,并继续写入和读取该流,因为bc 是一个交互式程序(直到您明确退出)。
    • 嗨 mscdex,我尝试了在我的远程 m/c 上运行此命令的提示 - "sudo su\nwhoami\n" 与 conn.shell。它开始在我的 nodejs 控制台上打印 shell 提示符(像这样 - [cloud-user@host-10-199-17-26 ~]$ ),这真的很丑陋,而且没有引发“结束”事件流.... 使用 conn.exec,流事件被正确引发,只是一个命令的更改对其他人不可见。
    • @MadhavanKumar 是的,这就是 ssh2 协议的本质,我对此无能为力。如果您只需要跟踪 cwd,您可以编写一个包装类,使用服务器上的 path 模块和/或 realpath 手动跟踪它。
    猜你喜欢
    • 2015-05-11
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    相关资源
    最近更新 更多