1

ノードコアのクラスター機能を使用しようとしています。

stdoutstderrストリームを、ワーカーIDごとに1つずつファイルに出力したいと思います。

次のようなもの:

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を書き換えているようには見えません。

これを達成する方法はありますか、それとも別の方法で行う必要がありますか?現在、クラスターを実行すると、1つのコンソールですべてのプロセスからすべての出力を取得していますが、これは非常に面倒です。

4

2 に答える 2

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;
    };
}

あまりエレガントではないかもしれませんが、これまでのところ、これが私が見つけた最良の解決策です。

于 2012-05-27T20:08:09.030 に答える
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を直接再バインドできるとは思えないので、これが最善の選択肢の1つかもしれません。

コンソールに何も出力したくない場合は、次のようにconsole.logを再バインドできます。

console.log = function (d) {
    var str = fs.createWriteStream(__dirname + '/app#' + workerId + '.log', {
        encoding: 'utf8'
    });
    process.stdout.pipe(str);
};

そして、外部スクリプトを忘れてください。

于 2012-05-25T22:13:50.127 に答える