从java调用脚本,收到sigpipe信号

时间:2010-11-17 20:27:49

标签: java linux bash stream signals

从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时的返回码。

有什么想法吗?

4 个答案:

答案 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次解决方法。

  1. 如果你真的想分别读取错误和输出流,请运行命令 “/ bin / sh foo.sh 1> / tmp / out 2> / tmp / err”然后从这些文件中读取。
  2. 如果您阅读stdout和stderr的混合物是有好处的,请使用ProcessBuilder,如下所示:
  3. ProcessBuilder b = new ProcessBuilder(“foo.sh”); b.redirectErrorStream(真); 过程p = b.start(); p.getInputStream(); // .....等。

    现在从包含stdout和stderr的输入流中读取。

答案 3 :(得分:0)

我遇到类似的问题,在一个线程中执行该进程,该方法的run方法会读取进程InputStream然后调用waitFor()方法。

我将进程InputStream的读取移动到自己的线程中,因为OP已经完成,并且不再看到返回的管道退出代码损坏。