Node.js生成子进程并获得终端输出

时间:2013-01-15 07:09:46

标签: node.js spawn capture-output

我有一个脚本输出'hi',睡眠一秒,输出'hi',睡眠1秒,依此类推。现在我想我可以用这个模型解决这个问题。

var spawn = require('child_process').spawn,
temp    = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR');

temp.stdout.pipe(process.stdout);

现在的问题是需要完成任务才能显示输出。正如我所理解的那样,这是因为新生成的进程需要执行控制。显然node.js不支持线程所以任何解决方案?我的想法是可能运行两个实例,第一个用于创建任务的特定目的,并将输出传输到第二个实例的进程,考虑到这可以实现。

8 个答案:

答案 0 :(得分:86)

现在(2年后)更容易了!

Spawn返回 childObject ,然后您可以侦听事件。事件是:

  • 类:ChildProcess
    • 事件:'错误'
    • 事件:'退出'
    • 事件:'关闭'
    • 事件:'断开'
    • 事件:'消息'

还有一堆来自childObject的对象,它们是:

  • 类:ChildProcess
    • child.stdin
    • child.stdout
    • child.stderr
    • child.stdio
    • child.pid
    • child.connected
    • child.kill([信号])
    • child.send(message [,sendHandle] [,callback])
    • child.disconnect()

在此处查看有关childObject的更多信息:https://nodejs.org/api/child_process.html

所以,结合所有这些,你得到:

var spawn = require('child_process').spawn;
var child = spawn('node ./commands/server.js');
child.stdout.on('data', function(data) {
    console.log('stdout: ' + data);
    //Here is where the output goes
});
child.stderr.on('data', function(data) {
    console.log('stderr: ' + data);
    //Here is where the error output goes
});
child.on('close', function(code) {
    console.log('closing code: ' + code);
    //Here you can get the exit code of the script
});

这就是你如何通过Node获得输出!

答案 1 :(得分:70)

我还在尝试使用Node.js,但我有一些想法。首先,我认为您需要使用execFile而不是spawn; execFile用于获取脚本的路径,而spawn用于执行Node.js可以针对您的系统路径解析的已知命令。

1。 Provide a callback来处理缓冲的输出:

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], function(err, stdout, stderr) { 
    // Node.js will invoke this callback when the 
    console.log(stdout); 
});  

2。向子进程'stdout stream9thport.net

添加一个侦听器
var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3' ]); 
// use event hooks to provide a callback to execute when data are available: 
child.stdout.on('data', function(data) {
    console.log(data.toString()); 
});

此外,似乎有一些选项可以将生成的进程从Node的控制终端分离,从而允许它以异步方式运行。我还没有对此进行过测试,但API docs中有一些例子如下:

child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], { 
    // detachment and ignored stdin are the key here: 
    detached: true, 
    stdio: [ 'ignore', 1, 2 ]
}); 
// and unref() somehow disentangles the child's event loop from the parent's: 
child.unref(); 
child.stdout.on('data', function(data) {
    console.log(data.toString()); 
});

答案 2 :(得分:16)

这是我发现的最干净的方法:

require("child_process").spawn('bash', ['./script.sh'], {
  cwd: process.cwd(),
  detached: true,
  stdio: "inherit"
});

答案 3 :(得分:12)

我从" npm install"中获取日志输出时遇到了一些麻烦。我在子进程中生成npm时的命令。依赖项的实时日志记录未显示在父控制台中。

原始海报想要做的最简单的方法似乎是这个(在Windows上生成npm并将所有内容记录到父控制台):

var args = ['install'];

var options = {
    stdio: 'inherit' //feed all child process logging into parent process
};

var childProcess = spawn('npm.cmd', args, options);
childProcess.on('close', function(code) {
    process.stdout.write('"npm install" finished with code ' + code + '\n');
});

答案 4 :(得分:3)

类似PHP的passthru

import { spawn } from 'child_process';

export default async function passthru(exe, args, options) {
    return new Promise((resolve, reject) => {
        const env = Object.create(process.env);
        const child = spawn(exe, args, {
            ...options,
            env: {
                ...env,
                ...options.env,
            },
        });
        child.stdout.setEncoding('utf8');
        child.stderr.setEncoding('utf8');
        child.stdout.on('data', data => console.log(data));
        child.stderr.on('data', data => console.log(data));
        child.on('error', error => reject(error));
        child.on('close', exitCode => {
            console.log('Exit code:', exitCode);
            resolve(exitCode);
        });
    });
}

用法

const exitCode = await passthru('ls', ['-al'], { cwd: '/var/www/html' })

答案 5 :(得分:1)

子:

setInterval(function() {
    process.stdout.write("hi");
}, 1000); // or however else you want to run a timer

父:

require('child_process').fork('./childfile.js');
// fork'd children use the parent's stdio

答案 6 :(得分:0)

我发现自己经常需要此功能,因此我将其打包到名为std-pour的库中。它应该让您执行命令并实时查看输出。简单安装:

npm install std-pour

然后执行命令并实时查看输出非常简单:

const { pour } = require('std-pour');
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`));

它是基于承诺的,因此您可以链接多个命令。它甚至与child_process.spawn功能签名兼容,因此无论您在何处使用它都应该是替代品。

答案 7 :(得分:-1)

添加与child_process.exec相关的答案,因为我也需要实时反馈,直到脚本完成后才收到任何答案。这也补充了我对已接受答案的评论,但是因为格式化它会更容易理解和阅读。

基本上,我有一个调用Gulp的npm脚本,调用一个随后使用child_process.exec执行bash或批处理脚本的任务,具体取决于操作系统。两个脚本都通过Gulp运行构建过程,然后调用一些使用Gulp输出的二进制文件。

它与其他人(产卵等)完全一样,但为了完成,这里的确切方法如下:

// INCLUDES
import * as childProcess from 'child_process'; // ES6 Syntax


// GLOBALS
let exec = childProcess.exec; // Or use 'var' for more proper 
                              // semantics, though 'let' is 
                              // true-to-scope


// Assign exec to a variable, or chain stdout at the end of the call
// to exec - the choice, yours (i.e. exec( ... ).stdout.on( ... ); )
let childProcess = exec
(
    './binary command -- --argument argumentValue',
    ( error, stdout, stderr ) =>
    {
        if( error )
        {
            // This won't show up until the process completes:
            console.log( '[ERROR]: "' + error.name + '" - ' + error.message );
            console.log( '[STACK]: ' + error.stack );

            console.log( stdout );
            console.log( stderr );
            callback();            // Gulp stuff
            return;
        }

        // Neither will this:
        console.log( stdout );
        console.log( stderr );
        callback();                // Gulp stuff
    }
);

现在就像添加事件监听器一样简单。对于stdout

childProcess.stdout.on
(
    'data',
    ( data ) =>
    {
        // This will render 'live':
        console.log( '[STDOUT]: ' + data );
    }
);

对于stderr

childProcess.stderr.on
(
    'data',
    ( data ) =>
    {
        // This will render 'live' too:
        console.log( '[STDERR]: ' + data );
    }
);

一点也不差 - HTH