在 textarea 中显示 ssh2 标准输出和标准错误

Posted

技术标签:

【中文标题】在 textarea 中显示 ssh2 标准输出和标准错误【英文标题】:display ssh2 stdout and stderr in textarea 【发布时间】:2015-03-16 03:05:33 【问题描述】:

我正在构建一个 node.js 应用程序来管理服务器。 在这个应用程序中,我可以创建一些 shell 脚本并通过单击一个按钮在服务器上执行它们。

这是我的 routes.js 文件中用于此操作的内容:

app.get('/exec', isLoggedIn, function(req, res) 

  var url = require('url');
  var url_parts = url.parse(req.url, true);
  var query = url_parts.query;

  var Server         = require('../app/models/server');
  var Script         = require('../app/models/script');
  var async          = require('async');
  var scriptId       = query.scriptId;
  var userId         = query.userId;
  var serverId       = query.serverId;

  var stdout = "";
  var stderr = "";

  async.parallel(
    servers: function(callback)
      Server.find("_id" : serverId).exec(callback);
    ,
    scripts: function(callback)
      Script.find("_id" : scriptId).exec(callback);
    
  , function(err, results) 
    if (err)
      res.send(err);

      var selectedServer = results.servers;
      var selectedScript  = results.scripts;

      var serverIp       = selectedServer[0].serverDetails.serverAddress;
      var serverPort     = selectedServer[0].serverDetails.serverPort;
      var serverUsername = selectedServer[0].serverDetails.serverUsername;
      var scriptContent  = selectedScript[0].scriptDetails.scriptContent;

      var Connection   = require('ssh2');
      var conn         = new Connection();
      conn.on('ready', function() 
        //console.log('Connection :: ready');
        conn.exec(scriptContent, function(err, stream) 
          if (err) throw err;
          stream.on('exit', function(code, signal) 
            //console.log('Stream :: exit :: code: ' + code + ', signal: ' + signal);
          ).on('close', function() 
            //console.log('Stream :: close');
            conn.end();
          ).on('data', function(data_out) 
            console.log('STDOUT: \n' + data_out);
            stdout = stdout + data_out;
            res.render('execresults.ejs', 
              stdout : stdout
            );
          ).stderr.on('data', function(data_err) 
            console.log('STDERR: \n' + data_err);
          );
        );
      ).connect(
        host: serverIp,
        port: serverPort,
        username: serverUsername,
        privateKey: require('fs').readFileSync('id_rsa')
      );

      conn.on('error', function(e)  console.log("Connection failed or timed out"));

    );

  );

它工作正常,我在控制台中有执行结果。但我想在 ejs 页面的两个文本区域中显示 stdout 和 stderr 结果。

问题是当我运行像“uptime”这样的简单命令时,它可以工作,我的文本区域中会显示标准输出结果。

但是当 shell 脚本返回 stdout 和 stderr 时,或者如果 stdout 是大量文本,我认为由于这个错误,我没有将所有内容都传递到我的 ejs 页面:错误:不能发送后设置标题。

我的问题是:如何将 stdout 和 stderr 都发送到我的 ejs 页面,只有当脚本完全执行时?我试图通过连接所有标准输出输出来构建一个“标准输出”变量,但它似乎不起作用......

有人可以帮我吗?

非常感谢

【问题讨论】:

【参考方案1】:

假设进程最终自行结束并且不会输出大量数据,您可能只是缓冲数据,然后在进程关闭时渲染:

conn.exec(scriptContent, function(err, stream) 
  if (err)
    return res.send(err);

  var stdout = '',
      stderr = '';
  stream.on('close', function() 
    conn.end();
    res.render('execresults.ejs', 
      stdout: stdout,
      stderr: stderr
    );
  ).on('data', function(data) 
    stdout += data;
  ).stderr.on('data', function(data) 
    stderr += data;
  );
);

其次,

if (err)
  res.send(err);

真的应该有return:

if (err)
  return res.send(err);

以防止进一步执行错误。

【讨论】:

亲爱的 ssh2 创建者,非常感谢它完美运行 :) !我想问你一些事情:这种方式是在服务器上执行 shell 脚本的最佳方式,还是使用 sftp 上传脚本然后执行脚本更好?非常感谢! 我认为没有“最佳方式”,这完全取决于您的需求以及最适合您的方式。我的意思是,如果脚本不是静态的,那么我认为不值得进行上传,调用 exec,然后从服务器上删除文件。如果它是一个永远不会改变的脚本,那么只需上传一次并在 exec 中调用它可能会更有利,因为您传输的字节更少(但如果它是一个小脚本,可能对性能的影响可以忽略不计)。无论哪种方式,您都会得到相同的输出。

以上是关于在 textarea 中显示 ssh2 标准输出和标准错误的主要内容,如果未能解决你的问题,请参考以下文章

textarea

textarea 换行之间的转换

输出控制台(打印功能)到 Gui TextArea

Html—让textarea标签中的内容原格式输出的两种办法

textarea保持文本样式

将代码片段插入数据库并在 textarea 中以相同方式显示