Exec : display stdout “live”

2019-01-08 03:12发布

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 :

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 ? !

Thanks

8条回答
看我几分像从前
2楼-- · 2019-01-08 03:58

Don't use exec. Use spawn which is an EventEmmiter object. Then you can listen to stdout/stderr events (spawn.stdout.on('data',callback..)) as they happen.

From NodeJS documentation:

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 buffers the output and usually returns it when the command has finished executing.

查看更多
爷、活的狠高调
3楼-- · 2019-01-08 03:59

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.

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

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());
});
查看更多
Summer. ? 凉城
4楼-- · 2019-01-08 04:03

There are already several answers however none of them mention the best (and easiest) way to do this, which is using spawn and the { stdio: 'inherit' } option. It seems to produce the most accurate output, for example when displaying the progress information from a 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.

查看更多
Explosion°爆炸
5楼-- · 2019-01-08 04:04

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 data will be multiple lines, so the oldSchoolMakeBuild header will appear once for multiple lines. But this didn't bother me enough to change it.

查看更多
Explosion°爆炸
6楼-- · 2019-01-08 04:08

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

var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
查看更多
一夜七次
7楼-- · 2019-01-08 04:08

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

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')
查看更多
登录 后发表回答