2010-11-17 1 views
3

У меня возникает какое-то странное поведение при вызове сценария оболочки из процесса Java.Вызов сценария из java, полученного сигнала sigpipe

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.

Любые идеи?

+0

, возможно, вы должны распечатать ошибки, они могут дать вам смысл сообщение об ошибке –

+0

'SIGPIPE' может быть вызвано ранним выходом из' while' в 'StreamGobblerThread'. Чтобы проверить это, просто используйте пустой 'run()'.Добавьте некоторую отладочную печать в цикле, чтобы узнать, что такое '' доступный''. Попытайтесь читать данные вместо пропусков. – khachik

+0

Кажется, что не существует «ошибки», кроме кода возврата из сценария, потому что это не исключение Java. все java, похоже, знают, что код выхода скрипта – Will

ответ

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); 
} 

чтения() блокирует так, таким образом, он на самом деле будет продолжать чтение, пока поток не будет закрыт.

(Примечание: Этот код от реализации Groovy о consumeProcessOutput()

+0

хороший catch .. поток StreamGobbler фактически закрывал входной поток, как только ничего больше не было доступно. но поскольку скрипт оболочки все еще работает, он закрывает его преждевременно. – Will

1

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

1

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

  1. Если вы действительно хотите, чтобы прочитать сообщение об ошибке и выходной поток отдельно, запустите команду, как «/ бен/ш foo.sh 1>/TMP/из 2>/TMP/ERR», а затем прочитать из этих файлов.
  2. Если это хорошо для вас, чтобы прочитать смесь стандартный вывод и стандартный поток ошибок, используйте ProcessBuilder следующим образом:

ProcessBuilder б = новый ProcessBuilder («foo.sh»); b.redirectErrorStream (true); Процесс p = b.start(); p.getInputStream(); // ..... и т. Д.

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

0

У меня была аналогичная проблема выполняющийся процесс в потоке, который запустить метод будет читать процесс InputStream, а затем вызвать метод Waitfor().

я переехал чтение процессов InputStream в свой собственный поток, как ОП сделали и больше не видеть разбитую трубу коды выхода вернулись.

Смежные вопросы