it-swarm.com.de

Einen Prozess mit Java beenden

Ich würde gerne wissen, wie man einen Prozess "tötet", der gestartet wurde. Ich kenne die Process API, bin mir aber nicht sicher, ob ich damit einen bereits laufenden Prozess "kill" wie firefox.exe usw. "töten" kann. Wenn die Process API verwendet werden kann, können Sie mich bitte in die richtige richtung? Wenn nicht, was sind die anderen verfügbaren Optionen? Vielen Dank.

60
Jeel Shah

Wenn Sie den Prozess in Ihrer Java-Anwendung mit starten (z. B. durch Aufruf von Runtime.exec() oder ProcessBuilder.start()), verfügen Sie über eine gültige Process-Referenz, und Sie können die destroy()-Methode in der Process-Klasse aufrufen, um diesen bestimmten Prozess zu beenden. 

Beachten Sie jedoch, dass die von Ihnen aufgerufenen Prozesse möglicherweise nicht beendet werden (siehe http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=4770092 ).

Wenn Sie dagegen externe Prozesse beenden möchten (die Sie nicht aus Ihrer Java-App hervorgebracht haben), können Sie O/S-Dienstprogramme aufrufen, mit denen Sie dies tun können. Sie können beispielsweise einen Befehl Runtime.exec() für kill unter Unix/Linux versuchen und nach Rückgabewerten suchen, um sicherzustellen, dass die Anwendung beendet wurde oder nicht (0 bedeutet Erfolg, -1 bedeutet Fehler). Aber das macht Ihre Anwendungsplattform natürlich abhängig.

51
Yohan Liyanage

Unter Windows können Sie diesen Befehl verwenden 

taskkill /F /IM <processname>.exe 

es gewaltsam zu töten So wird es sein

Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")
56

AFAIU Java.lang.Process ist der Prozess, der von Java selbst erstellt wird (wie Runtime.exec ('firefox')).

Sie können systemabhängige Befehle wie verwenden 

 Runtime rt = Runtime.getRuntime();
  if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) 
     rt.exec("taskkill " +....);
   else
     rt.exec("kill -9 " +....);
30
chro

Ich bin zufällig auf einen anderen Weg gestoßen, einen Force Kill auf Unix zu machen (für diejenigen, die Weblogic verwenden). Dies ist billiger und eleganter als das Ausführen von/bin/kill -9 über Runtime.exec () .

import weblogic.nodemanager.util.Platform;
import weblogic.nodemanager.util.ProcessControl;
...
ProcessControl pctl = Platform.getProcessControl();
pctl.killProcess(pid);

Und wenn Sie Schwierigkeiten haben, die PID zu erhalten, können Sie Reflection auf Java.lang.UNIXProcess verwenden, z.

Process proc = Runtime.getRuntime().exec(cmdarray, envp);
if (proc instanceof UNIXProcess) {
    Field f = proc.getClass().getDeclaredField("pid");
    f.setAccessible(true);
    int pid = f.get(proc);
}
4
chukko

Es könnte ein Java-Interpreterfehler sein, aber Java unter HPUX führt kein kill -9 aus, sondern nur ein kill -TERM.

Ich habe einen kleinen Test testestest.Java gemacht: 

ProcessBuilder pb = new ProcessBuilder(args);
Process process = pb.start();
Thread.sleep(1000);
process.destroy();
process.waitFor();

Und die Anrufung:

$ tusc -f -p -s signal,kill -e /opt/Java1.5/bin/Java testDestroy sh -c 'trap "echo TERM" TERM; sleep 10'

stirbt nach 10s (wird nicht wie erwartet nach 1s getötet) und zeigt:

...
[19999]   Received signal 15, SIGTERM, in waitpid(), [caught], no siginfo
[19998] kill(19999, SIGTERM) ............................................................................. = 0
...

Wenn Sie dasselbe für Windows tun, scheint dies den Prozess zu beenden, auch wenn das Signal verarbeitet wird (dies kann jedoch daran liegen, dass Fenster keine Signale zum Zerstören verwenden).

Eigentlich fand ich Java - Process.destroy () Quellcode für Linux verwandte Threads und Openjava-Implementierung scheinen auch -TERM zu verwenden, was sehr falsch erscheint.

3
chukko

Versuch es:

String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();

wenn der Prozess noch läuft, fügen Sie hinzu:

p.destroyForcibly();
2
Haysa Rodrigues

Mit Java 9 können wir ProcessHandle verwenden, was die Identifizierung und Steuerung nativer Prozesse vereinfacht:

ProcessHandle
  .allProcesses()
  .filter(p -> p.info().commandLine().map(c -> c.contains("firefox")).orElse(false))
  .findFirst()
  .ifPresent(ProcessHandle::destroy)

wo "firefox" der Prozess ist, der zu töten ist.

Diese:

  • Zuerst werden alle auf dem System ausgeführten Prozesse als Stream<ProcessHandle> aufgelistet.

  • Faul filtert diesen Stream, um nur Prozesse zu behalten, deren gestartete Befehlszeile "Firefox" enthält. Sowohl commandLine als auch command können abhängig davon verwendet werden, wie der Prozess abgerufen werden soll.

  • Sucht den ersten gefilterten Prozess, der die Filterbedingung erfüllt.

  • Wenn mindestens eine Befehlszeile "firefox" enthielt, wird sie mit destroy beendet.

Kein Import notwendig, da ProcessHandle Bestandteil von Java.lang ist.

1
Xavier Guihot

Sie können einen (SIGTERM) Windows-Prozess beenden, der von Java aus gestartet wurde, indem Sie die destroy-Methode für das Process-Objekt aufrufen. Sie können auch alle untergeordneten Prozesse (seit Java 9) beenden. 

Der folgende Code startet eine Batchdatei, wartet zehn Sekunden, beendet dann alle Unterprozesse und beendet schließlich den Batchprozess selbst.

ProcessBuilder pb = new ProcessBuilder("cmd /c my_script.bat"));
Process p = pb.start();
p.waitFor(10, TimeUnit.SECONDS);

p.descendants().forEach(ph -> {
    ph.destroy();
});

p.destroy();
0
Jamie Lister