使用child_process.execSync,但将输出保留在控制台中


160

我想使用execSync在NodeJS 0.12中添加的方法,但仍然在运行Node脚本的控制台窗口中具有输出。

例如,如果我运行具有以下行的NodeJS脚本,我想在控制台中看到rsync命令“ live”的完整输出:

require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"');

我知道这会execSync返回命令的输出,执行后我可以将其输出到控制台,但是这样我就没有“实时”输出了……

Answers:


324

如果需要的话,可以将父级的stdio传递给子进程

require('child_process').execSync(
    'rsync -avAXz --info=progress2 "/src" "/dest"',
    {stdio: 'inherit'}
);

3
这意味着子进程将使用父进程的stdin,stdout和stderr流。因此,当子进程写入其中任何一个时,它实际上将直接写入父进程的流中。
gregers 2015年

7
这是一个非常有价值的答案,因为官方文档并未真正明确预期的语法。
chikamichi 2015年

49
而不是[0,1,2]我使用过的'inherit',它等效于[process.stdin, process.stdout, process.stderr][0,1,2]文档使用
Kurt


2
@Booligoosh而不是简单地添加{stdio:'inherit'},您必须添加.toString(),然后手动调用console.log并显示结果。另外,它甚至不能满足看到“实时”命令输出的问题要求。我不认为它“简单得多”,实际上我认为它并不简单。
boileau

19

您可以简单地使用.toString()

var result = require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"').toString();
console.log(result);

这已经在Node上进行了测试v8.5.0,我不确定以前的版本。根据@etov,它不起作用v6.3.1-我不确定它们之间。


3
这在失败时不起作用(状态代码!= 0),因为.execSync()引发了一个Error实例。
阿尔瓦罗·冈萨雷斯

对我不起作用,即仅在命令完成后才写入输出。这是否适用于特定版本?我的节点-v:v6.3.1
etov

请考虑更新答案以注意它仅适用于某些节点版本-这将使其对其他节点更有用
etov

1
由于ti现在与命令执行期间有关输出问题的方式有关,因此请向下投票。
karfau

14

除非按照接受的答案建议重定向stdout和stderr,否则使用execSync或spawnSync无法实现。如果不重定向stdout和stderr,则这些命令仅在命令完成时返回stdout和stderr。

要做到这一点而无需重定向stdout和stderr,您将需要使用spawn来做到这一点,但这很简单:

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

//kick off process of listing files
var child = spawn('ls', ['-l', '/']);

//spit stdout to screen
child.stdout.on('data', function (data) {   process.stdout.write(data.toString());  });

//spit stderr to screen
child.stderr.on('data', function (data) {   process.stdout.write(data.toString());  });

child.on('close', function (code) { 
    console.log("Finished with code " + code);
});

我使用了ls命令,该命令以递归方式列出文件,以便您可以快速对其进行测试。Spawn将您要尝试运行的可执行文件名作为第一个参数,而作为第二个参数,它采用表示要传递给该可执行文件的每个参数的字符串数组。

但是,如果您设置使用execSync且由于某种原因而无法重定向stdout或stderr,则可以打开另一个终端(如xterm)并向其传递如下命令:

var execSync = require('child_process').execSync;

execSync("xterm -title RecursiveFileListing -e ls -latkR /");

这将使您看到命令在新终端中正在执行的操作,但仍具有同步调用。


2
使用spawn的示例可能是正确的,但是关于不打算使用execSync的开篇陈述并不正确。请参阅@gregers的答案
AgDude
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.