Groovy脚本不再适用于Cygwin?

Tim*_*m W 5 groovy cygwin

在旧版本的Groovy中,我可以按照他们自己的指示运行Groovy作为Cygwin下的shell脚本:

$ cat ~/bin/hiworld
#!/usr/bin/env groovy
println("Hello world")
Run Code Online (Sandbox Code Playgroud)

这很有效.但是,在(至少)Groovy 2.3.2和2.3.3下,我看到的是:

$ hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
Run Code Online (Sandbox Code Playgroud)

我在黑暗中最好的刺:"env"通过绝对路径启动脚本(例如"groovy/home/myacct/bin/hiworld"),而新版本的Groovy已被"改进",以便Groovy不再理解如何处理这个.

实际上,我可以通过这样做产生同样的错误:

$ groovy ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
Run Code Online (Sandbox Code Playgroud)

所以我不确定Groovy是如何(a)将其解析为Windows风格的路径,然后(b)无法理解它是一种Windows风格的路径.

我可以"修复"这个,然后通过这样运行它:

$ groovy $(cygpath -w ~/bin/hiworld)
Hello world
Run Code Online (Sandbox Code Playgroud)

...但是,来吧,这是让用户启动实用程序脚本的完全疯狂方式.(或者我可以编写一个"前端"脚本,当然只是用那条线来启动另一个脚本.但是,对于我想要最终实现的目标,我不妨放弃Groovy并分发一个可运行的脚本.带有相关启动脚本的JAR.)

那么Groovy是否只是放弃了对Cygwin的支持?或者它们是否真的有可能至少有两个版本没有测试他们自己推荐的在最流行的环境之一下运行脚本的方式?

如果没有,我错过了什么或做错了什么?


更新:我认为备份我在这里提出的一些建议会有所帮助.

首先,我想要注意Cygwin显然是(或者是)至少得到了一些支持:例如,groovyStart在支持Cygwin平台方面有相当多的代码(看起来和Mac OSX一样多).如前所述,它在以前的版本中显然工作正常.

目前,最后一个示例在groovyStart下解析为:

'/cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/java' -classpath C:/cygwin64/home/myacct/opt/groovy-2.3.3/lib/groovy-2.3.3.jar -Dscript.name=/home/myacct/opt/groovy-2.3.3/bin/groovy -Dprogram.name=groovy -Dgroovy.starter.conf=C:/cygwin64/home/myacct/opt/groovy-2.3.3/conf/groovy-starter.conf -Dgroovy.home=C:/cygwin64/home/myacct/opt/groovy-2.3.3 '-Dtools.jar=C:/Program Files/Java/jdk1.7.0_51/lib/tools.jar' org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf C:/cygwin64/home/myacct/opt/groovy-2.3.3/conf/groovy-starter.conf --classpath . C:/cygwin64/home/myacct/bin/hiworld
Run Code Online (Sandbox Code Playgroud)

只是为了澄清一下,调用JDK本身没有问题 - 运行命令的那部分运行就好了.被打破的部分是最后一个论点:如果我改变了

C:/cygwin64/home/myacct/bin/hiworld
Run Code Online (Sandbox Code Playgroud)

file:///C:/cygwin64/home/myacct/bin/hiworld
Run Code Online (Sandbox Code Playgroud)

......它再次起作用.这与我上面的断言一致,"groovy"(脚本)确实正确地从Cygwin/UNIX样式路径转换为本机Windows路径,但底层进程 - 在Windows Java中运行 - 实际上是因为窗口路径!显然它期待一个URL.


更新2:下面,Warren提出了尝试使用GVM的绝佳建议.可悲的是,这仍然会产生同样的错误:

$ which groovy
/home/myacct/.gvm/groovy/current/bin/groovy

$ hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c

$ sh $(which groovy) ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
Run Code Online (Sandbox Code Playgroud)

将"-x"标志添加到上一个命令会显示Groovy仍在使用我的Windows JVM(这没有错,只是注意到)并且现在引用了GVM安装的库(此处显示为了可读性而略微重新格式化):

'/cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/java' \
  -classpath C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/lib/groovy-2.3.3.jar \
  -Dscript.name=/home/C400334/.gvm/groovy/current/bin/groovy \
  -Dprogram.name=groovy \
  -Dgroovy.starter.conf=C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/conf/groovy-starter.conf \
  -Dgroovy.home=C:/cygwin64/home/myacct/.gvm/groovy/2.3.3 \
  '-Dtools.jar=C:/Program Files/Java/jdk1.7.0_51/lib/tools.jar' \
  org.codehaus.groovy.tools.GroovyStarter \
  --main groovy.ui.GroovyMain \
  --conf C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/conf/groovy-starter.conf \
  --classpath . \
  C:/cygwin64/home/myacct/bin/hiworld
Run Code Online (Sandbox Code Playgroud)

和以前一样,在最终参数之前添加"file:///"似乎可以解决问题.

所以我想知道我们是否正在使用不同版本的JVM或其他东西?


更新3:升级到jdk1.7.0_60(尝试了64位和32位版本),但这似乎没有什么区别.Java 6表现出同样的问题,但也增加了对缺少NioGroovyMethods的抱怨.

War*_*ung 2

我不确定 Groovy 如何 (a) 将其解析为 Windows 风格的路径

startGroovy脚本中有特定的代码来检测 Cygwin 并cygpath根据需要使用。

通过 GVM 安装 Groovy发现了这一点,GVM 是为 Unixy 平台获取 Groovy 的公认方法。(在这种情况下,您不想使用 Groovy 的本机 Windows 发行版!)

唯一棘手的事情是弄清楚如何设置JAVA_HOME。在这里,它需要是:

 $ export JAVA_HOME='/cygdrive/c/Program Files (x86)/Java/jre7'
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 64 位版本的 Windows,并且像我一样安装了 32 位 JRE,那么这也应该适合您。否则,您可能需要调整路径。

一旦我gvm install groovy成功了,如果我将它运行为 ,你的hiworld例子在这里工作得很好。这是使用 Java 1.7.0_55 的 32 位版本的 Cygwin。./hiworld

但是,当我将其放入PATH并运行它时hiworld,正如您所做的那样,这传递了一个到包装器脚本的完全限定路径groovy(例如/home/wyoung/bin/hiworld)而不是相对路径,这导致startGroovy脚本通过 运行路径cygpath -m,这变成变成类似的东西C:/cygwin64/home/wyoung/bin/hiworld。Oracle 的 JRE 无法处理本地路径中的正斜杠。它盲目地假设 Windows 上的正斜杠意味着它是某种 URL,因此C:被视为 URL 方案,或他们所说的“协议”。

我不知道这是Java中的回归还是startGroovy脚本中的回归。虽然您可以file://像您发现的那样在此处传递 URL,但您也可以使用反斜杠而不是正斜杠传递“正确的”Windows 路径。cygpath您可以通过-wswitch 而不是 来获得它-m。在这种情况下,您必须更加小心,避免意外的反斜杠转义,这可能会解释回归。