2010-05-14 9 views
14

Ich arbeite an einer Anwendung, wo ich ein System-Shutdown erkennen muss. Allerdings habe ich keine zuverlässige Möglichkeit gefunden, eine Benachrichtigung zu dieser Veranstaltung zu erhalten.Wie erkennen Sie ausstehende Systemabschaltung unter Linux?

Ich weiß, dass beim Beenden, meine App ein Signal gefolgt von einem SIGKILL erhalten wird. Ich möchte wissen, ob es eine Möglichkeit gibt, abzufragen, ob ein SIGTERMTeil einer Abschaltsequenz ist?

Weiß jemand, ob es eine Möglichkeit gibt, das programmatisch abzufragen (C API)?

Soweit ich weiß, bietet das System keine andere Methode zur Abfrage eines bevorstehenden Herunterfahrens. Wenn das der Fall ist, würde das auch mein Problem lösen. Ich habe runlevels auch versucht, aber Änderung in runlevels scheinen sofort und ohne vorherige Warnungen zu sein.

+0

Interessante Frage zu tun. Möchten Sie das Herunterfahren stoppen oder nur benachrichtigt werden? – ereOn

+0

Ich möchte nur benachrichtigt werden. – 341008

+0

Nun, ich habe aufgegeben. Ich habe beschlossen, jedes SIGTERM als eine Nachricht zu behandeln, die das Betriebssystem herunterfahren möchte. Meine (lame ??) Begründung ist, dass SIGTERMs Hauptzweck ist, Apps höflich darum zu bitten, sauber zu beenden, und es ist unwahrscheinlich, dass jemand mit genügend Privilegien ein SIGTERM ausstellt, wenn er nicht möchte, dass die App beendet wird. Auch wenn es kein Herunterfahren ist, sollte die App darauf hören. Das bringt mich zu einer anderen Frage. Was ist die Mindestzeit zwischen einem SIGTERM und einem SIGKILL in einer Shutdown-Sequenz? Ich weiß, dass es mit -t-Schalter konfiguriert werden kann, aber gibt es eine minimale Grenze? – 341008

Antwort

5

Es kann nicht festgestellt werden, ob ein SIGTERM Teil einer Abschaltsequenz ist. Um eine Shutdown-Sequenz zu erkennen, können Sie entweder rc.d Skripte wie ereOn und Eric Sepanson verwenden oder Mechanismen wie DBus verwenden.

Aus Sicht des Designs macht es jedoch keinen Sinn, zu ignorieren, auch wenn es nicht Teil einer Abschaltung ist. 's Hauptzweck ist höflich bitten apps sauber zu beenden und es ist nicht wahrscheinlich, dass jemand mit genügend Berechtigungen eine ausstellen, wenn er/sie nicht will, dass die App beendet wird.

1

Wenn das System herunterfährt, werden die Skripte aufgerufen.

Vielleicht können Sie dort ein Skript hinzufügen, das ein spezielles Signal an Ihr Programm sendet.

Allerdings bezweifle ich, dass Sie das Herunterfahren des Systems auf diese Weise stoppen können.

+0

Danke für die schnelle Antwort. Ich habe keine Kontrolle über die Geräte, auf denen meine App installiert wird, sodass ich nichts daran ändern kann. Außerdem möchte ich nicht mit dem Herunterfahren aufhören. Ich möchte nur wissen, wann das Herunterfahren kurz bevorsteht. – 341008

+0

Nun, ich fürchte, es gibt nichts anderes zu tun (zumindest, das kann ich mir vorstellen). Vielleicht, wenn Sie uns erklären, was Sie erreichen möchten, können wir Ihnen helfen, eine Alternative zu finden? – ereOn

3

Wenn Ihre Anwendung auf einige SIGTERM-Signale anders reagiert als auf andere, erscheint sie undurchsichtig und möglicherweise verwirrend. Es ist vertretbar, dass Sie auf ein gegebenes Signal immer gleich reagieren sollten. Das Hinzufügen ungewöhnlicher Bedingungen erschwert das Verständnis und das Testen des Anwendungsverhaltens.

Das Hinzufügen eines RC-Skripts, das das Herunterfahren behandelt (indem ein spezielles Signal gesendet wird), ist ein vollständig standardmäßiger Weg, um mit einem solchen Problem umzugehen; Wenn dieses Skript als Teil eines Standardpakets installiert wird (make install oder rpm/deb packaging), sollten Sie sich keine Gedanken über die Steuerung von Benutzermaschinen machen.

5

Von Mann Abschaltung:

Wenn das Zeitargument verwendet wird, 5 Minuten, bevor das System ausfällt die /etc/nologin-Datei erstellt wird, um sicherzustellen, dass weitere Anmeldungen werden nicht zugelassen werden.

So können Sie das Vorhandensein von /etc/nologin testen. Es ist nicht optimal, aber wahrscheinlich am besten.

+0

Hmm .. Ich frage mich, ob Sie 'inotifywait' verwenden können, um auf seine Erstellung zu reagieren ... – Izkata

10

