禁用守护程序时,Gradle console()为null

时间:2017-04-28 19:24:53

标签: java gradle groovy

我正在使用Gradle 2.13和Java 1.8.0_121。

我们的Gradle任务之一依赖于用户输入。

def user = System.console().readLine('Please enter new user username: ')

但是我收到以下错误:> Cannot invoke method readLine() on null object

所以console()必须为null ......好吧。我找到了this related issue suggesting to disable the daemon.

我做了那个并用./gradlew configureTask --no-daemon运行但得到了相同的结果......同样的错误。我很确定它没有使用守护进程,因为我收到以下消息:To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/2.13/userguide/gradle_daemon.html.

因此,如果Gradle守护程序没有导致此问题,那还有什么呢?有没有更多有经验的Gradle知道吗?

1 个答案:

答案 0 :(得分:1)

Gradle说它需要在子进程中运行构建,因为构建设置中存在某些内容:

  

为了遵守此版本的JVM设置,将分叉一个新的JVM。

我猜Gradle以允许它获取输出的方式创建该子进程(这是Java提供的用于生成子进程的API的默认值)。因此,子进程无法访问终端的I / O,并且System.console()在该进程中为空:它连接到系统控制台。

这让我好奇所以我想出了一个演示问题的脚本(使用Groovy的简洁性,它与Java在这里是一样的):

import java.io.Console

println "Console for main JVM: " + System.console()

Process p1 = new ProcessBuilder("groovy", "-e", "print System.console()")
    .redirectErrorStream(true)
    .start()
p1.waitFor()
println "Console for child JVM: " + p1.text

Process p2 = new ProcessBuilder("groovy", "-e", "println 'Console for child JVM with inherited IO: ' + System.console()")
    .redirectErrorStream(true)
    .inheritIO() // <- this changes everything, as now p2 is attached to system console
    .start()
p2.waitFor()
// No need to (actually cannot) get output of p2, as I/O is inherited by p2 it gets printed to terminal directly

结果:

Console for main JVM: java.io.Console@64cd705f
Console for child JVM: null
Console for child JVM with inherited IO: java.io.Console@3c130745

所以Gradle可能在我的例子中构建了像p1这样的子进程。我想它需要,因为它需要检查输出(而不是让它直接进入系统输出)。

我认为您唯一的解决方案是:

  • 找到一种方法让Gradle在主JVM中进行构建,而不需要分叉。不是Gradle专家,所以我不知道如何,但消息似乎暗示它是可能的。
  • 找到另一种获取用户输入的方法。也许是一个Swing对话框? (不是很优雅,但是嘿,一开始需要用户输入的构建并不是非常优雅,因此它的收集方式在这一点上并不重要)