Node.js 在 Linux 上的错误处理与日志配置
一 日志框架与输出策略
npm i winstonsudo mkdir -p /var/log/nodejs && sudo touch /var/log/nodejs/error.logsudo chown <nodejs_user>:<nodejs_group> /var/log/nodejs/error.logconst winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'error',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: '/var/log/nodejs/error.log', level: 'error' }),
new winston.transports.File({ filename: '/var/log/nodejs/combined.log' })
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({ format: winston.format.simple() }));
}
// 使用
logger.error('Unhandled error', { err: err.stack || err });
二 进程管理与标准输出重定向
sudo npm i -g pm2pm2 start app.js --name my_node_appmodule.exports = {
apps: [{
name: 'my_node_app',
script: 'app.js',
autorestart: true,
max_memory_restart: '1G',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
out_file: '/var/log/nodejs/my_node_app-out.log',
error_file: '/var/log/nodejs/my_node_app-error.log',
combine_logs: false,
log_level: 'error'
}]
};
// 启动:pm2 start ecosystem.config.js
三 未捕获异常与 Promise 拒绝
const logger = require('./logger'); // 前述 winston logger
process.on('unhandledRejection', (reason, promise) => {
logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
// 重要:记录后退出,避免状态不一致
process.exit(1);
});
process.on('uncaughtException', (error) => {
logger.error('Uncaught Exception:', error);
// 重要:记录后退出,由进程管理器(如 PM2)重启
process.exit(1);
});
四 日志轮转与保留策略
/etc/logrotate.d/nodejs-app/var/log/nodejs/*.log {
daily
missingok
rotate 7
compress
notifempty
create 0640 <nodejs_user> <nodejs_group>
}
五 常见 Linux 层错误与排查要点
ulimit -asudo systemctl daemon-reexec 或重启系统生效。npm install <module>。