从Java进程调用shell脚本时遇到一些奇怪的行为。
Process p = Runtime.getRuntime().exec("mybashscript.sh");
(new StreamGobblerThread(p.getInputStream())).start();
(new StreamGobblerThread(p.getErrorStream())).start();
p.waitFor();
returnValue = p.exitValue();
StreamGobblerThread只有一个执行
的run()方法while(((inputStream.available>0) { inputStream.skip(available); }
大约20%的时间可以使用,但大部分脚本都会失败,返回代码为141。
根据我在谷歌上发现的,141是收到SIGPIPE时的返回码。
有什么想法吗?
答案 0 :(得分:2)
我不是100%确定问题所在,但首先是:
while(((inputStream.available>0) { inputStream.skip(available); }
无效。
这是因为inputStream.available()没有阻塞,所以如果它没有立即读取的内容,它根本不会读取任何东西。
你最好有这样的事情:
byte[] buf = new byte[8192];
int next;
try {
while ((next = in.read(buf)) != -1) {}
} catch (IOException e) {
throw new GroovyRuntimeException("exception while dumping process stream", e);
}
read()是阻塞的,这样它实际上会继续读取,直到流正确关闭。
(注意:此代码来自Groovy的consumeProcessOutput()
实现答案 1 :(得分:1)
这可能意味着“破管”错误。当管道连接的其中一个进程在另一个进程之前退出时,可能会发生这种情况。
答案 2 :(得分:1)
我一生中看过几次,发现了2次解决方法。
ProcessBuilder b = new ProcessBuilder(“foo.sh”); b.redirectErrorStream(真); 过程p = b.start(); p.getInputStream(); // .....等。
现在从包含stdout和stderr的输入流中读取。
答案 3 :(得分:0)
我遇到类似的问题,在一个线程中执行该进程,该方法的run方法会读取进程InputStream然后调用waitFor()方法。
我将进程InputStream的读取移动到自己的线程中,因为OP已经完成,并且不再看到返回的管道退出代码损坏。