web-dev-qa-db-ja.com

標準出力をファイルnodejsにリダイレクトする

私が作成しました:

var access = fs.createWriteStream('/var/log/node/api.access.log', { flags: 'w' });

その後、パイプ処理されました:

process.stdout.pipe(access);

次に試してみました:

console.log("test");

そして/var/log/node/api.access.logには何も現れていません。しかし、この方法は機能しています:

process.stdout.pipe(access).write('test');

誰かが私が間違っていることを説明できますか?

16
Supervision

この問題は次の方法で解決しました。

var access = fs.createWriteStream('/var/log/node/api.access.log');
process.stdout.write = process.stderr.write = access.write.bind(access);

もちろん、必要に応じてstdoutとstderrを分離することもできます。

また、キャッチされていない例外を処理することを強くお勧めします。

process.on('uncaughtException', function(err) {
  console.error((err && err.stack) ? err.stack : err);
});

これは、次の状況をカバーします。

  • process.stdout.write
  • process.stderr.write
  • console.log
  • console.dir
  • console.error
  • someStream.pipe(process.stdout);
  • 新しいエラーをスロー( 'クラッシュ');
  • 「これを絶対にしない」を投げます。
  • 未定義のスロー。
24

チェックアウトconsole.Console、通常のconsoleの親クラス。

var myLogFileStream = fs.createWriteStream(pathToMyLogFile);

var myConsole = new console.Console(myLogFileStream, myLogFileStream);

その後、myConsole.logmyConsole.errormyConsole.dirなどを使用して、ファイルに直接書き込むことができます。

次のように monkey patchprocess.stdout.writeにすることもできます。

var fn = process.stdout.write;

function write() {
  fn.apply(process.stdout, arguments);
  myLogFileStream.write.apply(myLogFileStream, arguments);
}

process.stdout.write = write;

stdoutをファイルに記録する動機に応じて、console._stdoutを上書きする他のオプションもあります。

3
richardpringle

_process.stdout_は書き込み可能です。 pipeReadable(Cf StreamAPI documentation: https://nodejs.org/api/stream.html のメソッドです

_process.stdout_のドキュメントはここで見ることができます: https://nodejs.org/api/process.html#process_process_stdout

エラーなしでprocess.stdout.pipe(...);を実行できることは驚くべきことです。しかし、この呼び出しは何もしないと思います。 stdoutにバインドされた新しいWritableストリームを返すことを除きます(または、_process.stdout_自体を返します。ドキュメントには仕様がありません)。

Stdoutをファイルにリダイレクトする場合、多くの解決策があります。

  • コマンドラインを使用するだけです。 Windowsスタイル:_node myfile.js > api.access.log_。
  • コンソールオブジェクトを独自のオブジェクトに置き換えます。また、コンソールメソッドを書き換えることができます。
  • よくわかりませんが、_process.stdout_をあなた自身のストリームに置き換えることができるかもしれません(そして、あなたはこれで何でもできます)
2
Magus

@ user3173842の返信は、この問題を次の方法で解決しました。

var access = fs.createWriteStream('/var/log/node/api.access.log');
process.stdout.write = process.stderr.write = access.write.bind(access);

https://github.com/nodejs/node/issues/7606 によれば、process.stdoutprocess.on('exit')の後に続くため、fs.WriteStreamprocess.stdoutで終了することを理解しています。

開発者がfs.Writestream.write()を通常の機能に戻したい場合、およびfs.Writestream.endが呼び出されると、書き込みストリームが閉じます。開発者はこれをどうやってやろうと思いましたか

a_l = asyncify_listener
p_std_stream_m is a process stream manager object

p_std_stream_m.std_info.p_stdout_write = process.stdout.write   

process.stdout.write = w_stream.write.bind(w_stream)

process.once('beforeExit', a_l(   p_std_stream_m.handler,process.stdout,w_stream   )   )       

     where in the 'beforeExit' event listener I did
process.stdout.write = p_std_stream_m.std_info.p_stdout_write

w_stream.end()

process.stdoutは現時点で多くの作業を行っているように見えるため、これは機能し、onceメソッドを使用します。これは良い習慣ですか、あなたはこれをしますか、この状況で何をしますか誰でも気軽に返信できます。

0
MIchael Odumosu