带有 -dname 的 keytool 在 Gradle 中包含空格:非法选项

keytool with -dname containing spaces in Gradle: illegal option

我正在尝试创建一个涉及 Java keytool 二进制文件的任务,但显然我无法正确传递 dname 参数。空格似乎是问题所在,但仅当 运行 作为 Gradle 脚本时才会出现。当我将相同的命令复制粘贴到终端时,它起作用了。 (我相信在这两种情况下都使用了相同的 keytool 二进制文件。)

这是我的脚本:

task generateTomcatKeystore() {
  doLast {
      def serverAlias = "server_debug"
      def serverStorePass = "changeit_server"
      def serverKeyPass = "changeit_server"

      def ourDomain = "domain.net"
      def ourName = "Company"

      def dName = /CN=$ourDomain, OU=Backend, O=$ourName, L=Prague, S=Czech Republic, C=CZ/
      def keytoolCommand = /keytool -genkeypair -alias $serverAlias -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -dname "$dName" -validity 365 -keypass $serverKeyPass -keystore tomcat.jks -storepass $serverStorePass/;

      // what exactly am I executing?
      println keytoolCommand

      def outputErr = keytoolCommand.execute().err.text
      // errors?
      println outputErr

      // am I calling the right binary? ...apparently yes
      println 'which keytool'.execute().text
  }
}

这是我收到的投诉:

Illegal option:  OU=Backend,

当我像这样消除 dname 组件之间的所有空格时:

def dName = /CN=$ourDomain,OU=Backend,O=$ourName,L=Prague,S=Czech Republic,C=CZ/

错误更改为:

Illegal option:  Republic,C=CZ"

...很明显空格是问题所在。但仅当 运行 来自 Gradle.

注意我的-dname是用双引号括起来的:

keytool -genkeypair -alias server_debug -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -dname "CN=domain.net,OU=Backend,O=Company,L=Prague,S=Czech Republic,C=CZ" -validity 365 -keypass changeit_server -keystore tomcat.jks -storepass changeit_server

根据 Oracle,只有逗号必须在 dname 参数中转义,see for yourself

在幕后,groovy 已向 java.lang.String 添加了一个 execute() 方法,可将您的字符串拆分为一个数组。它可能通过拆分 space 个字符来实现。参见 String.execute()

我建议您改用 Gradle 的 Project.exec(Closure)。你可以做类似

的事情
ByteArrayOutputStream errorOut = new ByteArrayOutputStream() 
exec {
  workingDir = "$javaHome/bin" 
  errorOutput = errorOut
  args "keytool -genkeypair -alias $serverAlias -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -dname".split(' ') 
  args dName
  args "-validity 365 -keypass $serverKeyPass -keystore tomcat.jks -storepass $serverStorePass".split(' ') 
} 
String errors = errorOut.toString()