在簡單的「Dockerized」Java程序中嘗試使用Java 9中的新的ProcessHandle
API時,發現在檢索進程ID時行爲方面存在差異正在運行的進程。特別是在調用方法ProcessHandle.pid()
,時,Docker上生成的PID與主機上顯示的本機ID不同,儘管文檔說該方法「返回進程的本機進程ID」。另外,ProcessHandle.allProcesses()
的結果有差異。Docker中的Java 9 ProcessHandle API:PID值和可見進程的差異
爲了演示,下面的程序執行以下操作:
- 打印當前進程的PID,
- 產生一個子進程,休眠幾秒鐘(允許時間打印的信息) ,
- 並最終打印所有可見的進程。
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不匹配主機上的人。
$ docker run test/java9-processhandle-example:1.0
運行上述命令後,主機顯示了以下過程:
然而,得到的程序輸出下面示出的代替的PID 1和16, 4291和4333.可見過程包括容器過程和產生的過程。
我想知道這是否是預期的。由於我對Docker相對來說比較陌生,如果這是容器造成的限制,如果有人能解釋它,我會很高興(我也不確定這是否可以在不同的Docker設置上重現,例如Linux或Windows上的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
我幾乎期待這一點。容器不應該知道主機的PID序列。 – Makoto
[docker和host之間的PID映射]的可能重複(https://stackoverflow.com/questions/33328841/pid-mapping-between-docker-and-host)..這與Java沒有多大關係,或者其版本IMO。您可以在答案中關注VonC的鏈接以瞭解詳細信息。 – nullpointer
搬到這裏,只是爲了進一步闡明,你的問題是如何在Docker中使用ProcessHandler(我懷疑內容)或在docker和host中獲取不同的PID(在這種情況下,我相信它是重複的)? – nullpointer