首页 > 解决方案 > Log4j 自定义翻转脚本,用于在文件系统使用率达到一定百分比时删除日志

问题描述

我正在使用 log4j 登录我的应用程序。我想根据文件系统使用情况删除压缩文件。因此,一旦文件系统已满 80%,它应该开始删除旧的压缩文件。Log4j 没有任何可以开箱即用的附加程序,但它具有可以使用的 ScriptCondition。在 log4j 文档中,我只找到了 groovy 脚本(我们的系统上没有安装 groovy)。它还提到javascript,nashorn也可以工作。我编写了以下脚本只是为了查看它是否运行。

<configuration status="trace" name="REST Servlet Logging Configuration">
        <Properties>
                <Property name="xx">xx</Property>
        </Properties>
        <appenders>
                <RollingFile name="xx"
                        fileName="xx"
                        filePattern="xx.log.%i.gz" append="true"
                        bufferedIO="true" immediateFlush="false" fileOwner="xx"
                        fileGroup="xx" filePermissions="rw-r-----">
                        <Policies>
                                <SizeBasedTriggeringPolicy size="4 MB" />
                        </Policies>
                        <DefaultRolloverStrategy max="100" fileIndex="min">
                        <Delete basePath="${xx}" maxDepth="1">
                        <ScriptCondition>
                        <Script name="superstitious" language="javascript"><![CDATA[
                             var  exec  = require('child_process');
                                exec("df -h / | tail -1 | tr -s ' ' | cut -d' ' -f4", (error, stdout, stderr) => {
                                        if(error) {
                                                 console.log('error: ${error.message}');
                                                 return;
                                         }
                                        if(stderr) {
                                                console.log('stderr: ${stderr}');
                                                return;
                                        }
                                         console.log('stdout: ${stdout}');
                                        statusLogger.trace("stdout in trace :${stdout}");
                                });
                            statusLogger.trace("running javascript");
                            result;
                        ]]>
                        </Script>
                    </ScriptCondition>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

在日志中我可以看到提到了 javascript,但错误地我得到了 nashorn 异常。

