Groovy脚本不再适用于Cygwin?

时间:2014-06-19 09:20:10

标签: groovy cygwin

在旧版本的Groovy中,我可以在Cygwin下运行Groovy作为shell脚本,遵循他们自己的instructions这样做:

$ cat ~/bin/hiworld
#!/usr/bin/env groovy
println("Hello world")

这很有用。但是,在(至少)Groovy 2.3.2和2.3.3下,我看到了这一点:

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

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

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

$ groovy ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c

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

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

$ groovy $(cygpath -w ~/bin/hiworld)
Hello world

...但是,来吧,这是让用户启动实用程序脚本的完全疯狂方式。 (或者我可以编写一个“前端”脚本,当然只是用那条线来启动另一个脚本。但是,对于我想要最终实现的目标,我不妨放弃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

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

C:/cygwin64/home/myacct/bin/hiworld

file:///C:/cygwin64/home/myacct/bin/hiworld

......它又有效了。这与我上面的断言一致,“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

将“-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

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

所以我想知道我们是否正在使用不同版本的JVM或什么?


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

3 个答案:

答案 0 :(得分:2)

  

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

startGroovy脚本中包含特定代码以检测Cygwin,并在必要时使用cygpath

我通过installing Groovy via GVM发现了这一点,这是获得针对Unixy平台的Groovy的批准方式。 (在这种情况下,您不希望使用Groovy的本机Windows发行版!)

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

 $ export JAVA_HOME='/cygdrive/c/Program Files (x86)/Java/jre7'

如果您使用的是64位版本的Windows并且安装了32位JRE,那么这对您也有用。否则,您可能需要调整路径。

我成功gvm install groovy后,hiworld示例在此处正常运行如果我将其作为./hiworld运行。这是使用32位版本的Cygwin和Java 1.7.0_55。

但是,当我将它放在PATH并将其作为hiworld运行时,正如您所做的那样,这会传递一条到groovy包装器脚本的完全限定路径(例如{ {1}})而不是相对路径,导致/home/wyoung/bin/hiworld脚本运行startGroovy的路径,将其转换为cygpath -m之类的路径。 Oracle的JRE无法应对本地路径中的正斜杠。它盲目地假设Windows上的正斜杠意味着它是某种类型的URL,因此C:/cygwin64/home/wyoung/bin/hiworld被视为URL方案,或者#34;协议"正如他们所说的那样。

我不知道这是Java还是C:脚本中的回归。虽然您可以在此处传递startGroovy网址,但您也可以传递正确的"带有反斜杠而不是正斜杠的Windows路径。您可以使用file://开关而不是cygpath-w获得该结果。在这种情况下,你必须更加小心避免意外的反斜杠逃逸,这可以解释回归。

答案 1 :(得分:1)

刚刚遇到同样的问题,并将startGroovy脚本中的exec调用更改为以下内容(请注意最后两行):

    exec "$JAVACMD" $JAVA_OPTS \
        -classpath "$STARTER_CLASSPATH" \
        -Dscript.name="$SCRIPT_PATH" \
        -Dprogram.name="$PROGNAME" \
        -Dgroovy.starter.conf="$GROOVY_CONF" \
        -Dgroovy.home="$GROOVY_HOME" \
        -Dtools.jar="$TOOLS_JAR" \
        $STARTER_MAIN_CLASS \
        --main $CLASS \
        --conf "$GROOVY_CONF" \
        --classpath "$CP" \
        "$(cygpath -w $1)" \
        "${@:2}"

...正如上面所建议的那样,被调用的脚本被改为带有反斜杠的Windows路径,然后不会被解释为它看起来像一个URL。讨厌的黑客,但至少我能够再次执行我的脚本:)

答案 2 :(得分:0)

不确定是否还有人对此感兴趣。但不久我评论了上述答案,我找到了解决方案。

更新" startGroovy"脚本有以下两个更改:

for dir in $ROOTDIRSRAW ; do
    ROOTDIRS="$ROOTDIRS$SEP$dir"
    SEP="|"
done
ROOTDIRS="/c$SEP$ROOTDIRS"  ## <<<< ADD THIS LINE;assuming cygwin on c: drv

并替换--mixed与--windows:

CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
if [ $CHECK -ne 0 ] ; then
    ### change the --mixed to --windows here
    patched=`cygpath --path --ignore --windows "$arg"`  
else
    patched="$arg"
fi

它应该有用。