将输出重定向到滚动文件

4

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

是否有任何方法可以使用操作系统核心内容实现这一点?

我的客户让我创建每个应用程序的日志文件,并记录所有std out。
该应用程序是长时间运行的应用程序,并包含几个模块,这些模块在不同的JVM中启动(换句话说,这些是其他应用程序),并使用相同的log4j.properties文件。
我正在使用Java和log4j,但是log4j按软件包而非按应用程序记录。对我来说不太适合,因为两个模块可能具有相同的软件包(日志记录器类别),但应被定向到不同的文件中。
应用程序模块使用.sh脚本启动。

谢谢


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

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。如果你喜欢,甚至可以将名称作为变量字符串。 - Dariop
对我来说不适用。例如,我在两个模块中都有org.mycompany.communication.jms.Sender。即使使用“JmsSenderLogger”,我也无法将输出直接定向到不同的文件,因为两个模块都使用相同的log4j.properties。 - Mike
这是两个模块都使用的同一类。为该类创建多个记录器没有任何用处。即使创建Java程序,也不知道如何区分该类被多个应用程序使用。您是否建议将该类复制粘贴到多个模块中?.. - Mike
不,但是你肯定有某种属性/可能性可以检测类正在运行的模块,对吧?然后只需按照我之前的评论建议,将记录器变量命名。例如:Logger LOG = Logger.getLogger(getCurrentModule().toString()); - Dariop
不,我的问题“是否有任何使用操作系统核心工具来完成这个任务的方法?”的答案在这里:https://dev59.com/M2DVa4cB1Zd3GeqPay47。而你的解决方案需要重新设计大量代码。 - Mike

3
这个最适合我(将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 将其作为启动参数传递给 vm。 您也可以在运行时使用 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文件中使用,然后就可以创建其他过滤器了,谢谢。 - Mike

2
如果您的应用程序可以记录到stdout,那么有许多工具可以帮助您,例如:
  • rotatelogs,Apache的一部分。它从stdin读取并根据时间将其写入日志文件;它会在必要时更改日志文件。您可以使用简单的工具(例如find -mtime ...)清理旧日志文件。

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

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

还有许多类似的解决方案......我相信还有许多专门针对Java的想法,但我会留给其他人来阐述。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接