日志轮转是解决日志量过大的基础方法,通过定期分割、压缩和删除旧日志,避免单个文件过大或磁盘空间耗尽。Debian下推荐两种工具:
logrotate(系统原生工具):
配置步骤:
① 安装:sudo apt-get install logrotate(Debian默认包含);
② 创建配置文件:sudo nano /etc/logrotate.d/nodejs,添加以下内容(根据实际路径调整):
/var/www/your-app/logs/*.log {
daily # 每日轮转
rotate 7 # 保留7天日志
compress # 压缩旧日志(节省空间)
delaycompress # 延迟1天压缩(避免影响最新日志读取)
missingok # 日志文件不存在时不报错
notifempty # 空日志不处理
create 0640 www-data www-data # 新日志文件权限(适配Debian默认web用户)
sharedscripts # 所有日志轮转完成后执行脚本
postrotate
# 若用PM2管理进程,需通知其重新打开日志
if [ -f /var/run/pm2.pid ]; then
pm2 reload logs
fi
endscript
}
③ 测试配置:sudo logrotate -d /etc/logrotate.d/nodejs(模拟运行,查看是否有错误);
④ 强制执行:sudo logrotate -f /etc/logrotate.d/nodejs(立即触发轮转)。
PM2内置日志管理(适合用PM2部署的应用):
若使用PM2管理Node.js进程,可直接安装pm2-logrotate插件,简化配置:
① 安装插件:pm2 install pm2-logrotate;
② 设置参数:pm2 set pm2-logrotate:compress true(启用压缩)、pm2 set pm2-logrotate:rotateInterval '0 0 * * *'(每天凌晨轮转)、pm2 set pm2-logrotate:max_days 7(保留7天)。
通过日志库限制输出的日志级别,过滤掉调试(debug)、信息(info)等非必要日志,仅保留警告(warn)、错误(error)等关键信息。常用日志库配置示例:
const winston = require('winston');
const logger = winston.createLogger({
level: 'warn', // 仅输出warn及以上级别日志
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }), // 错误日志单独存储
new winston.transports.Console() // 控制台输出
]
});
const bunyan = require('bunyan');
const logger = bunyan.createLogger({
name: 'my-app',
level: 'warn', // 日志级别设置为warn
streams: [
{ level: 'warn', stream: process.stdout }, // 控制台输出warn及以上
{ level: 'error', path: 'app-error.log' } // 错误日志写入文件
]
});
生产环境中,建议将日志级别设置为warn或error,开发环境可设为debug。避免在代码中滥用console.log或无意义的调试日志,采用条件日志记录(仅在特定环境或条件下输出):
if (process.env.NODE_ENV === 'development') {
logger.debug('Debug information: Request received'); // 仅开发环境输出
}
// 生产环境避免记录敏感信息(如密码、银行卡号)
logger.info('User logged in', { userId: user.id, ip: request.ip }); // 记录必要字段
此外,可使用结构化日志(如JSON格式),便于后续过滤和分析,减少无效日志占比。
对于高并发应用,传统日志库(如console.log)可能成为性能瓶颈。推荐使用异步、轻量级日志库:
const pino = require('pino');
const logger = pino({ level: 'warn' }); // 异步写入,默认压缩
logger.warn('This is a warning message');
winston-async传输,提升写入性能:const { AsyncTransport } = require('winston-async');
const logger = winston.createLogger({
transports: [
new AsyncTransport({
transports: [
new winston.transports.File({ filename: 'combined.log' })
]
})
]
});
这些库能有效降低日志记录对应用性能的影响,适合生产环境。对于分布式系统或多节点应用,建议使用集中式日志管理工具,将日志集中存储、分析和检索,避免单节点日志堆积:
const winston = require('winston');
const { LogstashTransport } = require('winston-logstash-transport');
const logger = winston.createLogger({
transports: [
new LogstashTransport({
host: 'your-elk-server-ip',
port: 5000,
level: 'info'
})
]
});
除日志轮转外,可通过cron作业定期删除超过阈值的旧日志(如30天以上):
① 编写清理脚本/usr/local/bin/clean_old_logs.sh:
#!/bin/bash
find /var/www/your-app/logs -type f -name "*.log" -mtime +30 -exec rm -f {} \;
find /var/www/your-app/logs -type f -name "*.gz" -mtime +90 -exec rm -f {} \; # 删除3个月以上的压缩日志
② 添加执行权限:chmod +x /usr/local/bin/clean_old_logs.sh;
③ 添加cron任务:crontab -e,添加以下内容(每天凌晨2点执行):
0 2 * * * /usr/local/bin/clean_old_logs.sh >> /var/log/log_clean.log 2>&1
此方法可作为日志轮转的补充,进一步释放磁盘空间。