我有一个脚本输出'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不支持线程所以任何解决方案?我的想法是可能运行两个实例,第一个用于创建任务的特定目的,并将输出传输到第二个实例的进程,考虑到这可以实现。
答案 0 :(得分:86)
现在(2年后)更容易了!
Spawn返回 childObject ,然后您可以侦听事件。事件是:
还有一堆来自childObject的对象,它们是:
在此处查看有关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可以针对您的系统路径解析的已知命令。
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);
});
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