4

如何将子进程的无缓冲输出通过管道传输到 HTTP.ServerResponse?

下面的 Node.js 代码适用于缓冲输出,但不适用于无缓冲输出。

var http = require('http'),
    spawn = require('child_process').spawn;

http.createServer(function (req, res) {
    req.on('data', function (data) {
        var ping = spawn("ping", ["127.0.0.1"]);
        ping.stdout.pipe(res);
        ping.stderr.pipe(res);
        req.connection.on('end', function() {
            ping.kill();
        });
    });
});

这是来自的输出ping 127.0.0.1

ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1

由于ping将请求超时作为非缓冲数据写入 STDOUT,因此上面的代码仅在ping成功时才有效。

我正在使用 Node.js v0.8.19。

4

2 回答 2

5

这是一个常见的问题,不一定限于 Node.js。

如果您使用的是 Unix,则可以使用该unbuffer脚本,它是Expect的一部分。大多数 GNU 系统也提供stdbuf,它可以让你做同样的事情(尽管我承认对它不是很熟悉)。

如果要使用unbuffer,只需将上面的示例更改为:

var ping = spawn("unbuffer", ["ping", "127.0.0.1"]);

如果你在 Windows 上,事情就有点困难了,因为 Windows 本身并不提供任何与PTY. 诸如winpty(及其 JavaScript 绑定pty.js )之类的项目尝试使用Windows 控制台 API重新创建此功能,尽管我发现它们的实现有些错误和不完整。

ActiveState 的 win32 Expect 包不是最容易安装的东西,并且在默认发行版中不包含该unbuffer脚本。然而,如果你设法让一切正常工作并对 Unixunbuffer脚本进行一些小的修改,你应该能够编译一个unbuffer可执行文件,然后你可以从 Node.js 调用它。

于 2013-08-08T14:33:49.343 回答
0

您正在终止请求连接端的 ping 进程,这会在服务器上成功接收到请求后立即发生。ping 在它可以输出之前一直关闭Request timeout for icmp_seq 5

尝试做这样的事情

var http=require('http');
var spawn = require('child_process').spawn;
http.createServer(function (req, res) {
        var ping = spawn("ping", ["127.0.0.1","-c","20"]);
        ping.stdout.pipe(res);
        ping.stderr.pipe(res);
}).listen(8080);

注意: ping 永远持续,所以你不能等待它结束。使用 -c ping x 次。

于 2013-04-02T09:23:07.203 回答