将stdout重定向到文件nodejs

时间:2015-09-22 14:42:26

标签: node.js logging stdout

我创建了:

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');

有人可以解释我做错了什么吗?

5 个答案:

答案 0 :(得分:23)

我通过以下方式解决了这个问题:

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);
  • 抛出新错误('崩溃');
  • 抛出'永远不要这样做';
  • throw undefined;

答案 1 :(得分:3)

结帐console.Console,正常console的父类。

var myLogFileStream = fs.createWriteStream(pathToMyLogFile);

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

然后,您可以使用myConsole.logmyConsole.errormyConsole.dir等,直接写入您的文件。

您还可以monkey patch process.stdout.write完成以下操作:

var fn = process.stdout.write;

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

process.stdout.write = write;

还有其他选项可以覆盖console._stdout,具体取决于将stdout记录到文件的动机。

答案 2 :(得分:2)

process.stdout是可写的。 pipeReadable的一种方法(Cf StreamAPI文档: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(你可以随心所欲地做任何事情)

答案 3 :(得分:0)

@ user3173842 为答复 我通过以下方式解决了这个问题:

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

您确实知道process.stdoutprocess.on('exit')之后继续,因此fs.WriteStreamprocess.stdout之后关闭,根据 https://github.com/nodejs/node/issues/7606

因此,现在的问题仍然存在,即开发人员是否希望使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似乎可以完成很多工作    此时。 这是好习惯吗,您会这样做还是在这种情况下会做什么? 任何人都可以随时回复。

答案 4 :(得分:0)

最初基于@ Anatol-user3173842答案

但是在我的情况下,我需要钩住stdout和stderr并还要写入文件中。

因此,对于那些除了写入文件外还需要保持正常stdout行为的人。使用以下内容。

对于非错误:

// stdout logging hook
const stdoutWrite0 = process.stdout.write;
process.stdout.write = (args) => { // On stdout write
  CustomLogger.writeToLogFile('log', args); // Write to local log file
  args = Array.isArray(args) ? args : [args]; // Pass only as array to prevent internal TypeError for arguments
  return stdoutWrite0.apply(process.stdout, args);
};

对于错误:

// stderr logging hook
const stderrWrite0 = process.stderr.write;
process.stderr.write = (args) => { // On stderr write
  CustomLogger.writeToLogFile('error', args); // Write to local error file
  args = Array.isArray(args) ? args : [args]; // Pass only as array to prevent internal TypeError for arguments
  return stderrWrite0.apply(process.stderr, args);
};

// uncaught exceptions
process.on('uncaughtException', (err) => {
  CustomLogger.writeToLogFile('error', ((err && err.stack) ? err.stack : err));
});

这是CustomLogger代码,在这里我还按日期分隔了日志文件:

export class CustomLogger {

 static LOGS_DIR = 'location-of-my-log-files';

 private static logDailyName(prefix: string): string {
   const date = new Date().toLocaleDateString().replace(/\//g, '_');
   return `${CustomLogger.LOGS_DIR}/${prefix}_${date}.log`;
 }

 private static writeToLogFile(prefix, originalMsg) {
   const timestamp   = Date.now();
   const fileName    = this.logDailyName(prefix);
   const logMsg      = prepareForLogFile(originalMsg);
   fs.appendFileSync(fileName, `${timestamp}\t${logMsg}\n\n`);
   return originalMsg;
 }
}