2008-09-13 2 views
28

Java ProcessBuilder 클래스를 통해 프로세스를 시작하면 Java InputStreamsOutputStreams과 같이 해당 프로세스의 표준 입력, 표준 출력 및 표준 오류 스트림에 대한 모든 액세스 권한을 갖습니다. 그러나 이러한 스트림을 System.in, System.outSystem.err에 원활하게 연결할 수있는 방법을 찾을 수 없습니다.Java에서 상속 된 stdin/stdout/stderr을 사용하여 프로세스 시작 6

redirectErrorStream()을 사용하면 서브 프로세스의 표준 출력 및 표준 오류가 포함 된 단일 InputStream을 얻을 수 있으며이를 통해 루프를 반복하여 내 표준을 통해 전송할 수 있습니다.하지만이를 수행 할 방법을 찾을 수는 없습니다. 사용자가 C system() 호출을 사용했다면 그 사람이 할 수있는 것처럼 프로세스에 입력하십시오.

Java SE 7이 출시 될 때 이것이 가능할 것으로 보입니다. 현재 해결 방법이 있는지 궁금 할 것입니다. 보너스는 자식 프로세스의 isatty()의 결과가 리다이렉션을 수행하는 경우 가리 킵니다.

+0

죄송합니다. – jjnguy

+0

문제 없습니다. (나는 그런데 당신을 downvoted 사람이 아니었다.) –

+0

흠, 글쎄, 그 사람 덕분에 un-down-vote. 그리고 존 선생님, 저를 낮추지 않은 것에 대해 감사드립니다. – jjnguy

답변

15

out, err 및 입력 스트림을 시스템 버전으로 복사해야합니다. 가장 쉬운 방법은 Commons IO 패키지의 IOUtils 클래스를 사용하는 것입니다. copy method이 필요한 것 같습니다. copy 메소드 호출은 별도의 스레드에 있어야합니다. 여기

는 기본 코드입니다 :

// Assume you already have a processBuilder all configured and ready to go 
final Process process = processBuilder.start(); 
new Thread(new Runnable() {public void run() { 
    IOUtils.copy(process.getOutputStream(), System.out); 
} }).start(); 
new Thread(new Runnable() {public void run() { 
    IOUtils.copy(process.getErrorStream(), System.err); 
} }).start(); 
new Thread(new Runnable() {public void run() { 
    IOUtils.copy(System.in, process.getInputStream()); 
} }).start(); 
+4

아닙니다. IOUtils.copy는 InputStream을 첫 번째 인수로 취하므로 getOutputStream과 함께 작동하지 않습니다. 그래서 IOUtils.copy (process.getInputStream(), System.out); getOutputStream은 실제로 프로세스의 입력으로 연결되기 때문에 다소 혼란 스럽습니다. – Eelco

+0

이 구조는 올바르게 보이지만, IOUtils에 대한 매개 변수는 다시 말로 나타납니다. process.getInputStream()은 stdout으로 파이프되어야합니다 (예, 거꾸로 들립니다). 그래서이 구조가 좋게 보이지만, IOUtils에 대한 호출은 잘못된 것처럼 보이고 지금은 조금 혼란 스럽습니다 ... – titania424

+1

틀렸어. 부모와 자식의 입/출력 스트림 사이의 ** 파이프 ** 데이터는 ** 상속받습니다 **. 예를 들어, Java 명령이 터미널 (C isatty() == true 또는 System.console()! = null)에서 시작된 경우에도 자식은 터미널에서 실행되는 것으로 보이지 않습니다. 이는 입력/출력 스트림 파이프입니다. 이것은 (대부분의) 일부 프로그램이 터미널에서 실행될 때 다르게 작동하기 때문에 중요합니다. Java 7의 ProcessBuilder.Redirect.INHERIT는 이와 관련하여 올바르게 작동합니다. – Tobia

13

컴파일 및 가공 IO를 사용할 필요가 없습니다 존의 대답에 변화 : System.in를 들어

private static void pipeOutput(Process process) { 
    pipe(process.getErrorStream(), System.err); 
    pipe(process.getInputStream(), System.out); 
} 

private static void pipe(final InputStream src, final PrintStream dest) { 
    new Thread(new Runnable() { 
     public void run() { 
      try { 
       byte[] buffer = new byte[1024]; 
       for (int n = 0; n != -1; n = src.read(buffer)) { 
        dest.write(buffer, 0, n); 
       } 
      } catch (IOException e) { // just exit 
      } 
     } 
    }).start(); 
} 
+0

System.in에 대한 질문에 대답하지 않습니다. – solotim

+0

왜 pipe (System.in, process.getOutputStream()); 작동하지 않는 것 같습니까? –

3

가 대신 pipein() 다음 사용 pipe()

pipein(System.in, p.getOutputStream()); 

구현 :

private static void pipein(final InputStream src, final OutputStream dest) { 

    new Thread(new Runnable() { 
     public void run() { 
      try { 
       int ret = -1; 
       while ((ret = System.in.read()) != -1) { 
        dest.write(ret); 
        dest.flush(); 
       } 
      } catch (IOException e) { // just exit 
      } 
     } 
    }).start(); 

} 
+0

이것은 작동하지 않습니다. –

관련 문제