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

0md85ypi  于 2023-02-15  发布在  Node.js
关注(0)|答案(6)|浏览(240)

我创造了:

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

有人能解释一下我做错了什么吗?

acruukt9

acruukt91#

我用以下方法解决了这个问题:

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
  • 一些流管道(过程标准输出);
  • 抛出新错误("崩溃");
  • 抛出"永远不要这样做";
  • 投掷未定义;
fbcarpbf

fbcarpbf2#

checkout 普通console的父类console.Console

var myLogFileStream = fs.createWriteStream(pathToMyLogFile);

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

然后,您可以使用myConsole.logmyConsole.errormyConsole.dir等直接写入文件。
也可以按如下所示对process.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的其它选项。

am46iovg

am46iovg3#

process.stdout是可写的。pipeReadable的方法(参见StreamAPI文档:https://nodejs.org/api/stream.html
您可以在此处查看process.stdout的文档:www.example.comhttps://nodejs.org/api/process.html#process_process_stdout
令人惊讶的是,你可以毫无错误地执行process.stdout.pipe(...);。但是我想这个调用什么也不做。除了返回一个绑定到stdout的新的可写流(或者它可能返回process.stdout本身。文档中没有对此的规范)。
如果要将stdout重定向到某个文件,可以使用多种解决方案:

  • 只需使用命令行即可。Windows风格:node myfile.js > api.access.log.
  • 用你自己的对象替换控制台对象,你可以重写控制台方法。
  • 我不确定,但是有可能用您自己的流替换process.stdout(您可以对它做任何您想做的事情)
g6baxovj

g6baxovj4#

@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被调用时,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()

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

falq053o

falq053o5#

最初基于@ Anatol-user 3173842答案
但在我的例子中,我需要挂接stdout & stderr,并写入一个文件。
因此,对于那些除了写入文件之外还需要保持标准输出行为的人,请使用以下代码。
对于非错误:

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

icomxhvb6#

下面是一个logger类的快速示例,它将stdoutstderr和异常重定向到一个文件,同时仍然将所有内容写入控制台:

class Logger {
  #log_stream
  #stdout_write
  #stderr_write
  constructor(path) {
    this.#log_stream = fs.createWriteStream(path, { flags: 'a' })
    this.#stdout_write = process.stdout.write.bind(process.stdout)
    this.#stderr_write = process.stderr.write.bind(process.stderr)
    process.stdout.write = this.stdout_write.bind(this)
    process.stderr.write = this.stderr_write.bind(this)
    process.on('uncaughtException', function(err) {
      console.error((err && err.stack) ? err.stack : err)
    })
  }
  stdout_write(buffer) {
    this.#log_stream.write(buffer)
    this.#stdout_write(buffer)
  }
  stderr_write(buffer) {
    this.#log_stream.write(buffer)
    this.#stderr_write(buffer)
  }
}

const logger = new Logger('example.log')

相关问题