231

我有这个简单的脚本:

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 显示这些消息?如果是怎么办?!

谢谢

4

9 回答 9

309

不要使用exec. 使用spawnwhich 是一个EventEmmiter对象。stdout然后,您可以在/ stderrevents( 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缓冲输出并通常在命令执行完成时返回它。

于 2012-04-19T16:15:28.510 回答
230

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

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

coffeeProcess.stdout.pipe(process.stdout);

或使用 spawn 继承 stdio

spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
于 2015-05-06T18:35:12.593 回答
89

已经有几个答案,但是没有一个提到最好(也是最简单)的方法,即 usingspawn{ stdio: 'inherit' }option。它似乎产生了最准确的输出,例如在显示来自git clone.

只需这样做:

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

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

感谢@MorganTouvreyQuilling 在此评论中指出这一点。

于 2017-04-18T16:15:23.603 回答
23

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

var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
于 2016-01-18T10:39:02.533 回答
21

我想补充一点,从生成的进程输出缓冲区字符串的一个小问题console.log()是它添加了换行符,这可以将生成的进程输出分散到其他行上。如果您输出stdoutor stderrwithprocess.stdout.write()而不是console.log(),那么您将“按原样”从生成的进程中获得控制台输出。

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

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

于 2014-07-29T11:54:27.117 回答
18

我发现向执行此操作的实用程序添加自定义 exec 脚本很有帮助。

实用程序.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())
  })
}

应用程序.js

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

exec('coffee -cw my_file.coffee')
于 2017-10-07T06:26:11.710 回答
5

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

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标题会出现一次。但这并不足以让我改变它。

于 2016-11-11T17:15:36.360 回答
3

child_process.spawn 返回一个带有 stdout 和 stderr 流的对象。您可以点击 stdout 流来读取子进程发送回 Node.js 的数据。作为流的标准输出具有流具有的“数据”、“结束”和其他事件。当您希望子进程将大量数据返回到 Node 时,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());
});
于 2018-05-15T07:06:37.140 回答
1

这是一个用 typescript 编写的异步辅助函数,似乎对我有用。我想这不适用于长期存在的过程,但对某人来说仍然很方便?

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})
        })
    })
}
于 2020-04-27T09:02:24.847 回答