Vielleicht ein bisschen spät. Ja, Sie können feststellen, ob sich ein SIGTERM in einem Shutdown-Prozess befindet, indem Sie den Befehl runlevel aufrufen.Beispiel:

#!/bin/bash 
trap "runlevel >$HOME/run-level; exit 1" term 
read line 
echo "Input: $line" 

speichern Sie es als, sagen wir, term.sh und ausführen. Wenn Sie killall term.sh ausführen, sollten Sie die run-level Datei in Ihrem Home-Verzeichnis sehen und untersuchen können. Durch Ausführen eines der folgenden Schritte:

sudo reboot 
sudo halt -p 
sudo shutdown -P 

und vergleichen Sie den Unterschied in der Datei. Dann sollten Sie die Idee haben, wie es geht.

2

Es ist ein bisschen wie ein Hack, aber wenn der Server systemd läuft, wenn Sie können

/bin/systemctl list-jobs shutdown.target

... läuft es berichten ...

JOB UNIT   TYPE STATE 
755 shutdown.target start waiting  <---- existence means shutting down 

1 jobs listed. 

... wenn der Server herunterfährt oder neu startet (Hinweis: Es gibt ein reboot.target, wenn Sie gezielt danach suchen wollen)

Sie erhalten No jobs running. i Es wird nicht heruntergefahren.

Sie müssen die Ausgabe analysieren, die ein bisschen unordentlich ist, da das Systemctl nicht einen anderen Beendigungscode für die zwei Ergebnisse zurückgibt. Aber es scheint einigermaßen zuverlässig zu sein. Sie müssen jedoch auf eine Formatänderung in den Nachrichten achten, wenn Sie das System jedoch aktualisieren.

+0

das scheint nicht für mich zu arbeiten –

+0

Danke, funktioniert für mich – Javi

2

Ich denke, ich habe es.

Source = https://github.com/mozilla-b2g/busybox/blob/master/miscutils/runlevel.c

Ich kopiere Teil des Codes hier, nur für den Fall der Hinweis verschwindet.

#include "libbb.h" 
... 
struct utmp *ut; 
char prev; 

if (argv[1]) utmpname(argv[1]); 

setutent(); 
while ((ut = getutent()) != NULL) { 
    if (ut->ut_type == RUN_LVL) { 
     prev = ut->ut_pid/256; 
     if (prev == 0) prev = 'N'; 
     printf("Runlevel: prev=%c current=%c\n", prev, ut->ut_pid % 256); 
     endutent(); 
     return 0; 
    } 
} 
puts("unknown"); 
0

Die praktische Antwort zu tun, was Sie ursprünglich gewünscht wird, dass Sie für den Shutdown-Prozess überprüfen (zB ps aux | grep „shutdown -h“), und dann, wenn Sie Sie es Zeilenbefehl überprüfen sicher sein wollen Argumente und Zeitpunkt, zu dem es gestartet wurde (zB "shutdown -h +240" um 14:51 Uhr wird um 18:51 Uhr beendet).

Im allgemeinen Fall gibt es aus der Sicht des gesamten Systems gibt es keine Möglichkeit, dies zu tun. Es gibt viele verschiedene Möglichkeiten, wie ein "Shutdown" passieren kann. Zum Beispiel kann jemand entscheiden, den Stecker zu ziehen, um ein Programm hart zu stoppen, dass sie jetzt ein schlechtes/gefährliches Verhalten zum Zeitpunkt des Herunterfahrens hat oder eine UPS könnte zuerst einen SIGHUP senden und dann einfach scheitern. Da eine solche Abschaltung plötzlich und ohne Warnung irgendwo in einem System stattfinden kann, gibt es keine Möglichkeit, sicher zu sein, dass es in Ordnung ist, nach einem SIGHUP weiter zu laufen.

Wenn ein Prozess SIGHUP empfängt, sollten Sie grundsätzlich davon ausgehen, dass etwas fieser wird bald folgen. Wenn du etwas Spezielles tun und SIGHUP teilweise ignorieren willst, a) musst du das mit jedem Programm koordinieren, das das Shutdown macht und b) du musst bereit sein, wenn ein anderes System das Shutdown macht und dich kurz nach einem SIGHUP umbringt Ihre Software und Daten bleiben erhalten. Schreiben Sie alle Daten aus, die Sie haben, und schreiben Sie nur weiter in Append-Only-Dateien mit sicheren atomaren Updates.

Für Ihren Fall bin ich fast sicher, dass Ihre aktuelle Lösung (alle SIGHUPs als Shutdown behandeln) der richtige Weg ist. Wenn Sie die Dinge verbessern wollen, sollten Sie dem Shutdown-Programm wahrscheinlich eine Funktion hinzufügen, die über DBUS oder etwas Ähnliches benachrichtigt.

1

siehe man systemctl, können Sie bestimmen, ob das System wie folgt heruntergefahren wird:

if [ "`systemctl is-system-running`" = "stopping" ]; then 
    # Do what you need 
fi 

dies in bash ist, aber man kann es mit 'System' in C