Node.js 日志**“丢失数据”通常不是 Node.js 本身故意丢,而是写入方式、进程生命周期、并发、缓冲区等综合问题**。下面按最常见原因 → 对应解决方案系统说明。
Node.js 默认是异步非阻塞 I/O,日志往往还在缓冲区里,进程就退出了。
console.log('start');
process.exit(0); // 日志可能没刷出去
✅ 解决方案
process.on('exit', () => {
// 不要在这里写异步日志,exit 时已经太晚
});
// 正确方式:等日志写完再退出
setTimeout(() => {
process.exit(0);
}, 100);
或使用:
process.exitCode = 0;
console.log 输出到 stdout,但:
✅ 解决方案
process.stdout.write(JSON.stringify(log) + '\n');
很多日志库默认有 buffer,不会立刻写磁盘。
new winston.transports.File({
filename: 'app.log',
// 默认有缓冲
})
✅ 解决方案
// 程序退出前
logger.end();
或:
logger.close();
✅ 解决方案
pino + pino-rotating-file未捕获异常时,Node.js 直接退出:
throw new Error('crash');
✅ 解决方案
process.on('uncaughtException', (err) => {
logger.error(err);
process.exit(1);
});
process.on('unhandledRejection', (err) => {
logger.error(err);
});
⚠️ 注意:异常里尽量只做同步日志
logger.info('xxx'); // 异步
res.send('ok'); // 先返回
✅ 解决方案
| 方式 | 是否可靠 | 说明 |
|---|---|---|
| console.log | ❌ 不可靠 | 容器 / 退出时易丢 |
| Winston | ⚠️ 默认不可靠 | 需 flush |
| Pino | ✅ 很可靠 | 推荐 |
| 直接 fs.writeFileSync | ✅ 可靠 | 性能差 |
| PM2 日志 | ⚠️ | 文件轮转问题 |
✅ 推荐组合
Node.js + Pino + systemd / Docker json-file
✅ 正确姿势
// 日志输出到 stdout
pino().info('hello');
Docker:
docker logs <container>
✅ 不要
你可以对照检查:
process.exit 太早?console.log 当正式日志?uncaughtException?import pino from 'pino';
const logger = pino({
level: 'info',
});
logger.info('this will not be lost');
如果你愿意,可以把你现在的:
贴出来,我可以直接帮你定位是哪一行在丢日志。