利用 Debian 上的 Node.js 日志定位问题的实用流程
一 定位日志来源与快速查看
- 应用日志
- 常见位置:项目目录下的 logs/,或自定义目录(如 /var/log/myapp/、/var/log/nodejs/)。若使用日志库(如 winston、morgan),以库配置为准。
- 快速查看:tail -f logs/app.log、less logs/error.log、grep -n “ERROR” logs/*.log。
- 进程与系统日志
- systemd 服务:journalctl -u nodeapp.service -f(实时跟踪),或 journalctl -u nodeapp.service --since “2025-11-30 10:00:00”。
- 系统日志:grep -i node /var/log/syslog;内核与驱动线索:dmesg | grep -i node。
- 运行时调试输出
- 开启模块调试:DEBUG=* node your-app.js;生产慎用,避免性能与信息泄露。
二 提高日志可读性与信息量
- 使用结构化日志库
- 选择 Winston / Pino / Bunyan,便于多目标输出(控制台、文件、远程)与后续检索分析。
- 配置合理的日志级别
- 开发环境:debug/info;生产环境:warn/error。可通过环境变量控制,如 WINSTON_LEVEL=debug、PINO_LEVEL=debug。
- 统一格式与时间戳
- 建议包含 timestamp、level、message、stack,JSON 格式便于聚合与检索。
- 请求日志与错误分离
- Express + morgan 记录 HTTP 请求;错误单独写入 error.log,避免淹没关键异常。
- 可读性增强
- 开发时用 pino-pretty / bunyan-pretty 美化输出;生产保持 JSON 便于机器处理。
三 常见错误模式与日志线索
- 未捕获异常与未处理的 Promise 拒绝
- 现象:进程意外退出、无堆栈或仅有简短提示。
- 线索:应用日志缺少 try/catch 堆栈;可能只有 “UnhandledPromiseRejectionWarning”。
- 处置:添加全局监听并记录完整堆栈,必要时退出进程,确保进程管理器(如 systemd)能重启。
- 依赖与配置错误
- 现象:启动失败、模块找不到、连接字符串错误。
- 线索:应用日志含 “MODULE_NOT_FOUND”、配置读取失败、数据库连接失败等关键字。
- 处置:核对 node_modules、.env 与配置路径,必要时回滚版本或修正配置。
- HTTP 层异常
- 现象:大量 4xx/5xx、接口超时。
- 线索:morgan 输出请求路径、状态码、耗时;结合业务日志定位上游/下游问题。
- 资源与内核限制
- 现象:进程被系统终止、间歇性失败。
- 线索:dmesg 出现 OOM(Out of Memory)或 cgroup 限制;syslog 有 killed process 记录。
- 处置:检查内存/CPU、调整服务资源限制或优化代码内存占用。
四 高效排查命令与最小实践示例
- 命令清单
- 实时跟踪服务日志:journalctl -u nodeapp.service -f
- 过滤关键字:grep -n “ERROR|Exception” /var/log/myapp/*.log
- 最近错误并高亮:tail -n 200 /var/log/myapp/error.log | grep -E --color=auto “ERROR|WARN”
- 内核与驱动线索:dmesg -T | tail -n 50
- 进程崩溃回溯:查看 syslog 中服务停止与 OOM 信息
- 最小实践示例(Express + Winston + Morgan)
- 安装依赖:npm i express morgan winston
- 日志配置(logger.js)
- const winston = require(‘winston’);
const { combine, timestamp, json } = winston.format;
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || ‘info’,
format: combine(timestamp(), json()),
transports: [
new winston.transports.File({ filename: ‘logs/error.log’, level: ‘error’ }),
new winston.transports.File({ filename: ‘logs/combined.log’ }),
new winston.transports.Console()
]
});
module.exports = logger;
- HTTP 请求日志(app.js)
- const express = require(‘express’); const morgan = require(‘morgan’);
const logger = require(‘./logger’);
const app = express();
app.use(morgan(‘combined’, { stream: { write: msg => logger.info(msg.trim()) } }));
app.get(‘/error’, () => { throw new Error(‘boom’); });
app.use((err, req, res, next) => {
logger.error({ err: err.stack }, ‘uncaught error’);
res.status(500).send(‘Internal Server Error’);
});
app.listen(3000, () => logger.info(‘Server listening on 3000’));
- 全局异常兜底
- process.on(‘unhandledRejection’, (reason) => {
logger.error({ reason }, ‘Unhandled Rejection’);
process.exit(1); // 交由 systemd 重启
});
- 运行与观察
- LOG_LEVEL=debug node app.js
- 访问 /error,观察控制台、logs/error.log 与 logs/combined.log 的输出。
五 稳定运行与长期改进
- 日志轮转与容量控制
- 使用 logrotate 管理日志文件大小与保留周期,避免磁盘被占满。
- 监控与告警
- 结合 Prometheus + Grafana 监控错误率、延迟与资源使用;对 ERROR 关键字设置告警。
- 集中化与结构化
- 将日志汇聚到 ELK/Datadog/New Relic 等平台,统一检索、可视化与链路追踪。