执行:显示标准输出“直播”

时间:2012-04-19 16:07:25

标签: node.js coffeescript

我有这个简单的脚本:

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

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

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

18:05:59 - compiled my_file.coffee

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

由于

9 个答案:

答案 0 :(得分:214)

请勿使用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缓冲输出,通常在命令执行完毕后返回它。

答案 1 :(得分:132)

exec还将返回一个EventEmitter的ChildProcess对象。

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子进程的stdout到主stdout。

coffeeProcess.stdout.pipe(process.stdout);

OR使用spawn继承stdio

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

答案 2 :(得分:34)

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

只需这样做:

git clone

感谢@MorganTouvereyQuilling将其指向this comment

答案 3 :(得分:20)

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

我在这里看到了解决方案: Node.js: printing to console without a trailing newline?

希望能帮助某人使用上述解决方案(即使是来自文档,这对于实时输出也很有用)。

答案 4 :(得分:16)

受到Nathanael Smith的回答和Eric Freese的评论的启发,它可能很简单:

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

答案 5 :(得分:5)

我发现将自定义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')

答案 6 :(得分:4)

在审核了所有其他答案之后,我最终得到了这个:

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标题将针对多行显示一次。但这并不足以让我改变它。

答案 7 :(得分:1)

child_process.spawn返回带有stdout和stderr流的对象。 您可以点击stdout流来读取子进程发送回Node的数据。作为流的stdout具有“数据”,“结束”以及流具有的其他事件。当您希望子进程将大量数据返回到节点 - 图像处理,读取二进制数据等时,最好使用spawn。

所以你可以使用下面使用的child_process.spawn来解决你的问题。

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());
});

答案 8 :(得分:1)

这是一个用打字稿编写的异步帮助器函数,似乎对我有用。我猜想这对于长期存在的进程将不起作用,但对于某些人来说还是很方便的?

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})
        })
    })
}