장기 실행 프로세스(Java에서 가끔 관련됨)를 시작한 다음 ps
기본적으로 다음을 수행하려고 합니다.
Process longRunningProcess = new ProcessBuilder(...).start();
Process psProcess = new ProcessBuilder("ps").start();
psProcess.waitFor();
// extract the PID from the output of psProcess
또는 Bash에서도 마찬가지입니다.
$ long_running_process > /dev/null & ps
문제는 장기 실행 프로세스가 ps
아직 보고되지 않은 아직 시작 중인 상태에 있을 수 있다는 것입니다. 아니면 실행 시 ps
장기 실행 프로세스가 눈에 보일 정도로 시작된다는 보장이 있나요 ? 명령을 반복적으로 실행나타나다프로세스는 항상 포함되지만 이는 분명히 아무 것도 증명하지 않습니다.
이 기사실행된 명령에 대해 가능한 경쟁 조건에 대해 경고뒤쪽에 ps
가 시작되었지만(예 ps | grep
: ) 이전에 시작된 프로세스에 대해서는 아무 것도 언급하지 않습니다 ps
.
답변1
OpenJDK와 동일한 작업인 경우v6-b14,PID~ 할 것이다ps
가상 파일 시스템을 검사할 때 사용할 수 있습니다 /proc
. 프로세스가 실제로 시작되었는지(즉, 아무것도 완료되었는지) 확실히 알 수 있는 방법은 없습니다. PID가 예약되고 예약되었다는 것뿐입니다.사망 한그리고 좀비 상태).
그러나 ps
Unix 시스템에 잠겨 있으므로 Reflection을 사용하여 ProcessBuilder에서 반환된 개체를 조사할 수 있습니다. 그러면 UnixProcess로 연결됩니다.
final class [More ...] UNIXProcess extends Process {
private FileDescriptor stdin_fd;
private FileDescriptor stdout_fd;
private FileDescriptor stderr_fd;
private int pid; <----------------------------------------------
private int exitcode;
물론 이예해킹이지만 생성과 크게 다르지 않으며 ps
확실히 더 빠릅니다. 그렇게 위험하지는 않습니다. pid
"Change Soon"이라는 pid 필드가 표시되지 않습니다 .
답변2
나는 Java에 익숙하지 않지만 ProcessBuilder.start
그것이 반환되면 뭔가 시작되었을 것입니다. 기존 스레드 내에서 콜백을 설정하고 나중에 이를 실행하여 하위 프로세스를 만들 수도 있고, 동일한 프로세스에서 다른 스레드를 시작하여 궁극적으로 하위 프로세스를 만들 수도 있고, fork
하위 프로세스를 만들기 위해 호출할 수도 있습니다. 올바른 결과를 얻는 것이 더 어렵기 때문에 처음 두 가지 중 하나인지 의심됩니다. 하위 프로세스와 통신하거나 해당 상태를 검색하는 메커니즘을 포함하여 하위 프로세스에 대한 참조는 해당 프로세스가 생성될 때까지 기다려야 합니다.
따라서 ProcessBuilder.start
반환되면 프로세스가 생성되었음을 확인할 수 있습니다. 그러나 이것이 경쟁 조건이 존재하지 않는다는 의미는 아닙니다. 프로세스가 시작된 직후 종료되거나 충돌하는 경우, 사용자가 볼 때쯤에는 해당 프로세스가 종료된 것일 수 있습니다. 프로세스 ID는 상위 프로세스가 다음 중 하나를 호출할 때까지 유지됩니다.wait
시스템 호출 계열;프로세스가 종료되면 해당 프로세스가 프로세스인 한 PID는 유효하게 유지됩니다.좀비즉, 부모가 전화하지 않는 한 wait
.
따라서 프로세스 ID가 유효한지 확인하는 유일한 방법은 상위 프로세스와 조정하여 상위 프로세스가 호출되었지만 fork
아직 호출되지 않았는지 확인하는 것입니다 wait
.
답변3
나는 과거에이 문제에 직면했습니다. 나는 다음을 수행하여 문제를 해결했습니다.
exec java WhateverTheClassNameIs -p $$
여기서 "-p"는 "내 PID가 이 플래그의 값입니다"를 의미하는 플래그입니다. main()
해당 부분을 Java 메소드로 코딩 해야 합니다 .
exec
기본 요소는 셸 자체를 통해 로드되므로 이는 셸 스크립트의 마지막 줄이어야 합니다 . java
프로그램의 종료 상태는 WhateverTheClassNameIs
더 이상 실제로 존재하지 않으므로 셸의 종료 상태가 아닌 의 종료 상태가 됩니다. 이로 인해 코드가 일부 왜곡될 수 있지만 PID를 Java 프로그램에 넣는 더 좋은 방법을 찾을 수 없습니다.