2012-05-25 65 views
1

我正在嘗試使用節點核心的羣集功能。將process.stdout設置爲每個node.js文件的核心羣集工作者

我想stdoutstderr流輸出到一個文件,每個工人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這樣。

有沒有辦法實現這一目標,還是應該以不同的方式完成?目前,當我運行我的集羣時,我在一個控制檯中獲取來自所有進程的所有輸出,這非常混亂。

回答

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

它可能不是很優雅,但到目前爲止,這是我已經找到了最好的解決方案。

+0

我得到'stdout'未定義(在hookWriteStream參數中)...我需要設置stdout爲什麼? – GavinR

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直接重新綁定,所以這可能是你的當中最好的選擇。

如果你不希望任何輸出到控制檯可言,你可以重新綁定的console.log像:

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

而忽略了外部腳本。

+0

恐怕這是行不通的。 'process.stdout'是[Writable Stream](http://nodejs.org/api/stream.html#stream_writable_stream),根據文檔沒有管道方法。我也測試過,這不會將stdout寫入給定的文件。 – Tom

+0

你說得對。嗯...... – genericdave

+0

我沒有看到你的第二個解決方案的重點,因爲它不允許我爲每個工作人員分別寫入文件。換句話說,它必須在節點內完成。 – Tom