&引用;adb启动服务器";,Java、Gradle和ApacheCommonsExec:如何使其正确?
当我试图从Java内部作为外部进程运行android start server时,遇到了各种各样的问题。Java由Gradle调用。让我向您描述一下在各种情况下到底发生了什么: 环境&引用;adb启动服务器";,Java、Gradle和ApacheCommonsExec:如何使其正确?,java,gradle,adb,apache-commons-exec,Java,Gradle,Adb,Apache Commons Exec,当我试图从Java内部作为外部进程运行android start server时,遇到了各种各样的问题。Java由Gradle调用。让我向您描述一下在各种情况下到底发生了什么: 环境 Windows 7 X64 爪哇7 commons-exec-1.1 梯度1.6 安卓API 17 IntelliJ IDEA 12.1.4社区版 假设 adb守护程序被终止,并将在调用adb启动服务器时启动 案例1 此代码: DefaultExecutor executor=new org.apache.co
- Windows 7 X64
- 爪哇7
- commons-exec-1.1
- 梯度1.6
- 安卓API 17
- IntelliJ IDEA 12.1.4社区版
adb守护程序被终止,并将在调用
adb启动服务器时启动
案例1
此代码:
DefaultExecutor executor=new org.apache.commons.exec.DefaultExecutor();
executor.execute(org.apache.commons.exec.CommandLine.parse(“adb启动服务器”);
log.info(“Checkpoint!”);
从应用程序插件的Gradlerun
task运行时,将显示启动服务器输出,即:
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
然后它将挂起,即“Checkpoint!”将永远不会被记录。手动终止adb.exe
进程将导致代码继续执行
问题1
为什么这个电话会阻塞?当从终端运行adb start server
命令时,几秒钟后控制返回到终端,那么为什么代码中不会发生这种情况呢
案例2
如果我直接使用Java运行时,就像这样:
Runtime.getRuntime().exec(新字符串[]{“adb”,“启动服务器”});
log.info(“Checkpoint!”);
系统出口(0);
如果像以前一样从Gradle调用,“检查点!”将被记录。但是,执行将挂起系统。退出(0)
。手动终止adb.exe将再次使Gradle调用完成
在这种情况下,不会显示adb启动服务器的输出
有趣的是,当我从IntelliJ IDEA运行应用程序而不是Gradle时,构建设置与Gradle类似,一切正常,应用程序正常完成
问题2
为什么Gradle挂起系统。退出(0)
而IntelliJ不挂起?这与Gradle本身是一个在内部调用Java的进程,而在IntelliJ中,Java是在没有任何间接寻址的情况下立即调用这一事实有什么关系吗?为什么这很重要
问题3
最终,我希望能够在没有任何挂起的情况下从Gradle运行此程序。记录adb启动服务器的输出将是一个额外的好处。如果您能给我一些提示,我将不胜感激。如果我回答了错误的问题,请原谅,但是如果我想从gradle启动一台服务器(我们为tomcat、sonicMQ、ApacheDS和EnterpriseDB这样做),我会从gradle Exec任务开始,如果它不合适,我只会尝试其他任务
task startADB(type: Exec) {
commandLine 'adb', 'start-server'
}
不幸的是,我不能回答你关于各种代码挂起的任何问题,因为我一点线索也没有!我只知道如果我想从gradle启动服务器,我会这么做。事实上,我就是这样做的。另一个稍微复杂一点的选择是使用或类似的东西。您仍然可以从gradle启动和停止它,但您可以获得一些高级功能。最终,我通过执行以下操作解决了问题:
在我的程序中,为了调用adb启动服务器
,我不再使用org.apache.commons.exec.defaultexector.execute(“adb启动服务器”)
或Java的Runtime.getRuntime().exec(“adb启动服务器”)
相反,我使用java.lang.ProcessBuilder(“adb启动服务器”).inheritIO().start().waitFor()
。注意,inheritaio()
是在Java 7中添加的,它允许在线读取已启动的进程stdout等。
EDIT与IntelliJ IDEA调用Gradle不同,直接从CLI调用Gradle时,Gradle中的Inheritario()
无效。有关详细信息,请参阅。
按照描述实施StreamGobbler
可能会解决问题
在Gradle中,我再次使用ProcessBuilder
重用run
任务变量,而不是Gradle的run
任务。看起来是这样的:
至于这些奇怪的行为的原因,我没有任何明确的答案,所以我不做进一步的评论
编辑2013年7月9日
似乎指出问题2的答案是:在windows上,父进程在终止前等待子进程。不幸的是,由于问题1中所述的问题,这里提出的解决方案不起作用
希望这有帮助,
康拉德谢谢!事实上,我正在考虑从外部启动亚洲开发银行,以规避我面临的所有问题。目前我认为Gradle挂起是因为应用程序插件的“运行”任务存在流缓冲问题(我查看了源代码)。也许是因为同样的原因,commons exec挂起。我继续调查……tanuki包装器允许您将基本上任何东西作为服务安装(在windows和linux中),并且它可以在不挂起的情况下更好地启动。gradle Exec变成了一个简单的“净启动”或“/etc/init.d/foo start”。我检查:gradle的Exec
任务也挂起System.exit(0)
。但是,此命令工作正常:newprocessbuilder(“adb”,“启动服务器”).inheritIO().start()代码>它不挂起在任何配置中,并显示输出。
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
// configuration-time of the original run task
run {
main = com.example.MainClass; // without this, our custom run will try to run "null"
}
task myRun(dependsOn: build) {
// execution-time of our custom run task.
doFirst {
ProcessBuilder pb = new ProcessBuilder(tasks['run'].commandLine);
pb.directory(tasks['run'].workingDir);
// works when the gradle command is executed from IntelliJ IDEA, has no effect when executed from standalone CLI interface.
pb.inheritIO();
Process proc = pb.start();
proc.waitFor();
}
}