从Node.js运行shell命令而不缓冲输出

我试图从Node.js启动一个shell命令, 而不用redirect那个命令的input和输出,就像使用shell脚本或者使用Ruby的system命令来执行shell命令一样。 如果subprocess想写入STDOUT,我希望直接进入控制台(或者如果我的Node应用程序的输出被redirect了,那么会被redirect)。

节点似乎没有任何直接的方法来做到这一点。 看起来运行另一个进程的唯一方法是使用child_process ,它始终将subprocess的input和输出redirect到pipe道。 我可以编写代码来接受来自这些pipe道的数据,并将其写入到我的进程的STDOUT和STDERR,但是如果我这样做,这些API迫使我牺牲一些灵活性。

我想要两个function:

  • Shell语法。 我希望能够在命令之间输出输出,或者运行Windowsbatch file。
  • 无限输出。 如果我向一个编译器发出消息,并且想要产生兆字节的编译器警告,我希望它们全部在屏幕上滚动(直到用户厌倦它并点击Ctrl + C)。

它看起来像节点希望强迫我在这两个function之间进行select。

  • 如果我想要无限量的输出,我可以使用child_process.spawn ,然后执行child.stdout.on('data', function(data) { process.stdout.write(data); });stderr ,它会很乐意pipe数据直到牛回家。 不幸的是, spawn不支持shell语法。
  • 如果我想要shell语法,我可以使用child_process.exec 。 但exec坚持要cachingsubprocess的STDOUT和STDERR,最后把它们全部提供给我,并且限制了这些缓冲区的大小(可configuration,默认为200K)。 我仍然可以挂上on('data')事件,如果我想在输出生成时看到输出,但是exec仍然会将数据添加到它的缓冲区中。 当数据量超过预定义的缓冲区大小时, exec将终止subprocess。

(还有child_process.execFile ,从灵活性的angular度来看,这是两个世界中最糟糕的一点:没有shell语法,但是你仍然要限制你期望的输出量。

我错过了什么吗? 有没有什么方法可以在Node中向subprocess输出,而不是redirectinput和输出? 一些支持shell语法的东西,并且在预定义的输出量之后不会出错,就像在shell脚本,Ruby等中一样。

你可以通过spawn参数inheritancestdin / out / errorstream,所以你不需要手动pipe道它们:

 var spawn = require('child_process').spawn; spawn('ls', [], { stdio: 'inherit' }); 

使用shell的shell语法 – 为bash它的-c参数从string中读取脚本:

 var spawn = require('child_process').spawn; var shellSyntaxCommand = 'ls -l | grep test | wc -c'; spawn('sh', ['-c', shellSyntaxCommand], { stdio: 'inherit' }); 

总结:

 var spawn = require('child_process').spawn; function shspawn(command) { spawn('sh', ['-c', command], { stdio: 'inherit' }); } shspawn('ls -l | grep test | wc -c'); 

我没有使用它,但我已经看到这个库: https : //github.com/polotek/procstreams

你会这样做。 .out()自动pipe道到进程的stdin / out。

 var $p = require('procstreams'); $p('cat lines.txt').pipe('wc -l').out(); 

如果不支持shell语法,但我认为这是相当微不足道的。

 var command_str = "cat lines.txt | wc -l"; var cmds = command_str.split(/\s?\|\s?/); var cmd = $p(cmds.shift()); while(cmds.length) cmd = cmd.pipe(cmds.shift()); cmd .out() .on('exit', function() { // Do whatever }); 

你可以通过spawnreplaceexec ,并简单地使用shell语法:

 const {spawn} = require ('child_process'); const cmd = 'ls -l | grep test | wc -c'; const p = spawn (cmd, [], {shell: true}); p.stdout.on ('data', (data) => { console.log (data.toString ()); }); 

魔术只是{shell: true}

在child_process模块​​的节点文档中有一个例子:

分离长时间运行的进程并将其输出redirect到文件的示例:

  var fs = require('fs'), spawn = require('child_process').spawn, out = fs.openSync('./out.log', 'a'), err = fs.openSync('./out.log', 'a'); var child = spawn('prg', [], { detached: true, stdio: [ 'ignore', out, err ] }); child.unref();