2017-10-08 4 views
2

간단한 "Dockerized"Java 프로그램에서 Java 9의 새로운 ProcessHandle API를 시도하면서 프로세스 ID 검색시 동작면에서 차이점을 발견했습니다 프로세스 실행 중. 특히 ProcessHandle.pid() 메서드를 호출 할 때 Docker의 결과 PID는 호스트에 표시된 기본 ID와 다릅니다. 단, 문서의 "프로세스의 기본 프로세스 ID를 반환합니다"라고되어 있습니다. 또한 ProcessHandle.allProcesses()의 결과에는 차이가 있습니다. (시간이 정보를 인쇄 할 수)Docker의 Java 9 ProcessHandle API : PID 값 및 표시 프로세스의 차이점

  1. 지문 현재 프로세스의 PID,
  2. 몇 초 동안 휴면 자식 프로세스를 생성합니다 :

    은 아래의 프로그램은 다음과 같은 작업을 수행, 설명하기 위해 ,
  3. 마지막으로 모든 보이는 프로세스를 인쇄합니다. (도커)없이 정상적으로 프로그램을 실행할 때

public static void main(String[] args) { 
    System.out.println("### Current process info ###"); 
    ProcessHandle currentProcess = ProcessHandle.current(); 
    printInfo(currentProcess); 

    System.out.println(); 

    // Fork a child process that lasts for a few seconds 
    spawnProcess("jshell --startup ./sleep.txt"); 

    printAllVisibleProcesses(); 
} 

private static void printAllVisibleProcesses() { 
    System.out.println("### Visible processes info ###"); 
    ProcessHandle.allProcesses().forEach(ProcessHandleExamples::printInfo); 
    System.out.println(); 
} 

