Ubuntu Node.js 日志定位问题的高效流程
一 定位日志来源与实时查看
- 先确认日志在哪里:应用常把日志写到项目下的 logs/ 目录(如 error.log、combined.log),也可能由 PM2 托管输出,或写入 systemd/journald,甚至进入系统日志 /var/log/syslog。
- 快速查看与跟踪的常用命令:
- 应用文件日志:
- 查看目录:ls -l logs
- 实时跟踪:tail -f logs/error.log
- PM2 托管:
- 实时查看:pm2 logs
- 指定应用:pm2 logs <app_name_or_id>
- 最近 N 行:pm2 logs --lines 1000
- systemd 服务:
- 实时跟踪:journalctl -u <service_name> -f
- 最近 10 分钟:journalctl -u <service_name> --since “10 minutes ago”
- 系统日志:sudo tail -f /var/log/syslog
- 建议优先从应用日志入手,再结合 PM2 或 journald 查看进程生命周期与系统层面的异常。
二 关键字筛选与堆栈定位
- 按级别与关键词快速缩小范围:
- 过滤错误:grep -i “error” logs/error.log
- 精确匹配:grep -i “specific error message” logs/error.log
- 关注警告:pm2 logs your-app --lines 50 | grep WARN
- 解读堆栈与上下文:
- 找到日志中的 堆栈跟踪(stack trace),从最上层业务调用向下看,定位到抛出异常的 文件:行号。
- 结合 时间戳 与 请求ID/用户ID/错误码 等字段,还原同一次请求的前后调用链,避免只看单条孤立日志。
- 小技巧:对 JSON 格式日志 可用 jq 提取字段,例如:
- 按级别统计:jq ‘select(.level==“error”) | .message’ combined.log | sort | uniq -c | sort -nr
三 常见错误一键排查
- 端口被占用 EADDRINUSE:
- 查占用:sudo lsof -i :<端口号>
- 释放:sudo kill -9
- 模块未找到 Module not found:npm install <模块名>
- 语法错误 SyntaxError:检查对应文件的语法与依赖版本
- 未处理的 Promise 拒绝:
- 给每个 Promise 加 .catch() 或用 try/catch
- 临时兜底:process.on(“unhandledRejection”, (reason) => console.error(reason))
- 监听器泄漏 MaxListenersExceededWarning:
- 检查重复添加监听器的逻辑,必要时 myEmitter.setMaxListeners(20) 并 removeListener 清理
- 内存不足 JavaScript heap out of memory:
- 临时提升:node --max-old-space-size=4096 app.js
- 排查泄漏:clinic doctor – node app.js
- 过时 API 警告(如 Buffer()):升级 Node.js 与依赖,按官方建议改用 Buffer.alloc() 等新 API
四 提升日志可读性与后续预防
- 结构化与多级别日志:使用 winston/morgan/pino 输出 JSON,并按 error/warn/info/debug 分级,便于检索与聚合。
- 日志轮转与保留:
- 应用侧:winston-daily-rotate-file(按天/大小切分、压缩、保留天数)
- 系统侧:/etc/logrotate.d/nodejs(示例:daily、rotate 7、compress、create 0640 root adm)
- 集中式日志与可视化:搭建 ELK Stack(Elasticsearch/Logstash/Kibana) 或 Graylog,统一采集、解析与检索。
- 监控与告警:接入 Prometheus + Grafana 做指标与错误趋势监控,结合阈值告警。
五 高效排查命令清单
- 实时看应用日志:tail -f logs/error.log
- 查最近 100 行并过滤错误:tail -n 100 logs/combined.log | grep -i error
- PM2 实时看某应用错误:pm2 logs --lines 200 | grep -i error
- 查最近 10 分钟服务日志:journalctl -u --since “10 minutes ago” -f
- 统计错误数量:grep -i “error” logs/combined.log | wc -l
- 按时间窗口提取日志:awk ‘/2025-12-17 10:00:00/,/2025-12-17 11:00:00/’ logs/combined.log
- 端口占用定位:sudo lsof -i :3000
- JSON 日志按级别统计错误数:jq ‘select(.level==“error”) | .message’ combined.log | sort | uniq -c | sort -nr