222

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

4

26 回答 26

219

你也可以重载默认的 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 的多参数版本也在这个页面上。

于 2014-01-11T10:45:20.780 回答
84

2013 年更新 -这是围绕 Node v0.2 和 v0.4 编写的;现在围绕日志记录有更好的实用程序。我强烈推荐温斯顿

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);
于 2011-12-06T00:28:20.197 回答
74

如果您正在寻找生产中的东西,winston可能是最佳选择。

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

nohup node simple-server.js > output.log &
于 2011-12-06T08:56:16.260 回答
68

我经常对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;
于 2015-11-24T15:47:13.147 回答
41

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

它还按日期将所有成功日志和错误日志记录在日志目录下的文件中,如您在此处看到的。
日志目录

于 2016-12-01T09:02:35.243 回答
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
于 2017-02-09T18:34:25.800 回答
12

如果这是针对应用程序的,则最好使用日志记录模块。它会给你更多的灵活性。一些建议。

于 2011-12-06T07:19:55.087 回答
10

对于简单的情况,我们可以使用'>''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");
})();

节点 test.js > test.log 2>&1

根据 POSIX 标准,“输入”、“输出”和“错误”流由正整数文件描述符(0、1、2) 标识。即,stdin 为 0,stdout 为 1,stderr 为 2。

第 1 步:'2>&1'将从 2 ( stderr ) 重定向到 1 ( stdout )

第 2 步:'>'将从 1 ( stdout ) 重定向到文件 ( test.log )

于 2019-01-09T11:12:56.800 回答
6

另一个尚未提及的解决方案是将流连接到Writableandprocess.stdoutprocess.stderr。这样您就不需要覆盖所有输出到 stdout 和 stderr的控制台函数。此实现将 stdout 和 stderr 都重定向到日志文件:

var log_file = require('fs').createWriteStream(__dirname + '/log.txt', {flags : 'w'})

function hook_stream(stream, callback) {
    var old_write = stream.write

    stream.write = (function(write) {
        return function(string, encoding, fd) {
            write.apply(stream, arguments)  // comments this line if you don't want output in the console
            callback(string, encoding, fd)
        }
    })(stream.write)

    return function() {
        stream.write = old_write
    }
}

console.log('a')
console.error('b')

var unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