private static void spawnProcess(String command) { 
    System.out.println("Spawning: " + command); 
    try { 
     Runtime.getRuntime().exec(command); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

private static void printInfo(ProcessHandle processHandle) { 
    ProcessHandle.Info processInfo = processHandle.info(); 
    System.out.println("Process ID: " + processHandle.pid()); 

    System.out.println("Process arguments: " + Arrays.toString(processInfo.arguments().orElse(new String[0]))); 
    System.out.println("Process executable: " + processInfo.command().orElse("")); 
    System.out.println("Process command line: " + processInfo.commandLine().orElse("")); 
    System.out.println("Process start time: " + processInfo.startInstant().orElse(null)); 
    System.out.println("Process total cputime accumulated: " + processInfo.totalCpuDuration().orElse(null)); 
    System.out.println("Process user: " + processInfo.user().orElse("")); 
} 

는 출력이 예상되는 바와 같이, 현재 프로세스의 고유 PID, 하위 프로세스 및 기타 가시 프로세스를 포함합니다.

### Current process info ### 
Process ID: 7756 
Process arguments: [] 
Process executable: D:\Dev\Java\jdk-9\bin\java.exe 
Process command line: 
Process start time: 2017-10-08T12:23:46.474Z 
Process total cputime accumulated: PT0.4368028S 
Process user: manouti 

Spawning: jshell --startup ./sleep.txt 
### Visible processes info ### 
... skipping some output 
Process ID: 8060 
Process arguments: [] 
Process executable: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 
Process command line: 
Process start time: 2017-10-08T12:20:04.758Z 
Process total cputime accumulated: PT10.4676671S 
Process user: manouti 

Process ID: 7756 
Process arguments: [] 
Process executable: D:\Dev\Java\jdk-9\bin\java.exe 
Process command line: 
Process start time: 2017-10-08T12:23:46.474Z 
Process total cputime accumulated: PT0.8268053S 
Process user: manouti 

Process ID: 8080 
Process arguments: [] 
Process executable: D:\Dev\Java\jdk-9\bin\jshell.exe 
Process command line: 
Process start time: 2017-10-08T12:23:46.992Z 
Process total cputime accumulated: PT0.0780005S 
Process user: manouti 

내가 (부두 노동자가 boot2docker 리눅스에서 실행 윈도우 7) 도커에서 실행

는 프로세스의 아주 작은 부분 집합 볼 수 있습니다, 그리고 PID를 호스트에있는 것들과 일치하지 않습니다.

enter image description here

그러나, 생성 프로그램 출력 아래 대신, PID가도 1 및도 16 :

$ docker run test/java9-processhandle-example:1.0

상기 명령을 실행 한 후에, 호스트는 다음과 같은 과정을 도시 가시적 인 프로세스에는 컨테이너 프로세스와 스폰 된 프로세스가 포함됩니다.

이것이 예상되는지 궁금합니다. Docker에 비교적 익숙하지 않기 때문에 컨테이너에서 발생하는 제한 사항이라면 누군가가 설명 할 수 있다면 기쁠 것입니다. (Linux 또는 Windows의 Docker와 같은 다른 Docker 설정에서 재현 할 수 있는지 확실하지 않습니다. 섬기는 사람). 그렇지 않으면 Javadocs에서 언급 된 것 같지 않은 컨테이너에 적용될 때 API 자체의 제한 사항입니까?

### Current process info ### 
Process ID: 1 
Process arguments: [ProcessHandleExamples] 
Process executable: /usr/lib/jvm/java-9-openjdk-amd64/bin/java 
Process command line: /usr/lib/jvm/java-9-openjdk-amd64/bin/java ProcessHandleExamples 
Process start time: 2017-10-08T14:17:48.420Z 
Process total cputime accumulated: PT0.35S 
Process user: root 

Spawning: jshell --startup ./sleep.txt 
### Visible processes info ### 
Process ID: 1 
Process arguments: [ProcessHandleExamples] 
Process executable: /usr/lib/jvm/java-9-openjdk-amd64/bin/java 
Process command line: /usr/lib/jvm/java-9-openjdk-amd64/bin/java ProcessHandleExamples 
Process start time: 2017-10-08T14:17:48.420Z 
Process total cputime accumulated: PT0.6S 
Process user: root 

Process ID: 16 
Process arguments: [--startup, ./sleep.txt] 
Process executable: /usr/lib/jvm/java-9-openjdk-amd64/bin/jshell 
Process command line: /usr/lib/jvm/java-9-openjdk-amd64/bin/jshell --startup ./sleep.txt 
Process start time: 2017-10-08T14:17:49.070Z 
Process total cputime accumulated: PT0.03S 
Process user: root 
+4

나는 거의 이것을 기대할 것이다. 컨테이너에는 호스트의 PID 시퀀스에 대한 지식이 없어야합니다. – Makoto

+2

[docker와 호스트 간의 PID 매핑] (https://stackoverflow.com/questions/33328841/pid-mapping-between-docker-and-host)의 가능한 복제본입니다. Java 또는 그것의 버전 IMO. VonC의 답변을 통해 링크를 따라 세부 정보를 얻을 수 있습니다. – nullpointer

+0

여기서 더 자세히 설명하기 위해 Docker에서 ProcessHandler를 사용하는 방법에 대해 궁금한 점이 있습니까 (Docker에서 의심 스럽습니까). docker와 host에서 다른 PID를 얻는 방법에 대한 질문입니다. – nullpointer

답변

6

이것은 Java 또는 Java 9에만 국한된 것이 아니라 도커 테마입니다.

각 컨테이너는 자신의 PID 네임 스페이스와 컨테이너에서 실행되는 첫 번째 과정이있다, 특히 1

당신은 docker documentation이에 대한 자세한 내용을보실 수 있습니다,의 PID가 있습니다

작성자 기본적으로 모든 컨테이너에는 PID 네임 스페이스가 활성화되어 있습니다.

PID 네임 스페이스는 프로세스 분리를 ​​제공합니다. PID를 네임 스페이스는 시스템 프로세스의보기를 제거하고, 프로세스 ID의 PID를 포함하여 재사용 할 수 있도록 1

+0

docker에만 국한되지는 않지만, 언급 된 pid 네임 스페이스를 사용하는 모든 것은 이것을 경험할 것입니다. 다른 모든 네임 스페이스의 축과 독립적으로'unshare'를 통해 가장 낮은 레벨에서이 작업을 수행 할 수 있습니다. – the8472

0

그래서 --pid=host이 암시 같이 ProcessHandle.pid()가 예상 된 값을 반환 할 수 있도록 할 필요가있는 용기를 실행 문서화 (운영체제에 의해 할당 된 원시 PID).

또한 ProcessHandle.allProcesses() return 시스템이 볼 수있는 프로세스 인을 컨테이너에 바인딩하는 것과 반대가됩니다.

+0

Java에서 _native_ pid는 보통'ps' 명령으로 볼 수 있습니다. 이것은 'jps'와 같은 프로세스 ID와 다른 점입니다. 이들은 Java 내부 프로세스 ID입니다. Docker 컨테이너 내의 _native_는 항상 네임 스페이스 ID입니다. 즉, 호스트 데이터 (및 다른 컨테이너의 데이터)를 노출시키지 않도록 컨테이너에 물건을 넣는 것입니다. –

+0

@PJMeisch 설명서에 "네이티브 프로세스 ID는 운영 체제가 프로세스에 할당합니다 ". 어쩌면 문서가 미래에 이러한 차이를 고려할 수 있습니다. – manouti

+0

그래서 컨테이너 화 된 컨텍스트에서 운영 체제는 무엇입니까? 나는 이것이 컨테이너라는 것을 이해하고 containered id를 얻는다. –