温馨提示×

如何在Ubuntu中设置Node.js日志

小樊
43
2025-12-11 23:26:48
栏目: 编程语言

在 Ubuntu 中设置 Node.js 日志的完整实践

一 基础方案选择

  • 使用 console.log / console.error / console.warn:开发调试最简单,直接输出到标准输出/错误。
  • 使用日志库:
    • winston:功能全面,支持多传输(控制台、文件、HTTP 等)、结构化日志。
    • morgan:Express 的 HTTP 请求日志中间件,常与文件流结合落盘。
    • pino:高性能,适合生产环境。
    • log4js:配置灵活,支持按文件/日期切分与多输出。
  • 使用进程管理工具:
    • PM2:内置日志管理(合并/分离输出、按应用查看)。
    • systemd:将应用日志接入 journald/syslog,便于集中查看与轮转。

二 应用内日志配置示例

  • 使用 winston 输出到控制台与文件(按级别分流)

    • 安装:npm install winston
    • 配置与使用示例:
      const winston = require('winston');
      
      const logger = winston.createLogger({
        level: process.env.LOG_LEVEL || 'info',
        format: winston.format.combine(
          winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
          winston.format.json()
        ),
        transports: [
          new winston.transports.File({ filename: 'error.log', level: 'error' }),
          new winston.transports.File({ filename: 'combined.log' }),
        ],
      });
      
      if (process.env.NODE_ENV !== 'production') {
        logger.add(new winston.transports.Console({
          format: winston.format.simple()
        }));
      }
      
      logger.info('Hello World');
      logger.error('Something went wrong');
      
    • 运行时动态设置级别:LOG_LEVEL=debug node app.js
  • 使用 morgan 记录 Express HTTP 请求日志到文件

    • 安装:npm install morgan
    • 配置与使用示例:
      const express = require('express');
      const morgan = require('morgan');
      const fs = require('fs');
      const path = require('path');
      
      const accessLogStream = fs.createWriteStream(
        path.join(__dirname, 'access.log'), { flags: 'a' }
      );
      
      const app = express();
      app.use(morgan('combined', { stream: accessLogStream }));
      
      app.get('/', (req, res) => res.send('Hello World'));
      app.listen(3000, () => console.log('Server on 3000'));
      
    • 提示:生产环境建议将访问日志与业务日志分离,便于排查与审计。
  • 使用 log4js 按类别与日期切分输出

    • 安装:npm install log4js
    • 配置与使用示例:
      const log4js = require('log4js');
      const path = require('path');
      
      log4js.configure({
        appenders: {
          console: { type: 'console' },
          file: {
            type: 'file',
            filename: path.join(__dirname, 'logs', 'app.log'),
            maxLogSize: 10 * 1024 * 1024, // 10MB
            backups: 5,
            encoding: 'utf-8'
          },
          dateFile: {
            type: 'dateFile',
            filename: path.join(__dirname, 'logs', 'app'),
            pattern: '.yyyy-MM-dd.log',
            alwaysIncludePattern: true,
            compress: true
          }
        },
        categories: {
          default: { appenders: ['console', 'file', 'dateFile'], level: 'debug' }
        }
      });
      
      const logger = log4js.getLogger();
      logger.info('Hello log4js');
      logger.error('Oops');
      
    • 说明:log4js 支持 console/file/dateFile 等类型,可按大小或日期切分并压缩归档。

三 运行方式与系统日志集成

  • 使用 PM2 管理进程与日志
    • 安装:npm install -g pm2
    • 启动:pm2 start app.js --name my-app
    • 查看:pm2 logs my-app(实时查看),pm2 logs my-app --err(仅错误),pm2 logs my-app --out(仅标准输出)
    • 日志文件:默认写入 ~/.pm2/logs/;也可在 ecosystem.config.js 中自定义:
      module.exports = {
        apps: [{
          name: 'my-app',
          script: 'app.js',
          out_file: 'logs/out.log',
          error_file: 'logs/err.log',
          combine_logs: false
        }]
      };
      
  • 使用 systemd 将日志写入 journald/syslog
    • 创建服务文件:/etc/systemd/system/myapp.service
      [Unit]
      Description=My Node.js App
      After=network.target
      
      [Service]
      Type=simple
      User=www-data
      WorkingDirectory=/opt/myapp
      ExecStart=/usr/bin/node /opt/myapp/app.js
      Restart=always
      StandardOutput=journal
      StandardError=journal
      SyslogIdentifier=myapp
      
      [Install]
      WantedBy=multi-user.target
      
    • 常用查看命令:
      • sudo systemctl daemon-reload && sudo systemctl enable --now myapp
      • journalctl -u myapp -f(实时查看)
      • journalctl -u myapp --since "2025-12-11 00:00:00"
    • 说明:也可将 StandardOutput/StandardError 设为 syslog 并配合 SyslogIdentifier 使用。

四 日志轮转与保留策略

  • 使用 logrotate(系统级,推荐与文件日志搭配)
    • 新建配置:/etc/logrotate.d/myapp
      /opt/myapp/logs/*.log {
        daily
        rotate 14
        compress
        delaycompress
        missingok
        notifempty
        create 640 www-data www-data
        copytruncate
      }
      
    • 说明:
      • daily 每日轮转;rotate 14 保留 14 份;compress 压缩归档;copytruncate 避免应用持有文件句柄(适合不支持信号重新打开日志的程序)。
      • 测试:sudo logrotate -d /etc/logrotate.d/myapp(语法检查),sudo logrotate -f /etc/logrotate.d/myapp(强制执行一次)。
  • 使用 winston-daily-rotate-file(应用内轮转)
    • 安装:npm install winston-daily-rotate-file
    • 配置示例:
      const DailyRotateFile = require('winston-daily-rotate-file');
      const transport = new DailyRotateFile({
        filename: 'logs/application-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '20m',
        maxFiles: '14d'
      });
      
      const logger = winston.createLogger({
        level: 'info',
        format: winston.format.json(),
        transports: [transport, new winston.transports.Console({ format: winston.format.simple() })]
      });
      
    • 说明:按日期与大小切分,自动压缩与保留策略更灵活。

五 生产环境建议

  • 明确日志级别(如 error/warn/info/debug),通过环境变量(如 LOG_LEVEL)在不同环境切换,避免生产输出过多 debug
  • 结构化日志(如 JSON)便于检索与聚合,配合 timestamp 统一时间格式。
  • 访问日志与业务日志分离,便于审计与性能分析。
  • 统一日志目录与权限,确保运行用户(如 www-data)可写。
  • 配置合理的保留周期与压缩策略,防止磁盘被占满。
  • 集中式日志:将日志发送到 ELK Stack(Elasticsearch/Logstash/Kibana)Graylog,便于检索、可视化与告警。

0