05:58:46 UTC 2021 DEBUG createScript(name="superstitious", language="javascript", scriptText="var  exec  = require('child_process');
2021-11-02T05:58:47.197Z exec("df -h / | tail -1 | tr -s ' ' | cut -d' ' -f4", (error, stdout, stderr) => {
2021-11-02T05:58:47.197Z if(error) {
2021-11-02T05:58:47.197Z console.log('error: ${error.message}');
2021-11-02T05:58:47.197Z return;
2021-11-02T05:58:47.197Z }
2021-11-02T05:58:47.197Z if(stderr) {
2021-11-02T05:58:47.197Z console.log('stderr: ${stderr}');
2021-11-02T05:58:47.197Z return;
2021-11-02T05:58:47.197Z }
2021-11-02T05:58:47.197Z console.log('stdout: ${stdout}');
2021-11-02T05:58:47.197Z statusLogger.trace("stdout in trace :${stdout}");
2021-11-02T05:58:47.197Z });

但我得到以下异常

2021-11-02T06:00:41.581Z 2021-02-11 06:00:41,575 Log4j2-TF-1-RollingFileManager-1 ERROR Error running script superstitious javax.script.ScriptException: <eval>:3:11 Expected : but found (
2021-11-02T06:00:41.581Z if(error) {
2021-11-02T06:00:41.582Z ^ in <eval> at line number 3 at column number 11
2021-11-02T06:00:41.582Z at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:482)
2021-11-02T06:00:41.582Z at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:549)
2021-11-02T06:00:41.582Z at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:536)
2021-11-02T06:00:41.582Z at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:414)
2021-11-02T06:00:41.590Z at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:167)
2021-11-02T06:00:41.590Z at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:244)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.script.ScriptManager$MainScriptRunner.execute(ScriptManager.java:239)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.script.ScriptManager$ThreadLocalScriptRunner.execute(ScriptManager.java:269)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.script.ScriptManager$1.run(ScriptManager.java:177)
2021-11-02T06:00:41.590Z at java.security.AccessController.doPrivileged(AccessController.java:678)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.script.ScriptManager.execute(ScriptManager.java:174)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.action.ScriptCondition.selectFilesToDelete(ScriptCondition.java:81)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.action.DeleteAction.callScript(DeleteAction.java:98)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.action.DeleteAction.executeScript(DeleteAction.java:86)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.action.DeleteAction.execute(DeleteAction.java:82)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.action.CompositeAction.execute(CompositeAction.java:74)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$AsyncAction.execute(RollingFileManager.java:486)
2021-11-02T06:00:41.590Z at org.apache.logging.log4j.core.appender.rolling.action.AbstractAction.run(AbstractAction.java:66)
2021-11-02T06:00:41.590Z at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1160)
2021-11-02T06:00:41.590Z at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
2021-11-02T06:00:41.590Z at java.lang.Thread.run(Thread.java:822)
2021-11-02T06:00:41.590Z Caused by: jdk.nashorn.internal.runtime.ParserException: <eval>:3:11 Expected : but found (
2021-11-02T06:00:41.590Z if(error) {
2021-11-02T06:00:41.590Z ^
2021-11-02T06:00:41.590Z at jdk.nashorn.internal.parser.AbstractParser.error(AbstractParser.java:306)
2021-11-02T06:00:41.590Z at jdk.nashorn.internal.parser.AbstractParser.error(AbstractParser.java:291)
2021-11-02T06:00:41.590Z at jdk.nashorn.internal.parser.AbstractParser.expectDontAdvance(AbstractParser.java:362)
2021-11-02T06:00:41.590Z at jdk.nashorn.internal.parser.AbstractParser.expect(AbstractParser.java:349)
2021-11-02T06:00:41.590Z at jdk.nashorn.internal.parser.Parser.propertyAssignment(Parser.java:2309)
2021-11-02T06:00:41.590Z at jdk.nashorn.internal.parser.Parser.objectLiteral(Parser.java:2167)

当我明确提到 javascript 时,我不确定为什么它试图将其编译为 nashorn 脚本。我是脚本新手,所以不确定这里出了什么问题。

根据我的建议,我将 => 更改为功能,我遇到了另一个异常

2021-12-02T06:56:30.192Z 2021-02-12 06:56:30,185 Log4j2-TF-1-RollingFileManager-2 ERROR Error running script superstitious javax.script.ScriptException: ReferenceError: "require" is not defined in <eval> at line number 1
2021-12-02T06:56:30.192Z at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:482)
2021-12-02T06:56:30.192Z at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:438)
2021-12-02T06:56:30.192Z at jdk.nashorn.api.scripting.NashornScriptEngine.access$300(NashornScriptEngine.java:85)
2021-12-02T06:56:30.192Z at jdk.nashorn.api.scripting.NashornScriptEngine$3.eval(NashornScriptEngine.java:526)
2021-12-02T06:56:30.192Z at javax.script.CompiledScript.eval(CompiledScript.java:103)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.script.ScriptManager$MainScriptRunner.execute(ScriptManager.java:232)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.script.ScriptManager$ThreadLocalScriptRunner.execute(ScriptManager.java:269)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.script.ScriptManager$1.run(ScriptManager.java:177)
2021-12-02T06:56:30.192Z at java.security.AccessController.doPrivileged(AccessController.java:678)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.script.ScriptManager.execute(ScriptManager.java:174)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.action.ScriptCondition.selectFilesToDelete(ScriptCondition.java:81)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.action.DeleteAction.callScript(DeleteAction.java:98)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.action.DeleteAction.executeScript(DeleteAction.java:86)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.action.DeleteAction.execute(DeleteAction.java:82)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.action.CompositeAction.execute(CompositeAction.java:74)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$AsyncAction.execute(RollingFileManager.java:486)
2021-12-02T06:56:30.192Z at org.apache.logging.log4j.core.appender.rolling.action.AbstractAction.run(AbstractAction.java:66)
2021-12-02T06:56:30.192Z at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1160)
2021-12-02T06:56:30.192Z at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
2021-12-02T06:56:30.192Z at java.lang.Thread.run(Thread.java:822)
2021-12-02T06:56:30.192Z Caused by: <eval>:1 ReferenceError: "require" is not defined
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:69)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:331)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:303)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.objects.Global.__noSuchProperty__(Global.java:1454)
2021-12-02T06:56:30.192Z at java.lang.invoke.DirectHandle.invokeExact_thunkArchetype_L(DirectHandle.java:302)
2021-12-02T06:56:30.192Z at java.lang.invoke.AsTypeHandle.invokeExact_thunkArchetype_X(AsTypeHandle.java:49)
2021-12-02T06:56:30.192Z at java.lang.invoke.BruteArgumentMoverHandle.invokeExact_thunkArchetype_X(BruteArgumentMoverHandle.java:404)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.scripts.Script$1$^eval_.:program(<eval>:1)
2021-12-02T06:56:30.192Z at java.lang.invoke.DirectHandle.invokeExact_thunkArchetype_L(DirectHandle.java:302)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:649)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:506)
2021-12-02T06:56:30.192Z at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:405)
2021-12-02T06:56:30.192Z at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:433)

标签: javascriptlog4jlog4j2nashorn

解决方案


我认为这是因为您正在尝试使用箭头函数,它是 ECMAScript 6 构造,而 Nashorn 默认为 ECMAScript 5.1。

您可以尝试使用,function (error, stdout, stderr) { … }而不是(error, stdout, stderr) => { … },我相信会奏效。

TL;博士:

Nashorn 确实支持 ES6 的一个不错的子集,但需要使用嵌入通常不支持的标志来启用它,因为您需要超出javax.scriptAPI 并使用 Nashorn 自己的 API, NashornScriptEngineFactory.getScriptEngine(String...)您可以在其中传递这些标志,所以它会是

ScriptEngine engine = NashornScriptEngineFactory.getScriptEngine("--language=es6");
...

FWIW,如果您要求语言为“ecmascript-6”或类似语言,我们提供一个 ES6 默认引擎是有意义的。我会考虑的。


推荐阅读