[java] process.waitFor ()는 절대 반환하지 않습니다.

Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader = 
    new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();



답변

waitFor()돌아 오지 않는 데는 여러 가지 이유가 있습니다.

그러나 일반적으로 실행 된 명령이 종료되지 않는다는 사실로 귀결됩니다.

이것 역시 여러 가지 이유가있을 수 있습니다.

한 가지 일반적인 이유는 프로세스가 일부 출력을 생성하고 적절한 스트림에서 읽지 않기 때문입니다. 즉, 버퍼가 가득 차면 프로세스가 차단되고 프로세스가 계속 읽기를 기다립니다. 당신의 프로세스는 다른 프로세스가 끝날 때까지 기다립니다 (당신의 프로세스를 기다리기 때문이 아닙니다 …). 이것은 고전적인 교착 상태 상황입니다.

차단되지 않도록 프로세스 입력 스트림에서 지속적으로 읽어야합니다.

“When Runtime.exec () wo n’t”Runtime.exec() 라는 모든 함정을 설명하고 그에 대한 방법을 보여주는 멋진 기사 가 있습니다.


답변

완료되기를 기다리기 전에 출력을 읽지 않는 것 같습니다. 출력이 버퍼를 채우지 않는 경우에만 괜찮습니다. 그렇다면 출력 catch-22를 읽을 때까지 기다립니다.

읽지 않은 오류가있을 수 있습니다. 이 경우 응용 프로그램이 중지되고 waitFor가 영원히 대기합니다. 이 문제를 해결하는 간단한 방법은 오류를 일반 출력으로 리디렉션하는 것입니다.

ProcessBuilder pb = new ProcessBuilder("tasklist");
pb.redirectErrorStream(true);
Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null)
    System.out.println("tasklist: " + line);
process.waitFor();


답변

또한 Java 문서에서 :

java.lang

수업 과정

일부 네이티브 플랫폼은 표준 입력 및 출력 스트림에 제한된 버퍼 크기 만 제공하기 때문에 입력 스트림을 즉시 쓰거나 하위 프로세스의 출력 스트림을 읽지 못하면 하위 프로세스가 차단되고 교착 상태가 될 수도 있습니다.

Process에서 입력 스트림의 버퍼 (하위 프로세스의 출력 스트림으로 파이프)를 지우지 못하면 하위 프로세스가 차단 될 수 있습니다.

이 시도:

Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((reader.readLine()) != null) {}
process.waitFor();


답변

이전 답변에 추가하고 싶지만 댓글을 달 담당자가 없기 때문에 답변 만 추가하겠습니다. 이것은 Java로 프로그래밍하는 Android 사용자를 대상으로합니다.

RollingBoy의 게시물에 따르면이 코드는 거의 저에게 효과적이었습니다.

Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((reader.readLine()) != null) {}
process.waitFor();

제 경우에는 return ( “ip adddr flush eth0”)없이 명령문을 실행했기 때문에 waitFor ()가 해제되지 않았습니다. 이 문제를 해결하는 쉬운 방법은 단순히 진술에 항상 무언가를 반환하도록하는 것입니다. 저에게 이것은 “ip adddr flush eth0 && echo done”실행을 의미했습니다. 하루 종일 버퍼를 읽을 수 있지만 아무것도 반환되지 않으면 스레드가 대기를 해제하지 않습니다.

누군가에게 도움이되기를 바랍니다!


답변

몇 가지 가능성이 있습니다.

  1. 당신은 프로세스의 모든 출력을 소비하지 않았습니다 stdout.
  2. 당신은 프로세스의 모든 출력을 소비하지 않았습니다 stderr.
  3. 프로세스가 사용자의 입력 을 기다리고 있으며 제공하지 않았거나 프로세스의 stdin.
  4. 프로세스가 하드 루프로 회전하고 있습니다.


답변

다른 사람들이 언급했듯이 stderrstdout 을 사용해야합니다 .

다른 답변과 비교할 때 Java 1.7 이후로 훨씬 쉽습니다. stderrstdout 을 읽기 위해 더 이상 스레드를 직접 만들 필요가 없습니다 .

그냥를 사용 ProcessBuilder하고 방법을 사용 redirectOutput중 하나와 함께 redirectError또는 redirectErrorStream.

String directory = "/working/dir";
File out = new File(...); // File to write stdout to
File err = new File(...); // File to write stderr to
ProcessBuilder builder = new ProcessBuilder();
builder.directory(new File(directory));
builder.command(command);
builder.redirectOutput(out); // Redirect stdout to file
if(out == err) { 
  builder.redirectErrorStream(true); // Combine stderr into stdout
} else { 
  builder.redirectError(err); // Redirect stderr to file
}
Process process = builder.start();


답변

같은 이유로 inheritIO()Java 콘솔을 다음과 같은 외부 앱 콘솔과 매핑 하는 데 사용할 수도 있습니다 .

ProcessBuilder pb = new ProcessBuilder(appPath, arguments);

pb.directory(new File(appFile.getParent()));
pb.inheritIO();

Process process = pb.start();
int success = process.waitFor();