2016-06-28 1 views
0

내가 외부 프로세스에 쉘 스크립트를 실행하는 스레드를 실행 중지하고 다음과 같이 나는이 외부 프로세스에서 표준 오류 및 표준 출력 스트림에서 읽을 아파치의 IOUtils을 사용하고 있습니다 :스레드

Thread t = new Thread(()-> { 
     ProcessBuilder pb = new ProcessBuilder("sh"); 
     Process p = null; 
     try { 
      p = pb.start(); 
      OutputStream os = p.getOutputStream(); 
      os.write("sleep 30 ; echo test".getBytes()); 
      os.flush(); 
      os.close(); 
      InputStream is = p.getInputStream(); 
      InputStream es = p.getErrorStream(); 
      String stdout = IOUtils.toString(is,"UTF-8"); 
      String stderr = IOUtils.toString(es,"UTF-8"); 
      int retval = p.waitFor(); 
     } catch (Exception e) { 
      System.out.println("Got exception: "+e.toString()); 
     } finally { 
      System.out.println("Done now!"); 
     } 
    }); 
t.start(); 
Thread.sleep(7000); 
t.interrupt(); 

어떤 이유로이 테스트 케이스를 실행할 때 예외가 throw되지 않습니다 (catch 블록이 실행되지 않음). finally 블록이 실행되지 않습니다. 내가 잡을 수없는 문제가 있습니까? stdout과 stderr를 다른 스레드가 수집해야합니까?

답변

3

stderr 용 버퍼가 가득 차면 프로그램이 중지됩니다. 다른 문자열에 있어야하는 경우가 아니라면 하나를 다른 문자열로 리디렉션합니다. 당신이 배경 스레드를 시작할 필요가 없습니다

waitFor(long, TimeUnit)는 시간 제한이있는 표준 에러를 읽을 추가 스레드를 필요가 없습니다

나는 출력을 결합 ProcessBuidler.redirectErrorStream을 사용합니다.

stderr 및 stdout을 인쇄하여 잘못된 것을 나타낼 수 있도록 표시하는 것이 좋습니다.

1

셸의 출력을 처리하기 전에 스레드가 종료 (중단됨)된다는 점을 제외하면 올바르게 보입니다. 문제는 쉘이 30 초 동안 대기하고 스레드가 7 초 내에 인터럽트된다는 것입니다.

"셸"스레드가 실제로 활성화되기 전에 catch 또는 finally 블록에서 메시지가 나타나지 않는 것은 main() 메서드에서 프로그램을 끝내면 발생할 수 있습니다.