node.js 将标准输出重定向到文件 nodejs

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32719923/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 19:19:06  来源:igfitidea点击:

Redirecting stdout to file nodejs

node.jsloggingstdout

提问by Supervision

I've created:

我创建了:

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

Then piped:

然后管道:

process.stdout.pipe(access);

Then tried:

然后尝试:

console.log("test");

And nothing has appeared in /var/log/node/api.access.log. However this way is working:

/var/log/node/api.access.log 中没有出现任何内容。但是这种方式是有效的:

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

Could someone explain what am I doing wrong ?

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

回答by Anatol - user3173842

I solved this problem the following way:

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

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

Of course you can also separate stdout and stderr if you want.

当然,如果需要,您也可以将 stdout 和 stderr 分开。

I also would strongly recommend to handle uncaught exceptions:

我也强烈建议处理未捕获的异常:

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

This will cover the following situations:

这将涵盖以下情况:

  • process.stdout.write
  • process.stderr.write
  • console.log
  • console.dir
  • console.error
  • someStream.pipe(process.stdout);
  • throw new Error('Crash');
  • throw 'never do this';
  • throw undefined;
  • process.stdout.write
  • 进程.stderr.write
  • 控制台日志
  • 控制台目录
  • 控制台错误
  • someStream.pipe(process.stdout);
  • throw new Error('崩溃');
  • 抛出“永远不要这样做”;
  • 抛出未定义;

回答by richardpringle

Checkout console.Console, the parent class of the normal console.

Checkout console.Console,父类正常console

var myLogFileStream = fs.createWriteStream(pathToMyLogFile);

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

You can then you use myConsole.log, myConsole.error, myConsole.dir, etc. and write directly to your file.

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

You can also monkey patchprocess.stdout.writeas follows:

您还可以按如下方式进行猴子补丁process.stdout.write

var fn = process.stdout.write;

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

process.stdout.write = write;

there are also other options for overwriting console._stdoutdepending on the motivation for logging the stdoutto a file.

console._stdout根据记录stdout到文件的动机,还有其他覆盖选项。

回答by MIchael Odumosu

@user3173842 for the reply on I solved this problem the following way:

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

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

you do understand that process.stdoutcontinues after process.on('exit')and therefore the fs.WriteStreamcloses after with process.stdout, according to https://github.com/nodejs/node/issues/7606

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

so now the question remains, if the developer desired to have the fs.Writestream.write()return to its normal functionality and when fs.Writestream.endis called the writestream closes. How would the developer go about doing this I did

所以现在问题仍然存在,如果开发人员希望fs.Writestream.write()恢复其正常功能以及何时fs.Writestream.end调用 writestream 关​​闭。开发人员将如何进行我所做的

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()

It works and you use the once method because the process.stdoutseems to do a lot of work at this time. Is this good practice, would you do this or what would you do in this situation anyone can feel free to reply.

它有效并且您使用 once 方法,因为此时process.stdout似乎做了很多工作。这是一个好的做法,你会这样做,或者在这种情况下你会做什么,任何人都可以随时回复。

回答by Magus

process.stdoutis a Writable. pipeis a method of Readable(Cf StreamAPI documentation : https://nodejs.org/api/stream.html

process.stdout是可写的。pipe是一种方法Readable(参见 StreamAPI 文档:https://nodejs.org/api/stream.html

You can see the documentation of process.stdouthere : https://nodejs.org/api/process.html#process_process_stdout

您可以在process.stdout此处查看文档:https: //nodejs.org/api/process.html#process_process_stdout

It's surprising that you can do process.stdout.pipe(...);without any error. But i suppose this call just do nothing. Except returning a new Writable stream binded to stdout (or maybe it returns process.stdoutitself. There's no specification for that in the documentation).

令人惊讶的是,您可以毫无错误地进行操作process.stdout.pipe(...);。但我想这个电话什么都不做。除了返回绑定到 stdout 的新 Writable 流(或者它可能返回process.stdout自身。文档中没有具体说明)。

If you want to redirect stdout to a file, you have many solutions :

如果要将标准输出重定向到文件,您有很多解决方案:

  • Just use your command line to do that. Windows style : node myfile.js > api.access.log.
  • Replace the console object by your own object. And you can rewrite console methods.
  • I'm not sure, but it may be possible to replace process.stdoutwith your own stream (and you can do whatever you want with this)
  • 只需使用您的命令行即可。窗户风格:node myfile.js > api.access.log
  • 用您自己的对象替换控制台对象。您可以重写控制台方法。
  • 我不确定,但可以process.stdout用你自己的流替换(你可以用它做任何你想做的事)

回答by Nikita Kurtin

Originally based on @Anatol-user3173842 answer

最初基于@Anatol-user3173842 答案

But in my case I needed to hook the stdout & stderr and also write into a file.

但就我而言,我需要挂钩 stdout 和 stderr 并写入文件。

So for those who need to keep the normal stdout behaviour in addition to writing into the file. Use the following.

所以对于那些除了写入文件之外还需要保持正常标准输出行为的人。使用以下内容。

For non-errors:

对于非错误:

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

For errors:

对于错误:

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

Here is the CustomLoggercode, where I also separate the log files by date:

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