You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

老旧Node.js应用基于forever-monitor的12小时日志轮转方案咨询

Hey there! 针对你用forever-monitor管理老旧Node.js应用子进程日志、需要每12小时自动轮转归档的需求,我给你整理了几个Node.js生态里常用且靠谱的npm库,还有具体的实现思路,帮你避开依赖系统logrotate的麻烦:

推荐的Node.js日志轮转方案

1. rotating-file-stream(最推荐,轻量专注轮转)

这个库是专门做日志轮转的轻量工具,完全贴合你不想依赖系统工具的需求,用起来也很直接。它可以直接接管forever-monitor的日志输出流,自动完成每12小时的归档、重命名和清空操作。

具体实现步骤:

  • 先安装库:npm install rotating-file-stream
  • 配置轮转流,指定归档目录和带时间戳的文件名规则:
    const rfs = require('rotating-file-stream');
    const path = require('path');
    const fs = require('fs');
    
    // 确保归档目录存在,不存在就创建
    const archiveDir = path.join(__dirname, '../logs/archives');
    fs.mkdirSync(archiveDir, { recursive: true });
    
    // 生成带时间戳的归档文件名
    const getOutputFilename = (time) => {
      if (!time) return 'childprocess_output.log'; // 当前活跃的日志文件名
      const timestamp = time.getTime();
      return `childprocess_output_${timestamp}.log`;
    };
    
    // 创建输出日志的轮转流:每12小时轮转,归档到指定目录
    const outStream = rfs.createStream(getOutputFilename, {
      interval: '12h', // 轮转间隔设为12小时
      path: archiveDir,
      size: '0', // 只按时间轮转,忽略文件大小
      compress: false, // 需要压缩归档文件的话可以改成'gzip'
      maxFiles: 0, // 0表示不限制归档文件数量,按需调整
      initialRotation: false // 启动时不立即触发轮转
    });
    
    // 同样配置错误日志的轮转流
    const getErrFilename = (time) => {
      if (!time) return 'childprocess_error.log';
      const timestamp = time.getTime();
      return `childprocess_error_${timestamp}.log`;
    };
    
    const errStream = rfs.createStream(getErrFilename, {
      interval: '12h',
      path: archiveDir,
      size: '0'
    });
    
  • 修改forever-monitor的配置,把子进程的输出导向我们的轮转流:
    const forever = require('forever-monitor');
    
    var child = new (forever.Monitor)(__dirname + '/../lib/childprocess.js', {
      max: 3,
      silent: false, // 关闭forever自带的文件写入,我们自己处理流
      options: [program.port]
    });
    
    // 把子进程的标准输出和错误输出分别导向轮转流
    child.stdout.pipe(outStream);
    child.stderr.pipe(errStream);
    
    child.start();
    

这样配置后,每12小时库会自动把当前的childprocess_output.log归档到archives目录,重命名为带时间戳的文件,然后创建新的空日志文件继续写入,完全符合你的需求。

2. winston + winston-daily-rotate-file(适合需要扩展日志功能的场景)

如果你的应用未来可能需要更复杂的日志处理(比如分级别日志、多输出目标),可以用Winston这个成熟的日志框架,搭配它的winston-daily-rotate-file插件,支持按时间、大小轮转,还能自定义文件名格式。

实现思路:

  • 安装依赖:npm install winston winston-daily-rotate-file
  • 配置Winston日志实例,设置轮转规则:
    const winston = require('winston');
    const { DailyRotateFile } = require('winston-daily-rotate-file');
    const path = require('path');
    const fs = require('fs');
    
    const archiveDir = path.join(__dirname, '../logs/archives');
    fs.mkdirSync(archiveDir, { recursive: true });
    
    // 配置输出日志的轮转transport
    const outputLogger = winston.createLogger({
      transports: [
        new DailyRotateFile({
          filename: 'childprocess_output_%TIMESTAMP%.log',
          datePattern: 'YYYY-MM-DD_HH', // 按小时区分,适配12小时轮转
          frequency: '12h', // 每12小时轮转一次
          maxFiles: '30d', // 保留30天的归档日志,按需调整
          dirname: archiveDir,
          createSymlink: true,
          symlinkName: path.join(__dirname, '../childprocess_output.log') // 软链接指向当前活跃日志
        })
      ]
    });
    
    // 同样配置错误日志的轮转transport
    const errorLogger = winston.createLogger({
      transports: [
        new DailyRotateFile({
          filename: 'childprocess_error_%TIMESTAMP%.log',
          datePattern: 'YYYY-MM-DD_HH',
          frequency: '12h',
          maxFiles: '30d',
          dirname: archiveDir,
          createSymlink: true,
          symlinkName: path.join(__dirname, '../childprocess_error.log')
        })
      ]
    });
    
  • 把forever子进程的输出传给Winston处理:
    var child = new (forever.Monitor)(__dirname + '/../lib/childprocess.js', {
      max: 3,
      silent: false,
      options: [program.port]
    });
    
    // 监听子进程输出,写入Winston日志
    child.stdout.on('data', (data) => {
      outputLogger.info(data.toString().trim());
    });
    
    child.stderr.on('data', (data) => {
      errorLogger.error(data.toString().trim());
    });
    
    child.start();
    

这种方式的好处是Winston提供了更多日志处理能力,比如日志级别、格式化等,但比单纯的轮转库稍重,适合需要扩展日志功能的场景。

3. logrotate-stream(轻量流式轮转备选)

这个库也是专注于流式日志轮转,用法简洁,支持按时间或大小轮转,适合追求轻量的场景。

简单示例:

const logrotate = require('logrotate-stream');
const path = require('path');
const fs = require('fs');

const archiveDir = path.join(__dirname, '../logs/archives');
fs.mkdirSync(archiveDir, { recursive: true });

// 创建输出日志的轮转流
const outStream = logrotate({
  file: path.join(__dirname, '../childprocess_output.log'),
  rotate: '12h',
  size: '0', // 禁用按大小轮转
  keep: 0, // 保留所有归档文件
  compress: false,
  // 自定义归档文件名和路径
  rename: (filename) => {
    const timestamp = Date.now();
    return path.join(archiveDir, `childprocess_output_${timestamp}.log`);
  }
});

// 同样配置错误日志流,然后pipe到forever的输出
child.stdout.pipe(outStream);

一些注意事项

  • 无论用哪个库,都要确保归档目录存在,可以用fs.mkdirSync(archiveDir, { recursive: true })在启动时自动创建,避免报错。
  • 测试的时候可以把轮转间隔改成1m(1分钟),快速验证功能是否正常。
  • 如果你的forever-monitor版本比较老,要确认它的stdout和stderr流可以正常被pipe,个别老版本可能需要微调配置。

内容的提问来源于stack exchange,提问作者Rito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:40:07