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

集成OpenTelemetry时,Gradle启动脚本$ENV未正确求值的解决方法

问题:Gradle生成的启动脚本中环境变量$ENV无法被正确求值

我使用gradle installDist任务准备要复制到Docker镜像的文件,为集成OpenTelemetry Agent,最初的Gradle配置如下:

application {
    mainClass.set("com.vincent.AppKt")
    applicationDefaultJvmArgs = listOf("-javaagent:../lib/opentelemetry-javaagent-$openTelemetryJavaAgentVersion.jar")
}

后续需要根据环境(staging或prod)加载不同的属性文件,于是修改配置为:

application {
    mainClass.set("com.vincent.AppKt")
    applicationDefaultJvmArgs = listOf(
        "-javaagent:../lib/opentelemetry-javaagent-$openTelemetryJavaAgentVersion.jar",
        "-Dotel.javaagent.configuration-file=../$ENV-otel.properties"
    )
}

tasks {
    register("replaceInInstallDist") {
        dependsOn("installDist")

        doLast {
            val buildDir = file("${buildDir}/install/${project.name}")
            val scriptFile = file("${buildDir}/bin/${project.name}")

            scriptFile.writeText(scriptFile.readText().replace("\\\$ENV", "\$ENV"))
        }
    }
}

生成的启动脚本中,DEFAULT_JVM_OPTS看起来符合预期:

DEFAULT_JVM_OPTS='"-javaagent:../lib/opentelemetry-javaagent-2.0.0.jar" "-Dotel.javaagent.configuration-file=../$ENV-otel.properties"'

但在容器中启动应用时,日志报错找不到配置文件:

ERROR io.opentelemetry.javaagent.tooling.config.ConfigurationPropertiesSupplier - Configuration file "../$ENV-otel.properties" not found.

奇怪的是,直接用命令行启动却能正常运行:

java -jar myJar.jar -javaagent:../lib/opentelemetry-javaagent-2.0.0.jar -Dotel.javaagent.configuration-file=../$ENV-otel.properties

问题出在生成的启动脚本使用exec "$JAVACMD" "$@"启动应用,包含$ENV的参数被包裹在$@中,无法被Shell正确解析求值。


解决方案

方案1:调整启动脚本的引号结构,让变量可被解析

修改replaceInInstallDist任务,调整参数的引号包裹方式,让$ENV能被Shell识别并求值:

tasks {
    register("replaceInInstallDist") {
        dependsOn("installDist")

        doLast {
            val buildDir = file("${buildDir}/install/${project.name}")
            val scriptFile = file("${buildDir}/bin/${project.name}")
            
            val originalContent = scriptFile.readText()
            val modifiedContent = originalContent
                // 移除参数的内层引号,同时替换转义的$ENV
                .replace("\"-Dotel.javaagent.configuration-file=../\\\$ENV-otel.properties\"", "-Dotel.javaagent.configuration-file=../\$ENV-otel.properties")
                // 把DEFAULT_JVM_OPTS的单引号替换为双引号,支持变量解析
                .replace("DEFAULT_JVM_OPTS='", "DEFAULT_JVM_OPTS=\"")
                .replace("'", "\"")
            
            scriptFile.writeText(modifiedContent)
        }
    }
}

修改后,启动脚本中的DEFAULT_JVM_OPTS会变为:

DEFAULT_JVM_OPTS=" -javaagent:../lib/opentelemetry-javaagent-2.0.0.jar -Dotel.javaagent.configuration-file=../$ENV-otel.properties"

Shell执行时会自动解析$ENV为实际环境值。

方案2:在启动脚本中添加变量解析逻辑

通过在启动脚本中提前解析$ENV变量,再赋值给DEFAULT_JVM_OPTS:

tasks {
    register("replaceInInstallDist") {
        dependsOn("installDist")

        doLast {
            val buildDir = file("${buildDir}/install/${project.name}")
            val scriptFile = file("${buildDir}/bin/${project.name}")
            
            val originalContent = scriptFile.readText()
            val modifiedContent = originalContent.replace(
                "DEFAULT_JVM_OPTS='\"-javaagent:../lib/opentelemetry-javaagent-2.0.0.jar\" \"-Dotel.javaagent.configuration-file=../\\\$ENV-otel.properties\"'",
                """
                DEFAULT_JVM_OPTS_BASE='"-javaagent:../lib/opentelemetry-javaagent-2.0.0.jar" "-Dotel.javaagent.configuration-file=../${'$'}ENV-otel.properties"'
                DEFAULT_JVM_OPTS=$(eval echo "$DEFAULT_JVM_OPTS_BASE")
                """.trimIndent()
            )
            
            scriptFile.writeText(modifiedContent)
        }
    }
}

脚本会先通过eval解析DEFAULT_JVM_OPTS_BASE中的$ENV,再将结果赋值给DEFAULT_JVM_OPTS,确保启动时使用正确的参数。

方案3:Docker启动时动态传递参数(推荐)

完全避开Gradle生成脚本的引号问题,不在Gradle配置中硬编码属性文件路径,而是在Docker启动命令中动态添加:

CMD ["sh", "-c", "java -javaagent:../lib/opentelemetry-javaagent-2.0.0.jar -Dotel.javaagent.configuration-file=../$ENV-otel.properties -jar myJar.jar"]

由Shell直接解析$ENV变量,逻辑更清晰,也避免了Gradle配置的复杂修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:13:16