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的特殊配置实现固定文件的循环覆盖:
- 创建
logrotate配置文件(比如/etc/logrotate.d/node-service):
/path/to/logs/service_name.log { size 1M copytruncate missingok notifempty }
copytruncate:先复制文件内容,再截断原文件,服务无需重启即可继续写入size 1M:文件达到1MB时触发操作
- 在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
相关产品推荐
相关产品推荐

