En essayant la nouvelle API ProcessHandle
en Java 9 sur un simple programme Java "Dockerized", j'ai trouvé une différence de comportement quand il s'agit de récupérer des ID de processus des processus en cours. Spécifiquement lors de l'appel de la méthode ProcessHandle.pid()
, le PID résultant sur Docker est différent de l'ID natif affiché sur l'hôte, bien que les docs disent que la méthode "renvoie l'ID de processus natif du processus". En outre, il y avait une différence entre les résultats de ProcessHandle.allProcesses()
.Java 9 ProcessHandle API dans Docker: différence dans les valeurs PID et les processus visibles
Pour démontrer, le programme ci-dessous effectue les opérations suivantes:
- imprime le PID du processus en cours,
- génère un processus enfant qui dort pendant quelques secondes (pour laisser le temps d'imprimer son info)
- et imprime enfin tous les processus visibles.
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(""));
}
Lors de l'exécution de l'application normalement (sans Docker), la sortie est comme prévu; il inclut le PID natif du processus en cours, son processus fils et beaucoup d'autres processus visibles.
### 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
Quand je cours sur Docker (Windows 7 avec Docker en cours d'exécution sur un boot2docker Linux), beaucoup plus petit sous-ensemble de processus sont visibles, et les PIDs ne correspondent pas à ceux de l'hôte.
$ docker run test/java9-processhandle-example:1.0
Après l'exécution de la commande ci-dessus, l'hôte présente les processus suivants:
Cependant, la sortie du programme résultant ci-dessous montre les PID 1 et 16, au lieu de 4291 et 4333. Et les processus visibles comprennent le processus conteneur et le processus engendré.
Je me demande si c'est prévu. Comme je suis relativement nouveau à Docker, si c'est une limitation causée par le conteneur, je serais content que quelqu'un puisse l'expliquer (je ne suis pas sûr que cela soit reproductible sur une autre configuration de Docker, par exemple Docker sous Linux ou Windows) Serveur). Sinon, est-ce une limitation de l'API elle-même lorsqu'elle est appliquée dans des conteneurs (ce qui ne semble pas être mentionné dans les Javadocs)?
### 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
Je m'attendrais presque ceci. Le conteneur ne devrait avoir aucune connaissance de la séquence PID de l'hôte. – Makoto
Possible duplication de [mappage PID entre docker et hôte] (https://stackoverflow.com/questions/33328841/pid-mapping-between-docker-and-host) .. Cela n'a pas grand chose à voir avec Java ou sa version IMO. Vous pouvez suivre les liens par VonC dans la réponse pour réaliser les détails. – nullpointer
Déplacement ici et juste pour clarifier plus loin, est votre question comment utiliser ProcessHandler dans Docker (dont je doute par le contenu) OU obtenir différents PIDs dans le docker et l'hôte (dans ce cas je crois que c'est un doublon)? – nullpointer