如何从节点js服务器向客户端显示shell脚本的结果?

use*_*766 1 javascript browser shell node.js

我有一个节点js服务器,它触发我有的shell脚本.代码如下(简单的Hello World示例):

var http = require("http");    

function onRequest(request, response) {
    console.log("Request received.");
    response.writeHead(200, {"Content-Type": "text/plain"});

    var spawn = require('child_process').spawn;
    //executes my shell script - main.sh when a request is posted to the server
    var deploySh = spawn('sh', [ 'main.sh' ]);
    //This lines enables the script to output to the terminal
    deploySh.stdout.pipe(process.stdout);

    //Simple response to user whenever localhost:8888 is accessed
    response.write("Hello World");
    response.end();
}

http.createServer(onRequest).listen(8888);
console.log("Server has started.");
Run Code Online (Sandbox Code Playgroud)

代码工作正常 - 服务器启动,无论何时在浏览器中加载(请求)页面,shell脚本都在服务器上运行并在终端上输出结果.

现在,我想将结果显示回客户端浏览器而不是"Hello World".怎么做?请注意,脚本需要4-5秒才能执行并生成结果.

srq*_*inn 8

您有两种选择:

选项1:

转换您的函数以使用child_process.exec方法而不是child_process.spawn方法.这将缓冲发送到stdout内存中的所有数据,并允许您作为一个块发送到浏览器:

var http = require("http"),
    exec = require("child_process").exec;

function onRequest(request, response) {
  console.log("Request received.");
  response.writeHead(200, {"Content-Type": "text/plain"});

  //executes my shell script - main.sh when a request is posted to the server
  exec('sh main.sh', function (err, stdout, stderr) {
    if (err) handleError();

    //Print stdout/stderr to console
    console.log(stdout);
    console.log(stderr);

    //Simple response to user whenever localhost:8888 is accessed
    response.write(stdout);
    response.end();
  });
}

http.createServer(onRequest).listen(8888, function () {
  console.log("Server has started.");
});
Run Code Online (Sandbox Code Playgroud)

选项2:

如果要保留该child_process.spawn方法,则需要在堆栈中引入实时网络,以便在从子进程接收事件时将数据事件推送到浏览器.看一下socket.io或(推荐)SockJS,以便在服务器和客户端之间建立实时通信.

边注:

我想指出上面代码中的一个缺陷,从长远来看,这将最终伤害到你对节点的未来努力.

function onRequest(request, response) {
  console.log("Request received.");
  response.writeHead(200, {"Content-Type": "text/plain"});

  var spawn = require('child_process').spawn;
Run Code Online (Sandbox Code Playgroud)

在上面的最后一行中,您需要child_process在每个请求上使用该模块.这不仅会给每个请求增加不必要的开销,如果不小心,最终会遇到模块缓存问题.建议所有要求的调用都发生在模块范围的顶部而不是其他地方.在构建真正的同步CLI工具时,唯一一次"接受"需要在逻辑中间进行调用的是 - 但即便如此,最好将所有需求组织在模块范围的顶部以便于阅读.