IT

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

lottoking 2020. 9. 4. 07:44
반응형

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() 라는 모든 함정을 설명하고 그에 대한 방법을 사용하여 멋진 가이드가 있습니다 (예,이 가이드는 2000 년에 작성 내용은 여전히 ​​적용됩니다!).


완료되기 전에 기다리기 전에 읽지 않습니다. 출력이 버퍼를 채우지 않는 경우에만 괜찮습니다. 읽을 때까지 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 = 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();

제 경우에는 리턴이없는 명령문 ( "ip adddr flush eth0")을 실행했기 때문에 waitFor ()가 해제되지 않을 가능성이 있습니다. 이 문제를 해결하는 쉬운 방법은 항상 문제를 해결하는 것입니다. 저에게 이것은 "ip adddr flush eth0 && echo done"실행을 의미했습니다. 하루 종일 버퍼를 읽을 수 없습니다.

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


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

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

stderrstdout다른 사람들이 언급했듯이 .

다른 답변과 인수 때 Java 1.7 이후로 규모가 있습니다. 표준 오류표준 출력 을 읽기 위해 더 이상 스레드를 직접 만들 필요가 없습니다 .

그냥를 사용 하고 방법을 사용 중 하나와 함께 또는 .ProcessBuilderredirectOutputredirectErrorredirectErrorStream

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

상세한 문제를 목격하고 생각합니다. 일부 프로세스가 시작되는 가상화로 실행되는 것처럼 보입니다. waitFor () 함수는 작업 관리자에서 프로세스 종료 한 경우를 제외하고는 영원히 기다리고 있습니다.
그러나 명령 줄 길이가 127 자 이하인 경우 모든 것이 잘 작동했습니다. 긴 파일 이름이 불가피한 경우 환경 변수를 사용하여 명령 줄을 짧게 사용할 수 있습니다. 실행 실행하려는 프로그램을 호출하기 전에 환경 변수를 설정하는 배치 파일 (FileWriter 사용)을 생성 할 수 있습니다. 다음과 가변적이다.

    set INPUTFILE="C:\Directory 0\Subdirectory 1\AnyFileName"
    set OUTPUTFILE="C:\Directory 2\Subdirectory 3\AnotherFileName"
    set MYPROG="C:\Directory 4\Subdirectory 5\ExecutableFileName.exe"
    %MYPROG% %INPUTFILE% %OUTPUTFILE%

마지막 단계는 실행을 사용하여 배치 파일을 실행하는 것입니다.


여기 저에게 맞는 방법이 있습니다. 참고 :이 방법은 적용되지 않습니다. 예 : "logStandardOut (...), git-bash 등".

private String exeShellCommand(String doCommand, String inDir, boolean ignoreErrors) {
logStandardOut("> %s", doCommand);

ProcessBuilder builder = new ProcessBuilder();
StringBuilder stdOut = new StringBuilder();
StringBuilder stdErr = new StringBuilder();

boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
if (isWindows) {
  String gitBashPathForWindows = "C:\\Program Files\\Git\\bin\\bash";
  builder.command(gitBashPathForWindows, "-c", doCommand);
} else {
  builder.command("bash", "-c", doCommand);
}

//Do we need to change dirs?
if (inDir != null) {
  builder.directory(new File(inDir));
}

//Execute it
Process process = null;
BufferedReader brStdOut;
BufferedReader brStdErr;
try {
  //Start the command line process
  process = builder.start();

  //This hangs on a large file
  // https://stackoverflow.com/questions/5483830/process-waitfor-never-returns
  //exitCode = process.waitFor();

  //This will have both StdIn and StdErr
  brStdOut = new BufferedReader(new InputStreamReader(process.getInputStream()));
  brStdErr = new BufferedReader(new InputStreamReader(process.getErrorStream()));

  //Get the process output
  String line = null;
  String newLineCharacter = System.getProperty("line.separator");

  while (process.isAlive()) {
    //Read the stdOut
    while ((line = brStdOut.readLine()) != null) {
      stdOut.append(line + newLineCharacter);
    }

    //Read the stdErr
    while ((line = brStdErr.readLine()) != null) {
      stdErr.append(line + newLineCharacter);
    }

    //Nothing else to read, lets pause for a bit before trying again
    process.waitFor(100, TimeUnit.MILLISECONDS);
  }

  //Read anything left, after the process exited
  while ((line = brStdOut.readLine()) != null) {
    stdOut.append(line + newLineCharacter);
  }

  //Read anything left, after the process exited
  while ((line = brStdErr.readLine()) != null) {
    stdErr.append(line + newLineCharacter);
  }

  //cleanup
  if (brStdOut != null) {
    brStdOut.close();
  }

  if (brStdErr != null) {
    brStdOut.close();
  }

  //Log non-zero exit values
  if (!ignoreErrors && process.exitValue() != 0) {
    String exMsg = String.format("%s%nprocess.exitValue=%s", stdErr, process.exitValue());
    throw new ExecuteCommandException(exMsg);
  }

} catch (ExecuteCommandException e) {
  throw e;
} catch (Exception e) {
  throw new ExecuteCommandException(stdErr.toString(), e);
} finally {
  //Log the results
  logStandardOut(stdOut.toString());
  logStandardError(stdErr.toString());
}

return stdOut.toString();

}


출력과 동시에 소비해야합니다.

    private void runCMD(String CMD) throws IOException, InterruptedException {
    System.out.println("Standard output: " + CMD);
    Process process = Runtime.getRuntime().exec(CMD);

    // Get input streams
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    String line = "";
    String newLineCharacter = System.getProperty("line.separator");

    boolean isOutReady = false;
    boolean isErrorReady = false;
    boolean isProcessAlive = false;

    boolean isErrorOut = true;
    boolean isErrorError = true;


    System.out.println("Read command ");
    while (process.isAlive()) {
        //Read the stdOut

        do {
            isOutReady = stdInput.ready();
            //System.out.println("OUT READY " + isOutReady);
            isErrorOut = true;
            isErrorError = true;

            if (isOutReady) {
                line = stdInput.readLine();
                isErrorOut = false;
                System.out.println("=====================================================================================" + line + newLineCharacter);
            }
            isErrorReady = stdError.ready();
            //System.out.println("ERROR READY " + isErrorReady);
            if (isErrorReady) {
                line = stdError.readLine();
                isErrorError = false;
                System.out.println("ERROR::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::" + line + newLineCharacter);

            }
            isProcessAlive = process.isAlive();
            //System.out.println("Process Alive " + isProcessAlive);
            if (!isProcessAlive) {
                System.out.println(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Process DIE " + line + newLineCharacter);
                line = null;
                isErrorError = false;
                process.waitFor(1000, TimeUnit.MILLISECONDS);
            }

        } while (line != null);

        //Nothing else to read, lets pause for a bit before trying again
        System.out.println("PROCESS WAIT FOR");
        process.waitFor(100, TimeUnit.MILLISECONDS);
    }
    System.out.println("Command finished");
}

참고 URL : https://stackoverflow.com/questions/5483830/process-waitfor-never-returns

반응형