In Linux, wenn ich die Funktion destroy auf java.lang.Process-Objekt ausführen (Was ist True typisierte java.lang.UNIXProcess) sendet es ein SIGTERM-Signal zu verarbeiten, gibt es eine Möglichkeit, es mit SIGKILL zu töten?Wie kann ich einen Linux-Prozess in Java mit SIGKILL Process.destroy() töten SIGTERM
Antwort
Nicht mit reinem Java.
Ihre einfachste Alternative ist die Verwendung von Runtime.exec()
, um einen kill -9 <pid>
-Befehl als externen Prozess auszuführen.
Leider ist es nicht so einfach, die PID zu bekommen. Sie müssen entweder Reflexions-Schwarzmagie verwenden, um auf das Feld private int pid
zuzugreifen, oder mit der Ausgabe des Befehls ps
herumspielen.
UPDATE - eigentlich gibt es einen anderen Weg. Erstellen Sie ein kleines Dienstprogramm (C-Programm, Shell-Skript, was auch immer), das die reale externe Anwendung ausführt. Codieren Sie das Dienstprogramm so, dass es sich an die PID des untergeordneten Prozesses erinnert, und richtet einen Signalhandler für SIGTERM ein, der den untergeordneten Prozess SIGKILL wird.
Stephen seine Antwort ist richtig. Ich schrieb, was er sagte:
public static int getUnixPID(Process process) throws Exception
{
System.out.println(process.getClass().getName());
if (process.getClass().getName().equals("java.lang.UNIXProcess"))
{
Class cl = process.getClass();
Field field = cl.getDeclaredField("pid");
field.setAccessible(true);
Object pidObject = field.get(process);
return (Integer) pidObject;
} else
{
throw new IllegalArgumentException("Needs to be a UNIXProcess");
}
}
public static int killUnixProcess(Process process) throws Exception
{
int pid = getUnixPID(process);
return Runtime.getRuntime().exec("kill " + pid).waitFor();
}
Sie können auch die pid auf diese Weise erhalten:
public static int getPID() {
String tmp = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
tmp = tmp.split("@")[0];
return Integer.valueOf(tmp);
}
auf Linux, ich führe Befehle durch Java (interaktiver Prozess): nslookup -> google, dies hängt den Prozess, und ich kann diesen Prozess nicht beenden. So, jetzt habe ich Ihren Vorschlag verwendet, aber es beendet diesen Prozess nicht, es hängt einfach und ich kann mein Programm nicht beenden. Ich habe sogar versucht, das Pid manuell zu töten, aber ohne Erfolg, was soll ich tun ??? –
@Space Rocker: Ein einfacher Kill sendet ein SIGTERM. Ein "kill -9" sendet eine SIGKILL. Versuchen Sie "kill -9 -1": das sendet SIGKILL an alle Prozesse in der Prozessgruppe, die pid> 1 sind. Wenn das nicht tötet, dann wird nichts passieren. Aber das wird funktionieren. –
Verwenden Sie den zweiten Weg, um die Selbst-PID zu erhalten. VisualVM macht das gleiche. Der frühere Weg ist hässlich, es ist nicht plattformübergreifend und funktioniert möglicherweise nicht in zukünftigen Java-Versionen. – Espinosa
Wenn Sie Prozessnamen kennen Sie pkill
Runtime.getRuntime().exec("pkill firefox").waitFor();
Seit Java 1.8
verwenden könnenkönnen Sie die Methode destroyForcibly()
aufrufen, die die destroy()
erfüllt hod standardmäßig, aber gemäß den Java-Dokumenten implementieren alle Unterprozesse, die von ProcessBuilder
oder Runtime.exec()
zurückgegeben werden, diese Methode.
Leider ruft die Implementierung zur Zeit einfach 'destroy()' auf. Siehe hier: https://bugs.openjdk.java.net/browse/JDK-8056139 – Joe
Ich kann es so oder in JNI machen, obwohl ich nicht so eifrig bin, es auf diese Art zu tun, woher kennst du das Pid des Prozesses, den du töten willst? – ekeren
Erstmals danke für diese Antworten. Reflexion und JNI/Exec sind meine letzte Zuflucht, ich frage mich, ob jemand einen eleganteren Weg finden kann, dies zu tun. – ekeren
Ich bin auch hart gegenüber einem Wrapper Scharfrichter, eigentlich mein Chef hart :), So verstehe ich, dass es keine direkte Art und Weise zu tun, dass Sie wissen, von. – ekeren