You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中Winston日志达大小限制后覆盖文件的实现方案

解决方案

方案1:扩展Winston File传输器实现循环覆盖

Winston默认的File传输器达到maxsize后会停止写入,我们可以扩展它,当文件大小超过阈值时直接清空文件并继续写入,保持文件名固定。

代码示例:

const winston = require('winston');
const fs = require('fs');
const path = require('path');

// 自定义循环覆盖传输器
class CircularFileTransport extends winston.transports.File {
    constructor(options) {
        super(options);
        this.maxsize = options.maxsize;
    }

    log(info, callback) {
        const filePath = path.join(this.dirname, this.filename);
        // 检查文件大小
        fs.stat(filePath, (err, stats) => {
            if (!err && stats.size >= this.maxsize) {
                // 清空文件
                fs.truncate(filePath, 0, (truncErr) => {
                    if (truncErr) {
                        console.error('Failed to truncate log file:', truncErr);
                    }
                    // 执行原有的写入逻辑
                    super.log(info, callback);
                });
            } else {
                super.log(info, callback);
            }
        });
    }
}

// 使用自定义传输器
const logger = winston.createLogger({
    level: 'debug',
    transports: [
        new CircularFileTransport({
            dirname: 'logs',
            filename: `${service_name}.log`,
            handleExceptions: true,
            json: false,
            maxsize: 1000000, // 1MB
        })
    ]
});

这个实现会在每次写入日志前检查文件大小,超过阈值就清空文件,无需重启服务即可继续写入。

方案2:用fs.watch监控文件大小,定时截断

如果不想扩展Winston传输器,可以在服务中加入一段监控逻辑,实时检查日志文件大小并触发截断:

const fs = require('fs');
const path = require('path');

const logFilePath = path.join('logs', `${service_name}.log`);
const maxSize = 1000000; // 1MB

// 每5秒检查一次文件大小
setInterval(() => {
    fs.stat(logFilePath, (err, stats) => {
        if (!err && stats.size >= maxSize) {
            fs.truncate(logFilePath, 0, (truncErr) => {
                if (truncErr) {
                    console.error('Truncate log file error:', truncErr);
                } else {
                    console.log('Log file truncated due to size limit');
                }
            });
        }
    });
}, 5000);

将这段代码加入服务启动脚本,即可自动维护日志文件大小,保持文件名不变。

方案3:Docker内配合logrotate实现无重启覆盖

无需修改Node.js代码,在Docker容器中使用logrotate的特殊配置实现固定文件的循环覆盖:

  1. 创建logrotate配置文件(比如/etc/logrotate.d/node-service):
/path/to/logs/service_name.log {
    size 1M
    copytruncate
    missingok
    notifempty
}
  • copytruncate:先复制文件内容,再截断原文件,服务无需重启即可继续写入
  • size 1M:文件达到1MB时触发操作
  1. 在Docker容器中定时执行logrotate,可以通过cron任务或启动脚本实现:
    • 若用cron,需确保容器安装了cron和logrotate,添加定时任务*/5 * * * * /usr/sbin/logrotate /etc/logrotate.d/node-service
    • 若不想用cron,可在启动脚本中加入循环执行命令:while true; do /usr/sbin/logrotate /etc/logrotate.d/node-service; sleep 300; done

内容的提问来源于stack exchange,提问作者Anis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:05:09