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

Joe*_*ite 53 child-process node.js

我正在尝试从Node.js启动一个shell命令,而不重定向该命令的输入和输出 - 就像使用shell脚本弹出命令或使用Ruby的system命令一样.如果子进程想要写入STDOUT,我希望它直接进入控制台(或重定向,如果我的Node应用程序的输出被重定向).

Node似乎没有任何直接的方法来做到这一点.看起来运行另一个进程的唯一方法是使用child_process,它总是将子进程的输入和输出重定向到管道.我可以编写代码来接受来自这些管道的数据并将其写入我的进程的STDOUT和STDERR,但是如果我这样做,API会迫使我牺牲一些灵活性.

我想要两个功能:

  • Shell语法.我希望能够在命令之间管道输出,或运行Windows批处理文件.
  • 无限输出.如果我正在向编译器进行shell并且它想要生成兆字节的编译器警告,我希望它们都能在屏幕上滚动(直到用户厌倦了它并按Ctrl + C).

看起来Node想强迫我在这两个功能之间做出选择.

  • 如果我想要无限量的输出,我可以使用child_process.spawn,然后做child.stdout.on('data', function(data) { process.stdout.write(data); });同样的事情stderr,并且它会愉快地管道数据,直到奶牛回家.不幸的是,spawn不支持shell语法.
  • 如果我想要shell语法,我可以使用child_process.exec.但是exec坚持要为我缓冲子进程的STDOUT和STDERR并最终将它们交给我,并且它限制了这些缓冲区的大小(可配置,默认为200K).我仍然可以挂钩on('data')事件,如果我想看到生成的输出,但exec仍然会将数据添加到其缓冲区.当数据量超过预定义的缓冲区大小时,exec将终止子进程.

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

我错过了什么吗?有没有办法在Node中弹出子进程,而不是重定向其输入和输出?支持shell语法并且在预定义的输出量之后不会丢失的东西,就像在shell脚本,Ruby等中可用的那样?

And*_*rov 42

您可以通过spawn参数继承stdin/out/error流,因此您无需手动管道它们:

var spawn = require('child_process').spawn;
spawn('ls', [], { stdio: 'inherit' });
Run Code Online (Sandbox Code Playgroud)

使用shell进行shell语法 - 对于bash它的-c参数从字符串中读取脚本:

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

总结一下:

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

shspawn('ls -l | grep test | wc -c');
Run Code Online (Sandbox Code Playgroud)


Sky*_*r13 7

您可以替换exec通过spawn与简单地使用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 ());
});
Run Code Online (Sandbox Code Playgroud)

魔术是正义的{shell: true}


log*_*yth 4

我没有使用过它,但我见过这个库:https://github.com/polotek/procstreams

如果你这样做的话。自动.out()通过管道连接到进程的标准输入/输出。

var $p = require('procstreams');
$p('cat lines.txt').pipe('wc -l').out();
Run Code Online (Sandbox Code Playgroud)

if 不支持 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
  });
Run Code Online (Sandbox Code Playgroud)

  • 我刚刚尝试了一下,它不支持 Windows 批处理文件,这确实是我想要 shell 支持的主要原因。许多最初的 Unix 工具(例如 Rake)都是在 Windows 上使用批处理文件实现的,我希望能够从 Node 调用它们。 (3认同)