执行:display stdout "live"

我有这样一个简单的脚本:

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


exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
console.log(stdout);
});

,我只是执行一个命令来编译一个咖啡脚本文件。但是stdout永远不会显示在控制台中,因为命令永远不会结束(因为coffee的-w选项)。 如果我直接从控制台执行命令,我会得到这样的消息:

18:05:59 - compiled my_file.coffee

我的问题是:是否可以用node.js的exec来显示这些消息?如果是,怎么做?!

谢谢

143396 次浏览

不要使用exec。使用spawn,它是一个EventEmmiter对象。然后你可以收听stdout/stderr事件(spawn.stdout.on('data',callback..)) 当它们发生时

来自NodeJS文档:

var spawn = require('child_process').spawn,
ls    = spawn('ls', ['-lh', '/usr']);


ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});


ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});


ls.on('exit', function (code) {
console.log('child process exited with code ' + code.toString());
});

exec缓冲输出,通常在命令执行完成时返回。

我只想补充一个小问题,从console.log()生成的进程中输出缓冲字符串,它添加了换行符,这可以将生成的进程输出扩展到其他行。如果你用process.stdout.write()而不是console.log()输出stdoutstderr,那么你将从派生进程'原样'获得控制台输出。

我在这里看到了解决方案: Node.js:打印到控制台没有末尾换行符? < / p >

希望这对使用上述解决方案的人有所帮助(对于实时输出来说,这是一个很好的解决方案,即使它来自文档)。

exec还将返回一个ChildProcess对象,它是一个EventEmitter对象。

var exec = require('child_process').exec;
var coffeeProcess = exec('coffee -cw my_file.coffee');


coffeeProcess.stdout.on('data', function(data) {
console.log(data);
});

OR pipe子进程的标准输出到主标准输出。

coffeeProcess.stdout.pipe(process.stdout);

或者使用衍生继承stdio

spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });

受到Nathanael Smith的回答和Eric Freese评论的启发,这个问题可以简单到:

var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);

在回顾了所有其他答案后,我得出了以下结论:

function oldSchoolMakeBuild(cb) {
var makeProcess = exec('make -C ./oldSchoolMakeBuild',
function (error, stdout, stderr) {
stderr && console.error(stderr);
cb(error);
});
makeProcess.stdout.on('data', function(data) {
process.stdout.write('oldSchoolMakeBuild: '+ data);
});
}

有时data将是多行,因此oldSchoolMakeBuild头文件将为多行出现一次。但这并没有困扰到我去改变它。

已经有几个答案,但没有一个提到最好(和最简单)的方法,这是使用spawn{ stdio: 'inherit' }选项。它似乎产生了最准确的输出,例如在显示git clone中的进度信息时。

简单地这样做:

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


spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });

感谢@MorganTouvereyQuilling在这样的评论中指出这一点。

我发现在我的实用程序中添加一个自定义的exec脚本很有帮助。

utilities.js

const { exec } = require('child_process')


module.exports.exec = (command) => {
const process = exec(command)


process.stdout.on('data', (data) => {
console.log('stdout: ' + data.toString())
})


process.stderr.on('data', (data) => {
console.log('stderr: ' + data.toString())
})


process.on('exit', (code) => {
console.log('child process exited with code ' + code.toString())
})
}

app.js

const { exec } = require('./utilities.js')


exec('coffee -cw my_file.coffee')
< p > child_process。Spawn返回一个带有标准输出和标准错误流的对象。 您可以点击标准输出流以读取子进程发送回Node的数据。Stdout是一个流,它有"data", "end"和其他流的事件。当你想让子进程返回大量的数据到Node -图像处理,读取二进制数据等时,spawn最适合使用

所以你可以使用child_process来解决你的问题。衍生如下所示。

var spawn = require('child_process').spawn,
ls = spawn('coffee -cw my_file.coffee');


ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});


ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});


ls.on('exit', function (code) {
console.log('code ' + code.toString());
});

下面是一个用typescript编写的async helper函数,它似乎对我有用。我猜这对长生命周期的过程不适用,但对某些人来说仍然很方便。

import * as child_process from "child_process";


private async spawn(command: string, args: string[]): Promise<{code: number | null, result: string}> {
return new Promise((resolve, reject) => {
const spawn = child_process.spawn(command, args)
let result: string
spawn.stdout.on('data', (data: any) => {
if (result) {
reject(Error('Helper function does not work for long lived proccess'))
}
result = data.toString()
})
spawn.stderr.on('data', (error: any) => {
reject(Error(error.toString()))
})
spawn.on('exit', code => {
resolve({code, result})
})
})
}