配置Node.js将日志记录到文件而不是控制台

259

我可以配置console.log,使日志被写入文件而不是在控制台中打印吗?


2
对于长时间运行的生产应用程序来说,仅查找特定日期的日志可能很困难,不是吗?@racar - user1893702
28个回答

247
您也可以重载默认的console.log函数:
var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(d) { //
  log_file.write(util.format(d) + '\n');
  log_stdout.write(util.format(d) + '\n');
};

以上示例将记录到debug.log和stdout。

编辑:请参见此页面上Clément的多参数版本


24
不必费神覆盖控制台日志(console.log)。只需创建自己的函数,将日志记录到特定文件即可。 - Alexander Mills
2
此外,这不适用于多个参数。例如: console.log(p1, p2, p3) - user603749
13
很好的回答!此外,如果你想捕获多个console.log参数,只需在'd'的位置上获取“Arguments”对象-https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments - Charlie
7
我需要在每个JS文件中都有这个,有没有办法让它成为全局的? - stackdave
3
记录所有参数的方法如下:console.log = function (...d) { log_file.write(util.format(...d) + '\n'); log_stdout.write(util.format(...d) + '\n'); }; - Paulo Victor Duarte
显示剩余6条评论

91

更新于2013年-本文是针对Node v0.2和v0.4编写的;现在有更好的日志记录工具可用。我强烈推荐Winston

更新于2013年末-我们仍然使用winston,但现在使用一个日志库来包装自定义对象和格式化的日志记录功能。以下是我们logger.js的示例:https://gist.github.com/rtgibbons/7354879


应该就这么简单。

var access = fs.createWriteStream(dir + '/node.access.log', { flags: 'a' })
      , error = fs.createWriteStream(dir + '/node.error.log', { flags: 'a' });

// redirect stdout / stderr
proc.stdout.pipe(access);
proc.stderr.pipe(error);

2
Nvm,我想它是指进程... 这个怎么工作呢?console.log(whatever); 仍然会输出到控制台,而非文件。 - trusktr
15
由于最近的更改,您现在不能调用stderr.pipe()了 - 现在需要使用以下代码:process.__defineGetter__('stderr', function() { return fs.createWriteStream(__dirname + '/error.log', {flags:'a'}) }) - damianb
17
就我个人而言,我会远离 Winston。我们使用它已经一年了,最终决定完全移除它,因为它在我们的生产环境中引起了许多问题。这个项目现在似乎被极差地维护着。有一个长长的问题列表。其中许多问题已经由其他用户提交了拉取请求,但是项目维护者甚至没有花时间合并它们。作为替代方案,您可以考虑使用 node-bunyan 和 caterpillar。 - UpTheCreek
2
截至2015年4月,Winston似乎是最新的,并且受到了大量活动的关注。 - Mike Grace
1
部署应用程序后,如何访问此日志文件? - Abhay Sehgal
显示剩余8条评论

82

如果您正在寻找生产环境中的内容,winston 可能是最好的选择。

如果您只想快速地进行开发工作,并将输出直接写入文件(我认为这仅适用于*nix系统):

nohup node simple-server.js > output.log &

9
在Windows系统中,使用>符号重定向标准输出同样有效。但是nohup命令则不行。 - Brad
4
在*nix系统中,不需要使用nohup也可以愉快地运行此命令:node simple-server.js > output.log。如果您希望在日志书写时跟踪它,只需运行tail -f output.log即可。 - nasty pasty
在生产环境中这样做的缺点是什么? - m-a-r-c-e-l-i-n-o
1
顺便提一下,根据您的操作系统,“处理它”的方式可能只是日志轮换,这在我看来是一个不错的解决方案- https://abdussamad.com/archives/541-Log-rotation-in-CentOS-Linux.html - ferr
2
最后的 "&" 代表什么? - RonaldPaguay
显示剩余4条评论

78

我经常在console.log()console.error()中使用多个参数,我的解决方案是:

var fs = require('fs');
var util = require('util');
var logFile = fs.createWriteStream('log.txt', { flags: 'a' });
  // Or 'w' to truncate the file every time the process starts.
var logStdout = process.stdout;

console.log = function () {
  logFile.write(util.format.apply(null, arguments) + '\n');
  logStdout.write(util.format.apply(null, arguments) + '\n');
}
console.error = console.log;

这很好,但是 util.format.apply(null, arguments) 在程序启动时似乎会输出大量数据。就好像它会输出每个必需的对象一样。我不知道该如何停止它,但使用上面的单参方法则不会发生这种情况。 - Zei

47

Winston 是一个非常流行的 npm 模块,用于记录日志。

以下是使用说明。
在项目中安装 winston:

npm install winston --save

这里是一个开箱即用的配置,在我的项目中经常使用,作为utils下的logger.js。

 /**
 * Configurations of logger.
 */
const winston = require('winston');
const winstonRotator = require('winston-daily-rotate-file');

const consoleConfig = [
  new winston.transports.Console({
    'colorize': true
  })
];

const createLogger = new winston.Logger({
  'transports': consoleConfig
});

