【问题标题】:Calling script from java, sigpipe signal received从java调用脚本,收到sigpipe信号
【发布时间】:2010-11-17 20:27:49
【问题描述】:

我在从 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。

根据我在 google 上的发现,141 是收到 SIGPIPE 时的返回码。

有什么想法吗?

【问题讨论】:

  • 也许你应该打印出错误,它们可能会给你一个有意义的错误信息。
  • SIGPIPE 可能是由于在StreamGobblerThread 中提前退出while 造成的。要检查它,只需使用空的run()。在循环中添加一些调试打印以查看 available 是什么。尝试读取数据而不是跳过。
  • 似乎除了脚本的返回码之外没有“错误”,因为它不是发生的java异常。所有java似乎都知道脚本的退出代码
  • 如果你注释掉你为错误流启动线程的行,它会做同样的事情吗?
  • 我将尝试将错误线程注释掉。这段代码显然已经在生产环境中运行了很长时间没有问题,但它可能工作正常,只要没有任何东西进入 stderr

标签: java linux bash stream signals


【解决方案1】:

我不是 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() 实现

【讨论】:

  • 很好。当没有更多可用时,StreamGobbler 线程实际上正在关闭 inputStream。但由于 shell 脚本可能仍在运行,因此它过早地关闭了它。
【解决方案2】:

我在生活中多次看到这一点,并找到了 2 个解决方法。

  1. 如果你真的想分别读取错误和输出流,运行类似的命令 “/bin/sh foo.sh 1>/tmp/out 2>/tmp/err”,然后从这些文件中读取。
  2. 如果混合阅读 stdout 和 stderr 对您有好处,请使用 ProcessBuilder,如下所示:

ProcessBuilder b = new ProcessBuilder("foo.sh"); b.redirectErrorStream(true); 进程 p = b.start(); p.getInputStream(); //.....等等。

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

【讨论】:

    【解决方案3】:

    这可能意味着“管道损坏”错误。当管道连接的一个进程先于另一个退出时,可能会发生这种情况。

    【讨论】:

      【解决方案4】:

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

      像 OP 一样,我将进程 InputStream 的读取移到了它自己的线程中,并且不再看到返回的损坏的管道退出代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-26
        • 2011-12-08
        • 1970-01-01
        • 2021-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多