var unhook_stderr = hook_stream(process.stderr, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

console.log('c')
console.error('d')

unhook_stdout()
unhook_stderr()

console.log('e')
console.error('f')

它应该在控制台中打印

a
b
c
d
e
f

并在日志文件中:

c
d

有关更多信息,请查看此要点

于 2016-12-14T05:28:30.063 回答
5

覆盖 console.log 是要走的路。但要使其在所需模块中工作,您还需要将其导出。

module.exports = console;

为了省去编写日志文件、轮换和其他东西的麻烦,您可以考虑使用像 winston 这样的简单记录器模块:

// Include the logger module
var winston = require('winston');
// Set up log file. (you can also define size, rotation etc.)
winston.add(winston.transports.File, { filename: 'somefile.log' });
// Overwrite some of the build-in console functions
console.error = winston.error;
console.log = winston.info;
console.info = winston.info;
console.debug = winston.debug;
console.warn = winston.warn;
module.exports = console;
于 2016-01-12T22:33:16.210 回答
5

直接来自控制台上 nodejs 的 API 文档

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
于 2017-07-25T00:16:02.730 回答
3

方法标准输出和标准差

这种方法可以帮助你(我在我的项目中使用类似的东西)并且适用于所有方法,包括console.log、console.warn、console.error、console.info

此方法将 stdout 和 stderr 中写入的字节写入文件。比更改 console.log、console.warn、console.error、console.info 方法更好,因为输出将与此方法输出完全相同


var fs= require("fs")
var os= require("os")
var HOME= os.homedir()
var stdout_r = fs.createWriteStream(HOME + '/node.stdout.log', { flags: 'a' })
var stderr_r = fs.createWriteStream(HOME + '/node.stderr.log', { flags: 'a' })

var attachToLog= function(std, std_new){

    var originalwrite= std.write
    std.write= function(data,enc){
        try{
            var d= data
            if(!Buffer.isBuffer(d))
                d= Buffer.from(data, (typeof enc === 'string') ? enc : "utf8")
            std_new.write.apply(std_new, d)
        }catch(e){}
        return originalwrite.apply(std, arguments)
    }


}
attachToLog(process.stdout, stdout_r)
attachToLog(process.stderr, stderr_r)

// recommended catch error on stdout_r and stderr_r
// stdout_r.on("error", yourfunction)
// stderr_r.on("error", yourfunction)
于 2019-01-20T01:05:45.713 回答
2

改进 Andres Riofrio ,以处理任意数量的参数

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(...args) {
    var output = args.join(' ');
    log_file.write(util.format(output) + '\r\n');
    log_stdout.write(util.format(output) + '\r\n');
};
于 2018-07-04T04:42:55.847 回答
2

对于未来的用户。@keshavDulal答案不适用于最新版本。对于最新版本中报告的问题,我找不到合适的解决方案3.3.3

无论如何,我在研究了一下后终于修复了它。这是winston版本的解决方案3.3.3

安装winston和winston-daily-rotate-file

npm install winston 
npm install winston-daily-rotate-file

创建一个新文件 utils/logger.js

const winston = require('winston');
const winstonRotator = require('winston-daily-rotate-file');

var logger = new winston.createLogger({
  transports: [
    new (winston.transports.DailyRotateFile)({
      name: 'access-file',
      level: 'info',
      filename: './logs/access.log',
      json: false,
      datePattern: 'yyyy-MM-DD',
      prepend: true,
      maxFiles: 10
    }),
    new (winston.transports.DailyRotateFile)({
      name: 'error-file',
      level: 'error',
      filename: './logs/error.log',
      json: false,
      datePattern: 'yyyy-MM-DD',
      prepend: true,
      maxFiles: 10
    })
  ]
});


module.exports = {
  logger
};

然后在要使用日志记录的任何文件中导入模块,例如

const logger = require('./utils/logger').logger;

使用如下记录器:

logger.info('Info service started');
logger.error('Service crashed');
于 2020-08-02T16:52:36.833 回答
2

如果您使用的是 linux,您还可以使用输出重定向。不确定Windows。

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

>> file.log重定向stdout到文件

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

其他人都使用简写&>>,但我的mac和ubuntu都不接受它stdout:(stderr

额外: >覆盖,而>>追加。

顺便说一句,关于 NodeJS 记录器,我使用pino+ pino-prettylogger

于 2021-03-12T07:10:21.967 回答
1

您现在可以使用Caterpillar,它是一个基于流的日志系统,允许您登录到它,然后将输出通过管道传输到不同的转换和位置。

输出到文件很简单:

var logger = new (require('./').Logger)();
logger.pipe(require('fs').createWriteStream('./debug.log'));
logger.log('your log message');

Caterpillar 网站上的完整示例

于 2013-05-08T01:09:11.360 回答
1

添加到上面的答案中,对简短而有效的代码覆盖进行了一点扩展console.log。次要添加:使用日期设置文件名,包装函数,还执行原始 console.logging 以使控制台与信息保持活动状态。

用法:在代码的开头,运行setConsoleLogToFile([FILENAME]).

const fs = require("fs"),
    util = require('util');


const getPrettyDate = ()=> new Date().toString().replace(":","-").replace(/00\s\(.*\)/, "").replace(` ${new Date().getFullYear()}`, ",").replace(/:\d\d\s/, " ");

module.exports.getPrettyDate = getPrettyDate;

module.exports.setConsoleLogToFile = (filename) => {
    const log_file = fs.createWriteStream(`${__dirname}/${filename} -  ${getPrettyDate()}.log`, { flags: 'w' }),
        log_stdout = process.stdout;

    const origConsole = console.log;
    console.log = (d) => { 
        origConsole(d);
        log_file.write(util.format(d) + '\n');
        log_stdout.write(util.format(d) + '\n');
    };
}
于 2021-03-27T10:19:33.087 回答
1

大多数记录器都是矫枉过正的,并且不正确支持console.log中的构建。因此我创建了控制台日志到文件

import { consoleLogToFile } from "console-log-to-file";
// or `const { consoleLogToFile } = require("console-log-to-file/dist/index.cjs.js")`

consoleLogToFile({
  logFilePath: "/log/default.log",
});

// all of your console.log/warn/error/info will work as it does and save to file now.
于 2021-04-04T10:07:31.310 回答
1

如果您要永远使用来保持节点应用程序运行,那么输入forever list将显示 console.log 正在写入的日志文件的路径

在此处输入图像描述

于 2021-05-04T08:36:20.003 回答
1

如果您正在寻找不修改任何代码的解决方案,这里有一个简单的解决方案。

它需要 pm2,只需将其添加到您的节点模块并启动您的应用程序

pm2 start server.js

大功告成,console.logs 现在自动注册到home/.pm2/logs/server-out.log下。

于 2021-10-28T19:32:04.450 回答
0

你也可以看看这个 npm 模块: https ://www.npmjs.com/package/noogger

诺格

简单直接...

于 2016-05-11T04:08:19.503 回答
0

我接受了将输出流交换到我的流的想法。

const LogLater                = require ('./loglater.js');
var logfile=new LogLater( 'log'+( new Date().toISOString().replace(/[^a-zA-Z0-9]/g,'-') )+'.txt' );


var PassThrough = require('stream').PassThrough;

var myout= new PassThrough();
var wasout=console._stdout;
myout.on('data',(data)=>{logfile.dateline("\r\n"+data);wasout.write(data);});
console._stdout=myout;

var myerr= new PassThrough();
var waserr=console._stderr;
myerr.on('data',(data)=>{logfile.dateline("\r\n"+data);waserr.write(data);});
console._stderr=myerr;

loglater.js:

const fs = require('fs');

function LogLater(filename, noduplicates, interval) {
    this.filename = filename || "loglater.txt";
    this.arr = [];
    this.timeout = false;
    this.interval = interval || 1000;
    this.noduplicates = noduplicates || true;
    this.onsavetimeout_bind = this.onsavetimeout.bind(this);
    this.lasttext = "";
    process.on('exit',()=>{ if(this.timeout)clearTimeout(this.timeout);this.timeout=false; this.save(); })
}

LogLater.prototype = {
    _log: function _log(text) {
        this.arr.push(text);
        if (!this.timeout) this.timeout = setTimeout(this.onsavetimeout_bind, this.interval);
    },
    text: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text);
    },
    line: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text + '\r\n');
    },
    dateline: function dateline(text) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(((new Date()).toISOString()) + '\t' + text + '\r\n');
    },
    onsavetimeout: function onsavetimeout() {
        this.timeout = false;
        this.save();
    },
    save: function save() { fs.appendFile(this.filename, this.arr.splice(0, this.arr.length).join(''), function(err) { if (err) console.log(err.stack) }); }
}

