gradle应用程序插件和系统环境变量 [英] gradle application plugin and system environment variables

查看:76
本文介绍了gradle应用程序插件和系统环境变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我尝试在build.gradle中使用这样的系统环境配置应用程序:

In my project, I tried to configure my application with system environments like this in my build.gradle:

apply plugin: 'application'
applicationDefaultJvmArgs = ["-Ddw.server.applicationConnectors[0].port=${System.env.PORT}"]

如果PORT设置为常数(例如9001),则此方法有效.但是,如果我将PORT更改为另一个变量,则可执行脚本不会更改,它已在build/install/bin中已编译为PORT的旧值. /{executable-script},如下所示:

This works if PORT is set to a constant, lets say 9001. But if I change PORT to another variable, the executable script does not change, it is already compiled to the old value of PORT in the build/install/bin/{executable-script}, like this:

DEFAULT_JVM_OPTS='"-Ddw.server.applicationConnectors[0].port=9001"'

而不是我想要的,

DEFAULT_JVM_OPTS='"-Ddw.server.applicationConnectors[0].port=$PORT"'

是否有某种方法可以告诉应用程序插件使用系统环境变量而不是评估system.env变量?

Is there some way to tell the application plugin to use a system environment variable instead of evaluating the system.env variable?

顺便说一句,我也尝试不使用单引号来避免对$ PORT表达式求值

Btw, I also tried without single-quotes to avoid evaluation of the $PORT expression

applicationDefaultJvmArgs = ['-Ddw.server.applicationConnectors[0].port=$PORT']

applicationDefaultJvmArgs = ['-Ddw.server.applicationConnectors[0].port=\$PORT']

但是这两个都被编译为无法正常工作.

But both of these are compiled to this which will not work.

DEFAULT_JVM_OPTS='"-Ddw.server.applicationConnectors[0].port=\$PORT"'

推荐答案

(我是提交了applicationDefaultJvmArgs功能的Gradle贡献者)

(I'm the Gradle contributor who submitted the applicationDefaultJvmArgs feature)

如果您在applicationDefaultJvmArgs元素中写入"$ {System.env.PORT}",则在构建时即在开发人员机器上,甚至在Gradle看到它之前,都将PORT环境变量替换为该变量,然后将该值用于入门脚本,这就是您所看到的.

If you write "${System.env.PORT}" into the applicationDefaultJvmArgs element, the PORT environment variable is substituted at buildtime, i.e. on the developer machine, before Gradle even sees it, and that value is then used in the starter scripts, which is what you saw.

在Unix启动脚本中引用applicationDefaultJvmArgs中的文字$的事实不是错误,而是故意的. applicationDefaultJvmArgs数组旨在可在所有目标平台(即Unix和Windows)上移植.也就是说,生成Unix/Windows启动脚本,以便在两个平台上启动的JVM都能准确地看到在构建时传递给applicationDefaultJvmArgs的字符串参数.这意味着这些字符串中的任何外壳元字符(如$)都必须在Unix入门脚本中加引号,这样,如果您在其中一个参数中使用文字字符串"$ PORT",则该字符串将完全像这样被复制,即没有外壳变量扩展发生.如果将"$ PORT"写入$之前的UNIX起动器脚本中而不带\,则起动器脚本将完成您想要的操作-在Unix上.但是,在Windows上,启动脚本是cmd批处理文件,$没有特殊含义(相反,%%必须用于变量扩展),因此字符串"$ PORT"将按字面值传递给JVM,并且您将程序无法按预期工作.您可能并不关心Windows(实际上我也不是,至少不是很多),但是Gradle(尤其是具有所有功能的应用程序插件)可以在所有受支持的平台上完全移植,所以这就是事实立即实施.

The fact that a literal $ in applicationDefaultJvmArgs gets quoted in the Unix starter script isn't a bug, it's intentional. The applicationDefaultJvmArgs array is meant to be portable across all target platforms, i.e. Unix and Windows. Which is to say, the Unix/Windows start scripts are generated such that the launched JVMs on both platforms see exactly the string arguments that were passed into applicationDefaultJvmArgs at buildtime. This means that any shell metacharacters like $ in those strings must be quoted in the Unix starter script, so that if you have the literal string '$PORT' in one of the arguments, it gets reproduced exactly like that, i.e. no shell variable expansion takes place. If "$PORT" were written into the unix starter script without the \ before the $, then the starter script would do what you want -- on Unix. On Windows though, where the starter script is a cmd batch file, $ has no special meaning (instead, %% has to be used for variable expansion), so the string "$PORT" would be passed literally to the JVM, and your program wouldn't work as expected. You may not care about Windows (actually I don't either, not much at least), but Gradle, and specifically the application plugin with all its features, are meant to be fully portable across all supported platforms, so this is how things are implemented right now.

如果您确实想在运行时扩展$ PORT变量,即在用户计算机上运行启动脚本时,则必须在后处理步骤中相应地修改生成的启动脚本.例如:

If you really want to have your $PORT variable expanded at runtime, i.e. when the starter script is run on the user's machine, you have to modify the generated starter script accordingly in a post-processing step. For example:

startScripts {
    doLast {
        unixScript.text = unixScript.text.replace('\\$PORT', '$PORT') 
        windowsScript.text = windowsScript.text.replace('\\$PORT', '%PORT%') //untested
    }
}

在将来,人们可能会考虑在applicationDefaultJvmArgs中为运行时环境变量使用某种平台无关的表示法,然后应用程序插件会将其在每个启动脚本中扩展为正确的平台特定的变量表示法.但是AFAIK目前尚未计划.

For the future, one might think about having some kind of platform-independent notation for runtime environment variables in the applicationDefaultJvmArgs, and the application plugin would then expand that in each starter script to the correct platform-specific variable notation. But this isn't planned currently, AFAIK.

这篇关于gradle应用程序插件和系统环境变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