我正在尝试使用节点核心的群集功能。
我希望stdout
和stderr
个流输出到一个文件,每个工作者ID一个。
类似于以下内容:
var fs = require('fs'),
env = process.env,
workerId = env.NODE_WORKER_ID || env.NODE_UNIQUE_ID;
process.stdout = fs.createWriteStream(__dirname + '/app#' + workerId + '.log', {
encoding: 'utf8'
});
不幸的是,似乎没有像这样重写process.stdout。
有没有办法实现这一目标,还是应该采取不同的方式?目前,当我运行我的集群时,我将从一个控制台中获取所有进程的所有输出,这非常混乱。
答案 0 :(得分:2)
我最终做了以下事情:
//create a new stdout file stream
var stdoutFS = fs.createWriteStream(stdoutFile, {
encoding: 'utf8',
flags : 'a+'
});
//create a new stderr file stream
var stderrFS = fs.createWriteStream(stderrFile, {
encoding: 'utf8',
flags : 'a+'
});
//pipe stdout to a worker file
var unhookStdout = hookWriteStream(stdout, function(string, encoding, fd) {
stdoutFS.write(string, encoding || 'utf8');
});
console.log('\n\nPrepared new stdout hook to worker file.');
//pipe stderr to a worker file
var unhookStderr = hookWriteStream(stderr, function(string, encoding, fd) {
stderrFS.write(string, encoding || 'utf8');
});
console.log('Prepared new stderr hook to worker file.');
//unhook when things go wrong
stdoutFS.once('close', function() {
unhookStdout();
console.log('Unhooked stdout.');
});
stdoutFS.once('error', function(err) {
unhookStdout();
console.error('Error: Unhooked stdout due to error %j.', err);
});
stderrFS.once('close', function() {
unhookStderr();
console.log('Unhooked stderr.');
});
stderrFS.once('error', function(err) {
unhookStderr();
console.error('Error: Unhooked stderr due to error %j.', err);
});
});
function hookWriteStream(stream, callback) {
var oldWrite = stream.write;
stream.write = (function(write) {
return function(string, encoding, fd) {
write.apply(stream, arguments);
callback(string, encoding, fd);
};
})(stream.write);
return function() {
stream.write = oldWrite;
};
}
它可能不是很优雅,但到目前为止这是我找到的最佳解决方案。
答案 1 :(得分:0)
看起来我的想法在某种程度上起作用。只要大多数日志记录使用console.log完成而不是直接写入stdout,你就会很好。
就像我在下面的评论中所说,使用这样的脚本:
fs = require 'fs'
{exec} = require 'child_process'
execAndPipe = (execString) ->
piper = exec execString
piper.stdout.on 'data', (data) ->
if data[0...'PROCESS'.length] == 'PROCESS'
# extract the worker ID and output
# to a corresponding file
piper.stderr.on 'data', (data) ->
if data[0...'PROCESS'.length] == 'PROCESS'
# extract the worker ID and output
# to a corresponding file
task 'run', 'Run the server', ->
execAndPipe 'node blah.js'
运行您的服务器。然后重新定义console.log,如:
console.log = function (d) {
process.stdout.write('PROCESS' + WORKERID + d + '\n');
};
我有点怀疑你是否能够直接重新加入stdout,所以这可能是你最好的选择之一。
如果您不想在ALL处输出任何内容,您可以重新绑定console.log,如:
console.log = function (d) {
var str = fs.createWriteStream(__dirname + '/app#' + workerId + '.log', {
encoding: 'utf8'
});
process.stdout.pipe(str);
};
忘了外部脚本。