Node.js生成子进程并实时获取终端输出
我有一个脚本,输出“hi”,休眠一秒钟,输出“hi”,休眠一秒钟,依此类推。现在我想我可以用这个模型来解决这个问题Node.js生成子进程并实时获取终端输出,node.js,spawn,capture-output,Node.js,Spawn,Capture Output,我有一个脚本,输出“hi”,休眠一秒钟,输出“hi”,休眠一秒钟,依此类推。现在我想我可以用这个模型来解决这个问题 var spawn = require('child_process').spawn, temp = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR'); temp.stdout.pipe(process.stdout); 现在的问题是,为了显示输出,需要完成任务。据我所知,这是因为新生成的进程具有执行控制权。显然node.j
var spawn = require('child_process').spawn,
temp = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR');
temp.stdout.pipe(process.stdout);
现在的问题是,为了显示输出,需要完成任务。据我所知,这是因为新生成的进程具有执行控制权。显然node.js不支持线程,所以有什么解决方案吗?我的想法是可能运行两个实例,第一个用于创建任务的特定目的,并让它将输出输送到第二个实例的进程,考虑到这是可以实现的。我仍然对Node.js感到困惑,但我有一些想法。首先,我认为您需要使用
execFile
而不是spawn
execFile
用于有脚本路径时,而spawn
用于执行Node.js可以根据系统路径解析的已知命令
1.要处理缓冲输出,请执行以下操作:
2.将侦听器添加到子进程的stdout()
此外,似乎还有一些选项可以让您从节点的控制终端分离生成的进程,这将允许它异步运行。我还没有对此进行测试,但在中有这样的例子:
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());
});
儿童:
家长:
require('child_process').fork('./childfile.js');
// fork'd children use the parent's stdio
现在容易多了(6年后)
Spawn返回一个childObject,然后您可以使用它侦听事件。活动包括:
- 类别:ChildProcess
- 事件:“错误”
- 事件:“退出”
- 事件:“关闭”
- 事件:“断开连接”
- 事件:“消息”
- 类别:ChildProcess
- child.stdin
- 童装
- child.stderr
- 童装
- child.pid
- 儿童网络
- child.kill([信号])
- 发送(消息[,发送句柄][,回调])
- child.disconnect()
var child_process = require('child_process');
console.log("Node Version: ", process.version);
run_script("ls", ["-l", "/home"], function(output, exit_code) {
console.log("Process Finished.");
console.log('closing code: ' + exit_code);
console.log('Full output of script: ',output);
});
console.log ("Continuing to do node things while the process runs at the same time...");
// This function will output the lines from the script
// AS is runs, AND will return the full combined output
// as well as exit code when it's done (using the callback).
function run_script(command, args, callback) {
console.log("Starting Process.");
var child = child_process.spawn(command, args);
var scriptOutput = "";
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
data=data.toString();
scriptOutput+=data;
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
console.log('stderr: ' + data);
data=data.toString();
scriptOutput+=data;
});
child.on('close', function(code) {
callback(scriptOutput,code);
});
}
使用上述方法,您可以将脚本的每一行输出发送到客户端(例如,当您在stdout
或stderr
上接收事件时,使用Socket.io发送每一行)
同步的
如果希望节点停止正在执行的操作并等待脚本完成,则可以使用同步版本:
(节点v0.11.12+)
此方法的问题:
- 如果脚本需要一段时间才能完成,服务器将挂起一段时间 这么长时间李>
- 标准输出只会在脚本启动后返回 已完成运行。因为它是同步的,所以无法继续 直到当前行完成。因此它无法捕获 “stdout”事件,直到繁殖行完成
var child_process = require('child_process');
var child = child_process.spawnSync("ls", ["-l", "/home"], { encoding : 'utf8' });
console.log("Process finished.");
if(child.error) {
console.log("ERROR: ",child.error);
}
console.log("stdout: ",child.stdout);
console.log("stderr: ",child.stderr);
console.log("exist code: ",child.status);
当我在子进程中生成npm时,从“npm install”命令获取日志输出时遇到了一些问题。依赖项的实时日志记录未显示在父控制台中 完成原始海报所需的最简单的方法似乎是这样(在windows上生成npm并将所有内容记录到父控制台):
我发现自己经常需要这个功能,所以我将它打包到一个名为的库中。它应该允许您执行命令并实时查看输出。要简单安装,请执行以下操作:
npm install std-pour
然后执行命令并实时查看输出就足够简单了:
const { pour } = require('std-pour');
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`));
它基于承诺,因此您可以链接多个命令。它甚至与函数签名兼容,因此无论您在哪里使用它,它都应该是一个方便的替代品。以下是我发现的最干净的方法:
require("child_process").spawn('bash', ['./script.sh'], {
cwd: process.cwd(),
detached: true,
stdio: "inherit"
});
为
exec
添加一个示例,因为我也需要实时反馈,直到脚本完成后才得到任何反馈exec
确实返回一个EventEmitter,这与许多声称只有spawn
才能以这种方式工作的说法相反
这更彻底地补充了我对公认答案的评论
exec的接口类似于spawn:
//包括
从“子进程”导入*作为子进程;//ES6语法
//定义
让exec=childProcess.exec;//使用“var”更恰当地表示
//语义,或“const”全部
//如果那是你的事;虽然“让”是
//忠实于范围;
//不过,返回一个EventEmitter来使用
//您也可以链接stdout:
//(即exec(…).stdout.on(…);)
让childProcess=exec
(
'./二进制命令--argument argumentValue',
(错误,标准输出,标准输出)=>
{//当流程完成时:
如果(错误)
{
log(`${error.name}:${error.message}`);
log(`[STACK]${error.STACK}`);
}
控制台日志(stdout);
控制台日志(stderr);
callback();//吞咽东西
}
);
现在只需为stdout
注册一个事件处理程序即可:
childProcess.stdout.on('data',data=>console.log(data));
对于stderr
:
childProcess.stderr.on('data',data=>console.log(`[ERROR]:${data}`));
您还可以管道标准输出到主进程的标准输出:
childProcess.stdou
var child_process = require('child_process');
var child = child_process.spawnSync("ls", ["-l", "/home"], { encoding : 'utf8' });
console.log("Process finished.");
if(child.error) {
console.log("ERROR: ",child.error);
}
console.log("stdout: ",child.stdout);
console.log("stderr: ",child.stderr);
console.log("exist code: ",child.status);
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');
});
npm install std-pour
const { pour } = require('std-pour');
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`));
require("child_process").spawn('bash', ['./script.sh'], {
cwd: process.cwd(),
detached: true,
stdio: "inherit"
});
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' })