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

fok*_*int 86 spawn node.js 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);
Run Code Online (Sandbox Code Playgroud)

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

Kat*_*tie 104

现在(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');

// You can also use a variable to save the output 
// for when the script closes later
var scriptOutput = "";

child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
    //Here is where the output goes

    console.log('stdout: ' + data);

    data=data.toString();
    scriptOutput+=data;
});

child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
    //Here is where the error output goes

    console.log('stderr: ' + data);

    data=data.toString();
    scriptOutput+=data;
});

child.on('close', function(code) {
    //Here you can get the exit code of the script

    console.log('closing code: ' + code);

    console.log('Full output of script: ',scriptOutput);
});
Run Code Online (Sandbox Code Playgroud)

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

  • +1,现在应该选择正确的答案.请注意,回调中的数据变量以Buffer对象的形式出现.如果你想要utf8字符串,你可以使用```child.stdout.setEncoding('utf8')```. (10认同)
  • 如果您需要异步地从`stdout`中获取信息,也就是说,如果其余程序继续运行,则该过程将无效。 (2认同)
  • 嘿@ChristianHujer!我更新了我的答案以包括异步和同步:D (2认同)

Rub*_*ONO 76

我还在尝试使用Node.js,但我有一些想法.首先,我相信你需要用execFile而不是spawn; execFile当你有脚本的路径时,spawn是为了执行一个众所周知的命令,Node.js可以解决你的系统路径.

1. 提供回调以处理缓冲输出:

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

2.向子进程'stdout (9thport.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()); 
});
Run Code Online (Sandbox Code Playgroud)

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

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()); 
});
Run Code Online (Sandbox Code Playgroud)

  • 如果您可以解释如何使用exec()执行此操作,则需要执行shell cmd. (7认同)
  • 您还可以使用`child.stdout.pipe(process.stdout);将child.stdout直接传递给process.stdout; (4认同)
  • 您可以使用`child.spawn()`并将`shell`选项设置为`true`.https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options (2认同)

Har*_*wal 20

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

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

  • 到底在做什么?为什么行得通?为什么这是一种更清洁的方法? (2认同)

小智 15

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

做原始海报想要的最简单的方法似乎是这个(在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');
});
Run Code Online (Sandbox Code Playgroud)


小智 9

类似 PHP 的通道

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);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

用法

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