node.js Exec :显示标准输出“实时”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10232192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:34:19  来源:igfitidea点击:

Exec : display stdout "live"

node.jscoffeescript

提问by mravey

I have this simple script :

我有这个简单的脚本:

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

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

where I simply execute a command to compile a coffee-script file. But stdout never get displayed in the console, because the command never ends (because of the -w option of coffee). If I execute the command directly from the console I get message like this :

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

18:05:59 - compiled my_file.coffee

My question is : is it possible to display these messages with the node.js exec ? If yes how ? !

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

Thanks

谢谢

回答by Pooria Azimi

Don't use exec. Use spawnwhich is an EventEmmiterobject. Then you can listen to stdout/stderrevents (spawn.stdout.on('data',callback..)) as they happen.

不要使用exec. 使用spawnwhich 是一个EventEmmiter对象。然后您可以在stdout/ stderrevents( spawn.stdout.on('data',callback..))发生时收听它们

From NodeJS documentation:

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

execbuffers the output and usually returns it when the command has finished executing.

exec缓冲输出并通常在命令执行完成后返回它。

回答by Nathanael Smith

execwill also return a ChildProcess object that is an EventEmitter.

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 pipethe child process's stdout to the main stdout.

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

coffeeProcess.stdout.pipe(process.stdout);

OR inherit stdio using spawn

或使用 spawn 继承 stdio

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

回答by Livven

There are already several answers however none of them mention the best (and easiest) way to do this, which is using spawnand the { stdio: 'inherit' }option. It seems to produce the most accurate output, for example when displaying the progress information from a git clone.

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

Simply do this:

只需这样做:

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

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

Credit to @MorganTouvereyQuilling for pointing this out in this comment.

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

回答by Kevin Teljeur

I'd just like to add that one small issue with outputting the buffer strings from a spawned process with console.log()is that it adds newlines, which can spread your spawned process output over additional lines. If you output stdoutor stderrwith process.stdout.write()instead of console.log(), then you'll get the console output from the spawned process 'as is'.

我想补充一点,从生成的进程输出缓冲区字符串的一个小问题console.log()是它添加了换行符,这可以将生成的进程输出扩展到其他行。如果你的输出stdoutstderrprocess.stdout.write()替代的console.log(),那么你会得到从衍生进程“是”输出控制台。

I saw that solution here: Node.js: printing to console without a trailing newline?

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

Hope that helps someone using the solution above (which is a great one for live output, even if it is from the documentation).

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

回答by Tyler Long

Inspired by Nathanael Smith's answer and Eric Freese's comment, it could be as simple as:

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

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

回答by IanLancaster

I have found it helpful to add a custom exec script to my utilities that do this.

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

utilities.js

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

应用程序.js

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

exec('coffee -cw my_file.coffee')

回答by Tongfa

After reviewing all the other answers, I ended up with this:

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

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

Sometimes datawill be multiple lines, so the oldSchoolMakeBuildheader will appear once for multiple lines. But this didn't bother me enough to change it.

有时data会是多行,所以oldSchoolMakeBuild标题会为多行出现一次。但这并没有让我烦恼到足以改变它。

回答by Adeojo Emmanuel IMM

child_process.spawn returns an object with stdout and stderr streams. You can tap on the stdout stream to read data that the child process sends back to Node. stdout being a stream has the "data", "end", and other events that streams have. spawn is best used to when you want the child process to return a large amount of data to Node - image processing, reading binary data etc.

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

so you can solve your problem using child_process.spawn as used below.

所以你可以使用 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());
});

回答by Swaner

Here is an async helper function written in typescript that seems to do the trick for me. I guess this will not work for long-lived processes but still might be handy for someone?

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

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