module.exports = LogLater;
于 2018-05-07T23:19:51.330 回答
0

我只是建立一个包来做这个,希望你喜欢它;) https://www.npmjs.com/package/writelog

于 2018-07-11T20:41:39.143 回答
0

我自己只是简单地从 winston 中获取示例并添加了log(...)方法(因为 winston 将其命名为info(..)

控制台.js:

"use strict"

// Include the logger module
const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    transports: [
        //
        // - Write to all logs with level `info` and below to `combined.log`
        // - Write all logs error (and below) to `error.log`.
        //
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
    logger.add(new winston.transports.Console({
        format: winston.format.simple()
    }));
}

// Add log command
logger.log=logger.info;

module.exports = logger;

然后只需在您的代码中使用:

const console = require('Console')

现在您可以简单地在文件中使用正常的日志功能,它会创建一个文件并将其记录到您的控制台(在调试/开发时)。因为if (process.env.NODE_ENV !== 'production') {(如果你也想在生产中使用它)......

于 2018-10-05T16:11:10.810 回答
0

创建一个 utils/logger.js 文件:

var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/../logs/server.log', { flags: 'w' });
var log_stdout = process.stdout;

console.log = function () { //
    [...arguments].forEach(element => {
        log_file.write(util.format(element) + '\n');
        log_stdout.write(util.format(element) + '\n');
    });
};

module.exports = {
    console
}

从您想要 console.log 的任何文件中包含 logger.js 文件,例如:

const console = require('./utils/logger').console;

创建一个日志文件夹并在其中创建一个空的 server.log 文件并运行您的应用程序:)

于 2021-11-07T14:27:02.873 回答
0

基于Clément 的多参数版本,文本文件没有颜色代码

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

console.log = function () {
  // Storing without color codes
  logFile.write(util.format.apply(null,arguments).replace(/\033\[[0-9;]*m/g,"") + '\n');
  // Display normally, with colors to Stdout
  logStdout.write(util.format.apply(null, arguments) + '\n');
}

注意:由于我无法发表评论而回答

于 2021-12-30T12:33:14.030 回答