温馨提示×

Ubuntu上Node.js日志如何进行错误追踪

小樊
76
2025-09-26 20:14:45
栏目: 编程语言

Ubuntu上Node.js日志错误追踪的完整流程

一、基础错误日志查看方法

1. 查看Ubuntu系统日志

Ubuntu的系统日志会记录Node.js进程的底层错误(如端口冲突、权限问题),主要存储在/var/log目录下。常用命令包括:

  • cat /var/log/syslog:查看系统综合日志(包含Node.js进程的常规错误);
  • cat /var/log/kern.log:查看内核相关日志(如硬件或驱动问题导致的Node.js崩溃);
  • cat /var/log/error.log:查看系统级错误日志(聚焦严重错误)。
    这些日志能帮助定位与系统环境相关的Node.js问题。

2. 使用journalctl查看进程级日志

若Node.js作为systemd服务运行(如通过systemctl start your-node-service启动),可通过journalctl命令过滤服务相关日志:

journalctl -u your-nodejs-service-name -t "node"  # -u指定服务名,-t过滤"node"标签

该命令会显示服务的实时错误日志(如进程崩溃、未捕获异常),适合生产环境的服务级监控。

3. 查看应用自身日志文件

若应用代码中配置了日志输出(如重定向到文件),可直接查看指定日志文件。例如,若启动命令为:

node app.js > logs/app.log 2>&1 &  # 将标准输出和错误输出重定向到logs/app.log

则可通过以下命令实时跟踪错误日志:

tail -f logs/app.log  # 实时显示日志末尾新增内容

或搜索特定错误关键词(如"Error"):

grep -i "Error" logs/app.log  # -i忽略大小写,筛选含"Error"的行

二、进阶:使用进程管理器增强错误追踪

1. 使用PM2管理进程与日志

PM2是Node.js常用的进程管理器,能自动重启崩溃的进程,并集中管理日志。安装与使用步骤:

  • 全局安装PM2npm install pm2 -g
  • 启动应用pm2 start app.js --name "my-app"--name指定应用名称);
  • 查看日志pm2 logs my-app(实时显示应用日志,包含错误堆栈);
  • 保存日志pm2 save(保存当前进程列表),pm2 startup(生成开机自启脚本)。
    PM2的日志功能简化了生产环境的错误追踪,无需手动管理进程。

三、代码层错误处理与日志记录

1. 配置专业的日志库(以Winston为例)

内置console模块无法满足生产环境需求,推荐使用Winston(功能丰富)或Bunyan(结构化日志)记录错误。以Winston为例:

  • 安装Winstonnpm install winston
  • 配置日志级别与传输
    const winston = require('winston');
    const logger = winston.createLogger({
      level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug', // 生产环境仅记录warn及以上
      format: winston.format.json(), // 结构化日志(便于后续分析)
      transports: [
        new winston.transports.File({ filename: 'logs/error.log', level: 'error' }), // 错误日志单独存储
        new winston.transports.File({ filename: 'logs/combined.log' }), // 所有日志汇总
      ],
    });
    
    // 示例:捕获同步错误
    try {
      // 业务代码(可能抛出错误)
    } catch (error) {
      logger.error('同步错误捕获:', { message: error.message, stack: error.stack }); // 记录错误信息与堆栈
    }
    
    // 全局捕获未处理异常
    process.on('uncaughtException', (error) => {
      logger.error('未捕获异常:', { message: error.message, stack: error.stack });
      process.exit(1); // 强制退出进程(避免不可控状态)
    });
    
    // 全局捕获未处理Promise rejection
    process.on('unhandledRejection', (reason, promise) => {
      logger.error('未处理Promise rejection:', { reason, promise });
    });
    
    通过配置,可将错误日志分级存储(如error.log仅存严重错误),并添加上下文信息(如堆栈、请求ID),便于快速定位问题。

2. 关键位置记录错误日志

  • HTTP请求中间件:在Express/Koa中,通过中间件记录请求错误:
    app.use((err, req, res, next) => {
      logger.error(`请求错误 [${req.method} ${req.url}]:`, { error: err.message, stack: err.stack });
      res.status(500).send('Internal Server Error');
    });
    
  • 业务逻辑关键点:在数据库操作、第三方API调用等易出错环节记录错误:
    await database.query('SELECT * FROM users')
      .catch(error => logger.error('数据库查询失败:', { query: 'SELECT * FROM users', error: error.message }));
    

四、优化错误追踪的实用技巧

1. 使用结构化日志

将日志格式化为JSON(如Winston的json()格式化),便于后续用ELK Stack、Graylog等工具分析。例如:

{
  "level": "error",
  "message": "数据库连接失败",
  "timestamp": "2025-09-26T10:00:00Z",
  "database": "mysql",
  "error": "Connection refused"
}

结构化日志能快速筛选、聚合错误信息,提升分析效率。

2. 日志轮转避免文件过大

使用winston-daily-rotate-file插件自动分割日志文件(如按天分割),避免单个日志文件过大:

const DailyRotateFile = require('winston-daily-rotate-file');
const transport = new DailyRotateFile({
  filename: 'logs/application-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  maxSize: '20m', // 单个文件最大20MB
  maxFiles: '14d', // 保留14天日志
});

const logger = winston.createLogger({
  transports: [transport],
});

3. 集成第三方日志服务

将日志发送到Sentry、Loggly等平台,实现实时报警与远程分析:

  • Sentry示例
    const Sentry = require('@sentry/node');
    Sentry.init({ dsn: 'your-sentry-dsn' });
    app.use(Sentry.Handlers.errorHandler()); // Express错误处理中间件
    
    // 记录错误到Sentry
    logger.error('严重错误:', { error: new Error('Something went wrong') });
    Sentry.captureException(new Error('Something went wrong')); // 发送到Sentry
    

五、常见错误排查步骤

  1. 端口占用:若错误为"EADDRINUSE",用sudo lsof -i :3000查看占用进程,用kill -9 <PID>终止进程;
  2. 依赖缺失:若错误为"Module not found",用npm install missing-module安装缺失依赖;
  3. 环境变量未设置:若错误为"process.env.DB_URL is undefined",用export DB_URL=your_url设置环境变量;
  4. 代码逻辑错误:若错误为"TypeError"或"ReferenceError",检查代码中的变量定义与类型使用。

0