const successLogger = createLogger;
successLogger.add(winstonRotator, {
  'name': 'access-file',
  'level': 'info',
  'filename': './logs/access.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

const errorLogger = createLogger;
errorLogger.add(winstonRotator, {
  'name': 'error-file',
  'level': 'error',
  'filename': './logs/error.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

module.exports = {
  'successlog': successLogger,
  'errorlog': errorLogger
};

然后只需根据需要导入,如下所示:

const errorLog = require('../util/logger').errorlog;
const successlog = require('../util/logger').successlog;

然后您可以将成功记录为:

successlog.info(`Success Message and variables: ${variable}`);

并将错误定义为:

errorlog.error(`Error Message : ${error}`);

它还会将所有成功日志和错误日志记录在一个文件中,在logs目录下按日期存档,如下所示。
log direcotry


2
日志可在控制台中查看,但不会立即创建文件!!我有什么遗漏吗? - Nigilan
1
你能分享一下你的配置吗?或者你按照我的建议使用了它吗? 如果配置没问题,请检查导入(winstonwinston-daily-rotate-file)。 它们应该在项目根目录下的名为“logs”的文件夹中创建。 抱歉回复晚了。 - KeshavDulal
@Nigilan 你是怎么解决这个问题的?我也遇到了同样的问题。 - user2180794
1
不要忘记在logger-util的顶部添加以下内容: const winston = require('winston'); const winstonRotator = require('winston-daily-rotate-file');并且,在您想记录某些内容的任何地方,都需要添加以下内容: const errorLog = require('../util/logger').errorlog; const successlog = require('../util/logger').successlog; - KeshavDulal
这对我有效! - Nigilan
显示剩余3条评论

15
const fs = require("fs");
const {keys} = Object;
const {Console} = console;

/**
 * Redirect console to a file.  Call without path or with false-y
 * value to restore original behavior.
 * @param {string} [path]
 */
function file(path) {
    const con = path ? new Console(fs.createWriteStream(path)) : null;

    keys(Console.prototype).forEach(key => {
        if (path) {
            this[key] = (...args) => con[key](...args);
        } else {
            delete this[key];
        }
    });
};

// patch global console object and export
module.exports = console.file = file;

要使用它,请执行以下操作:

require("./console-file");
console.file("/path/to.log");
console.log("write to file!");
console.error("also write to file!");
console.file();    // go back to writing to stdout

只保存错误信息是可能的吗? - stackdave
不要循环遍历Console.prototype的键,只需明确设置this.error即可。 - rich remer
这会导致console.log出错吗? - G_V
它不会破坏 console.log。它会改变其行为,但是您可以通过调用 console.file() 恢复旧的行为。 - rich remer

15

对于简单情况,我们可以使用'>''2>&1'标准输出(STDOUT)和标准错误(STDERR)流直接重定向到一个文件(比如test.log)中。

例如:

// test.js
(function() {
    // Below outputs are sent to Standard Out (STDOUT) stream
    console.log("Hello Log");
    console.info("Hello Info");
    // Below outputs are sent to Standard Error (STDERR) stream
    console.error("Hello Error");
    console.warn("Hello Warning");
})();
根据 POSIX 标准,“输入”、“输出”和“错误”流通过正整数“文件描述符”(0、1、2)进行识别。即 stdin 是 0,stdout 是 1,stderr 是 2。
步骤 1:'2>&1' 表示将 2(stderr)重定向到 1(stdout) 步骤 2:'>' 表示将 1(stdout)重定向到文件 test.log

1
这对于简单情况非常有用,当您只想获取应用程序日志而无需处理控制台断行等情况时。 - divillysausages

11

5
您的log4js链接现在已经失效了。这个链接怎么样?https://github.com/nomiddlename/log4js-node - Joe Hildebrand
2
是的,我想这个项目换了人手。谢谢。 - Marco

11

如果您正在使用Linux,您还可以使用输出重定向。不确定Windows系统是否可行。

node server.js >> file.log 2>> file.log

>> file.log 用于将 stdout 重定向到文件

2>> file.log 用于将 stderr 重定向到文件

其他人使用缩写 &>> 来同时重定向 stdoutstderr,但我的 Mac 和 Ubuntu 都不支持 :(

额外说明:> 表示覆盖,而 >> 表示追加。

顺便说一下,关于 NodeJS 日志记录器,我使用 pino + pino-pretty 记录器。


这可能是我使用情况下最佳的答案。不幸的是,在Mac上无法工作。 - Confidant
你收到了什么错误信息?还是文件根本就没有出现在应该出现的地方? - Mon
你收到了什么错误信息?还是文件根本就没有出现在应该出现的地方? - undefined
我已经有一段时间没有尝试过了。我怀疑我的困难在于使用Docker。现在我只用Node.js尝试了一下,它成功了,谢谢。 - Confidant
我已经有一段时间没有尝试过了。我怀疑我的困难在于使用Docker。现在我只尝试了使用Node.js,它起作用了,谢谢。 - undefined
这在Windows上与Git Bash(VS Code)很好用 - undefined

9

直接来自nodejs的API文档:Console

const output = fs.createWriteStream('./stdout.log');
const errorOutput = fs.createWriteStream('./stderr.log');
// custom simple logger
const logger = new Console(output, errorOutput);
// use it like console
const count = 5;
logger.log('count: %d', count);
// in stdout.log: count 5

1
你的例子对我有用,但是你应该写成:const logger = new console.Console(output, errorOutput); - Abbas
1
在什么时候关闭 writeStreams?程序结束时如何关闭它们? - Beki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接