【问题标题】:redirect output to rolling file将输出重定向到滚动文件
【发布时间】:2012-05-07 06:38:54
【问题描述】:

有很多示例如何将程序输出重定向到文件。
我需要设置文件的最大大小并滚动文件(消失旧消息)或备份旧文件并开始记录到新文件。

有没有办法使用操作系统核心的东西来做到这一点?

我的客户对我每个应用程序创建日志文件并在那里记录所有标准输出感到困惑。
该应用程序是长时间运行的应用程序,包含多个模块,这些模块在不同的 JVM 中启动(换句话说,这些是多个应用程序)并使用相同的 log4j.properties 文件。
我正在使用 java 和 log4j,但 log4j 日志每个包不是每个应用程序。而且它不适合我,因为两个模块可以具有相同的包(记录器类别)但应该被定向到不同的文件。
应用程序模块使用 .sh 脚本启动。

谢谢

【问题讨论】:

  • 如果您可以登录到运行 SYSLOG 的服务器,您可以使用 log4j org.apache.log4j.net.SyslogAppender 将所有日志消息从所有进程发送到 SYSLOG。 (这是我们应用程序的标准)。在 syslog-ng.conf 文件中,您可以配置 syslog 以将所有这些消息发送到单个文件。如果这对你有用,我可以提供更多细节。

标签: java linux bash log4j


【解决方案1】:

This 最适合我(将 System.err 和 System.out 重定向到同一个日志文件,按大小拆分文件):

java MyApp 2>&1 | split -b500k - out.log

谢谢,大家投票赞成;)

【讨论】:

    【解决方案2】:

    您可以让 log4j 在您的情况下使用不同的文件,具体取决于您的日志记录配置中的系统属性。 (此附加程序可在 log4j extras 项目中找到)例如

      <appender name="R2" class="org.apache.log4j.rolling.RollingFileAppender">
        <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
          <param name="FileNamePattern" value="logs/log_${appName}.log.%d" />
          <param name="ActiveFileName" value="logs/log_${appName}.log" />
        </rollingPolicy>
        <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%d [%t] %c -\n  %-5p: %m%n" />
        </layout>
      </appender>
    

    参见${appName}:您可以使用-DappName=MyApp 将其作为启动参数传递给虚拟机。您也可以在运行时使用System.setProperty(.., ..) 进行设置,但这必须在 log4j 初始化之前进行。您的启动器进程决定了该属性的价值。

    您将拥有类似于 log_MyApp.log 的日志文件。

    编辑:对不起,我错过了您正在使用属性文件并想要基于大小的滚动策略的事实。在这个文件中你可以写(但实际的技巧是一样的):

    log4j.appender.R=org.apache.log4j.RollingFileAppender
    log4j.appender.R.File={myApp}.log
    log4j.appender.R.MaxFileSize=100KB
    log4j.appender.R.MaxBackupIndex=1
    

    这个更完整:http://logging.apache.org/log4j/1.2/manual.html :)

    【讨论】:

    • 命名应用程序模块并在 log4j.properties 中使用它是个好主意,然后就是创建额外的过滤器了,谢谢。
    【解决方案3】:

    log4j 不会基于包进行登录。您可以为其提供任何您喜欢的名称。

    在您的 log4j.xml 中,添加以下内容:

    <appender name="USERACTION" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="/var/logs/useraction.log" />
        <param name="DatePattern" value="'.'yyyy-MM-dd" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d%m%n" />
        </layout>
    </appender>
    
    <logger name="UserAction" additivity="false">
        <level value="INFO" />
        <appender-ref ref="USERACTION" />
    </logger>
    

    现在像这样实例化您的记录器:

    private final static Logger LOG = Logger.getLogger("UserAction");
    

    记录到这个记录器的所有内容都将进入文件 useraction.log。你看到相关性了吗?

    在当前类之后命名记录器只是方便,但绝不是强制性的。

    我经常使用它来区分日志条目。我的一些类有多个记录器实例,例如一个用于用户操作、一个用于低级内容、一个用于服务调用等等。

    【讨论】:

    • 只是不同的名字。像 JmsSenderLoggerModule1 和 JmsSenderLoggerModule2。如果愿意,您甚至可以将名称设为变量字符串。
    • 不适合我。例如,我在两个模块中都有 org.mycompany.communication.jms.Sender 。即使使用“JmsSenderLogger”,我也无法将输出定向到不同的文件,因为两个模块都使用相同的 log4j.properties。
    • 这是两个模块使用的同一个类。为该类创建多个记录器是没有用的。甚至通过创建 java 也不知道如何区分该类被多个应用程序使用。您是否建议将课程复制到多个模块中?..
    • 不,但是您肯定有某种属性/可能性来检测该类在哪个模块中运行,不是吗?然后只需按照我之前评论中的建议命名记录器变量的名称。像 Logger LOG = Logger.getLogger(getCurrentModule().toString());
    • 不,我的问题的分析器 有没有办法使用操作系统核心的东西来做到这一点? 在这里:stackoverflow.com/questions/9189504/…。而且您的解决方案需要重新设计大量代码。
    【解决方案4】:

    如果您的应用程序可以登录到stdout,那么有许多工具可以提供帮助,例如:

    • rotatelogs,Apache 的一部分。这从stdin 读取并根据时间写入日志文件;它负责根据需要更改日志文件。您可以使用find -mtime ...等简单工具清理旧日志文件。

    • svlogdrunit 的一部分。这类似于rotatelogs,但会根据需要自动删除旧文件,并且更多地处理大小限制而不是基于时间的轮换。

    • 如果您在 supervisor 等进程管理器下运行程序,则进程管理器可以处理日志输出、滚动日志文件等。

    还有许多其他类似的解决方案……我相信也有许多特定于 Java 的想法,但我会留给其他人。

    【讨论】:

      猜你喜欢
      • 2012-05-21
      • 2016-08-09
      • 2013-10-11
      • 2023-03-19
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      相关资源
      最近更新 更多