2017-10-08 14 views
2

新しい "ProcessHandle" APIをJava 9で単純な "Dockerized" Javaプログラムで試してみましたが、プロセス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のLinux上で実行されているとのWindows 7)で実行した場合、プロセスのはるかに小さいサブセットが表示されている、とPIDは、ホスト上のものと一致していません。

enter image description here

しかしながら、結果として得られるプログラムの出力は以下の代わりに、PIDが1と16を示しています。

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

上記のコマンドを実行した後、ホストは、次のプロセスを示しています見えるプロセスには、コンテナプロセスと生成されたプロセスが含まれます。

これが期待されているのでしょうか。私は比較的新しいDockerだから、もしこれがコンテナによって引き起こされた制限だとすれば、誰かがそれを説明できるならばうれしいだろう(LinuxやWindowsのDockerのような別のDockerの設定で再現可能かどうかもわからないサーバ)。さもなければ、これはコンテナに適用されたときのAPI自体の制限です(これはJavadocには記載されていないようです)。

### 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

[ドッカーとホストの間のPIDマッピング](https://stackoverflow.com/questions/33328841/pid-mapping-between-docker-and-host)の可能な複製。これはJavaまたはそのバージョンIMO。 VonCのリンクをたどって詳細を理解することができます。 – nullpointer

+0

ここに移動し、さらに明確にするために、DockerでProcessHandlerを使用する方法(コンテンツでは疑わしい)や、ドッカーとホストで異なるPIDを取得する方法があります。 – nullpointer

答えて

6

これはJavaやJava 9に特有のものではなく、ドッカーのテーマです。

各コンテナは、独自のPID名前空間を持っており、コンテナ内で実行される最初のプロセスが1

のPIDを持っているあなたは、特に、docker documentationでこれについての詳細を読むことができます:

ことでをデフォルトでは、すべてのコンテナにはPID名前空間が有効になっています。

PID名前空間はプロセスの分離を提供します。 PID名前空間は、システムプロセスのビューを削除し、プロセスIDがPIDだから--pid=host有する容器が中に暗黙としてProcessHandle.pid()が期待値を返すことができるようにするために必要とされる実行1.

+0

これはドッキングする人にはあまり意味がありません。前述のpidの名前空間を使用するものは、これを体験します。これは、他のすべての名前空間に依存しない 'unshare'を使って最下位レベルで行うことができます。 – the8472

0

含む再利用することを可能にしますドキュメント(オペレーティングシステムによって割り当てられたネイティブPID)。

また、コンテナにバインドされたプロセスだけでなく、のシステム可視プロセスが返されます。

+0

Javaの_native_pidは、通常は' ps'コマンドで表示されます。これは、例えば 'jps'が示すプロセスIDとは異なります。これらはJavaの内部プロセスIDです。 Dockerコンテナ内の_native_は常に名前空間IDです。それはホストデータ(および他のコンテナからのデータ)を公開しないようにコンテナに物を置く感覚です。 –

+0

@PJMeischドキュメントには「ネイティブプロセスIDはオペレーティングシステムはプロセスに割り当てます。将来、この違いを考慮する可能性があります。 – manouti

+0

ですから、コンテナ化されたコンテキストでオペレーティングシステムは何ですか?私はそれがコンテナであることを理解しています。したがって、コンテナのIDを取得します。 –

関連する問題