먼저 라인 교체를 권장합니다.
Process process = Runtime.getRuntime ().exec ("/bin/bash");
라인
ProcessBuilder builder = new ProcessBuilder("/bin/bash");
builder.redirectErrorStream(true);
Process process = builder.start();
ProcessBuilder는 Java 5의 새로운 기능이며 외부 프로세스를 더 쉽게 실행할 수 있습니다. 제 생각에 가장 중요한 개선점 Runtime.getRuntime().exec()
은 자식 프로세스의 표준 오류를 표준 출력으로 리디렉션 할 수 있다는 것입니다. 이것은 당신이 InputStream
읽을 것이 하나만 있다는 것을 의미합니다 . 그 전에는 표준 출력 버퍼가 비어있는 동안 (하위 프로세스가 중단되는) 표준 오류 버퍼 채우기를 방지하기 위해 stdout
에서 읽는 것과 에서 읽는 두 개의 별도 스레드가 필요했습니다 stderr
.
다음으로 루프 (두 개가 있음)
while ((line = reader.readLine ()) != null) {
System.out.println ("Stdout: " + line);
}
reader
프로세스의 표준 출력에서 읽는이 파일의 끝을 반환 할 때만 종료됩니다 . 이것은 bash
프로세스가 종료 될 때만 발생합니다 . 현재 프로세스에서 더 이상 출력이없는 경우 파일 끝을 반환하지 않습니다. 대신, 프로세스에서 출력의 다음 줄을 기다렸다가 다음 줄을 가질 때까지 반환하지 않습니다.
이 루프에 도달하기 전에 두 줄의 입력을 프로세스에 보내므로이 두 줄의 입력 후에 프로세스가 종료되지 않으면 두 루프 중 첫 번째 루프가 중단됩니다. 다른 줄을 읽을 때까지 기다리지 만 다른 줄은 읽을 수 없습니다.
나는 소스 코드를 (I 교체 그래서, 지금 윈도우에있어 컴파일 /bin/bash
에 cmd.exe
있지만 기본 원칙은 동일해야합니다), 그리고 그 발견 :
- 두 줄을 입력하면 처음 두 명령의 출력이 표시되지만 프로그램이 중단됩니다.
- 라고 입력
echo test
한 다음을 입력 exit
하면 cmd.exe
프로세스가 종료 된 이후 프로그램이 첫 번째 루프에서 빠져 나옵니다 . 그런 다음 프로그램은 다른 입력 줄 (무시 됨)을 요청하고 자식 프로세스가 이미 종료되었으므로 두 번째 루프를 건너 뛰고 자체 종료합니다.
- 입력
exit
하고를 입력 echo test
하면 파이프가 닫혀 있다는 IOException이 발생합니다. 이것은 예상 할 수 있습니다. 첫 번째 입력 라인은 프로세스를 종료 시켰고 두 번째 라인을 보낼 곳이 없습니다.
나는 내가 작업했던 프로그램에서 당신이 원하는 것과 비슷한 것을하는 트릭을 보았다. 이 프로그램은 여러 셸을 유지하고 그 안에서 명령을 실행하고이 명령의 출력을 읽습니다. 사용 된 트릭은 항상 셸 명령의 출력 끝을 표시하는 '마법'줄을 작성하고이를 사용하여 셸로 보낸 명령의 출력이 언제 완료되었는지 확인하는 것입니다.
나는 당신의 코드를 가져 와서 writer
다음 루프로 할당하는 줄 뒤의 모든 것을 바꿨습니다 .
while (scan.hasNext()) {
String input = scan.nextLine();
if (input.trim().equals("exit")) {
writer.write("exit\n");
} else {
writer.write("((" + input + ") && echo --EOF--) || echo --EOF--\n");
}
writer.flush();
line = reader.readLine();
while (line != null && ! line.trim().equals("--EOF--")) {
System.out.println ("Stdout: " + line);
line = reader.readLine();
}
if (line == null) {
break;
}
}
이렇게 한 후 몇 가지 명령을 안정적으로 실행하고 각 명령의 출력을 개별적으로 나에게 반환 할 수있었습니다.
echo --EOF--
쉘에 전송 된 두 개의 명령은 명령 --EOF--
의 오류 결과에서도 명령의 출력이 종료되도록하기 위해 있습니다.
물론이 접근 방식에는 한계가 있습니다. 이러한 제한 사항은 다음과 같습니다.
- 사용자 입력 (예 : 다른 셸)을 기다리는 명령을 입력하면 프로그램이 중단 된 것처럼 보입니다.
- 쉘에 의해 실행되는 각 프로세스가 출력을 개행으로 종료한다고 가정합니다.
- 쉘에 의해 실행되는 명령이 행을 작성하면 약간 혼란스러워집니다
--EOF--
.
bash
구문 오류를보고하고 일치하지 않는 일부 텍스트를 입력하면 종료됩니다 )
.
예약 된 작업으로 실행하려는 것이 무엇이든 이러한 병리학 적 방식으로 작동하지 않는 명령이나 작은 명령 집합으로 제한되는 경우 이러한 점은 중요하지 않을 수 있습니다.
편집 : Linux에서 실행 한 후 종료 처리 및 기타 사소한 변경 사항을 개선합니다.