Вызов скрипта из java, сигнал sigpipe получен - PullRequest
3 голосов
/ 17 ноября 2010

Я сталкиваюсь с некоторым странным поведением при вызове сценария оболочки из процесса Java.

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.

Есть идеи?

Ответы [ 4 ]

2 голосов
/ 18 ноября 2010

Я не уверен на 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 для takeProcessOutput ()

1 голос
/ 18 ноября 2010

Я видел это несколько раз в своей жизни и нашел 2 обходных пути.

  1. Если вы действительно хотите прочитать ошибку и поток вывода отдельно, выполните команду как "/ bin / sh foo.sh 1> / tmp / out 2> / tmp / err" и затем прочитайте из этих файлов.
  2. Если вам удобно читать смесь stdout и stderr, используйте ProcessBuilder следующим образом:

ProcessBuilder b = новый ProcessBuilder ("foo.sh"); b.redirectErrorStream (истина); Процесс p = b.start (); p.getInputStream (); // ..... и т. д.

теперь считывается из входного потока, который содержит как stdout, так и stderr.

1 голос
/ 17 ноября 2010

Это, вероятно, означает ошибку "сломанная труба".Это может произойти, когда один из процессов, связанных с каналом, завершается раньше другого.

0 голосов
/ 03 ноября 2014

У меня была похожая проблема: процесс выполнялся в потоке, метод run которого прочитал бы процесс InputStream и затем вызвал метод waitFor ().

Я переместил чтение процессов InputStream в его собственный потоккак OP сделал и больше не видел возвращенный код выхода из сломанной трубы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...