Question

Je travaille sur une application où je dois détecter un arrêt du système. Cependant, je ne l'ai pas trouvé de moyen fiable obtenir une notification sur cet événement.

Je sais que sur l'arrêt, mon application va recevoir un signal de SIGTERM suivi d'un SIGKILL. Je veux savoir s'il y a un moyen de requête si un SIGTERM est une partie d'une séquence d'arrêt ?

Est-ce que quelqu'un sait s'il y a un moyen de requête par programmation (API C)?

Pour autant que je sache, le système ne fournit aucune autre méthode de requête pour un arrêt imminent. Dans le cas contraire, cela résoudrait mon problème aussi bien. J'ai essayé sur runlevels aussi bien, mais le changement de runlevels semble être instantanée et sans aucun avertissement préalable.

Était-ce utile?

La solution 2

Il n'y a aucun moyen de déterminer si un SIGTERM est une partie d'une séquence d'arrêt. Pour détecter une séquence d'arrêt, vous pouvez utiliser des scripts comme l'utilisation de rc.d ereOn et Eric Sepanson proposés ou des mécanismes d'utilisation comme DBus.

Cependant, d'un point de vue de la conception, il n'a pas de sens d'ignorer SIGTERM même si elle ne fait pas partie d'un arrêt. l'objectif principal de SIGTERM est de demander poliment apps pour sortir proprement et il est peu probable que quelqu'un avec assez de privilèges émettra un SIGTERM s'il / elle ne veut pas l'application pour quitter.

Autres conseils

Peut-être un peu en retard. Oui, vous pouvez déterminer si un SIGTERM est dans un processus en bas fermeture invoquant la commande runlevel . Exemple:

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

Enregistrer comme, par exemple, term.sh et l'exécuter. En exécutant killall term.sh, vous devriez pouvoir voir et enquêter sur le fichier run-level dans votre répertoire personnel. En exécutant un des éléments suivants:

sudo reboot
sudo halt -p
sudo shutdown -P

et comparer la différence dans le fichier. Ensuite, vous devriez avoir l'idée sur la façon de le faire.

De l'arrêt de l'homme:

  

Si l'argument de temps est utilisé, 5 minutes avant que le système tombe en panne   le fichier /etc/nologin est créé pour veiller à ce que de nouvelles ouvertures de session doit   pas autorisée.

Vous pouvez tester l'existence de /etc/nologin. Il n'est pas optimale, mais probablement mieux que vous pouvez obtenir.

Faire votre demande de répondre différemment à certains signaux SIGTERM que d'autres semble opaque et potentiellement source de confusion. Il est possible de soutenir que vous devez toujours répondre de la même manière à un signal donné. Ajout de conditions inhabituelles rend plus difficile à comprendre et le comportement des applications de test.

Ajout d'un script rc que l'arrêt des poignées (par l'envoi d'un signal spécial) est une façon tout à fait classique pour gérer un tel problème; si ce script est installé dans le cadre d'un ensemble standard (make install ou emballage rpm / deb) il devrait y avoir pas de soucis sur le contrôle des machines utilisateur.

Son un peu un hack mais si le serveur est en cours d'exécution systemd si vous pouvez exécuter

/bin/systemctl list-jobs shutdown.target

... il fera rapport ...

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

1 jobs listed.

... si le serveur est l'arrêt ou le redémarrage (indice: il y a un reboot.target si vous voulez regarder spécifiquement pour cela)

Vous obtiendrez No jobs running. si son arrêt ne pas être.

Vous devez analyser la sortie qui est un peu en désordre que le systemctl ne marche pas retourner un code de sortie différent pour les deux résultats. Mais il ne semble raisonnablement fiable. Vous aurez besoin de regarder pour un changement de format dans les messages si vous mettez à jour mais le système.

Je pense que je l'ai eu.

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

Je copie une partie du code ici, juste au cas où la référence disparaît.

#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");

voir man systemctl, vous pouvez déterminer si le système est en cours d'arrêt comme ceci:

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

est en bash, mais vous pouvez le faire avec « système » dans C

Lorsque le système se ferme vers le bas, les scripts rc.d sont appelés.

Peut-être que vous pouvez ajouter un script qui envoie là un certain signal spécial à votre programme.

Cependant, je doute que vous pouvez arrêter l'arrêt du système de cette façon.

La réponse pratique à faire ce que vous avez initialement voulu est que vous vérifiez le processus d'arrêt (par exemple ps aux | grep « shutdown -h ») puis, si vous voulez être sûr que vous vérifiez ses arguments de ligne de commande et temps a été lancé (par exemple « shutdown -h +240 » a commencé à 14h51 à 18h51 se arrêtera).

Dans le cas général, il est du point de vue de l'ensemble du système il n'y a aucun moyen de le faire. Il y a beaucoup de façons différentes d'un « arrêt » peut se produire. Par exemple, quelqu'un peut décider de retirer la fiche afin d'arrêter un programme difficile qu'ils a maintenant un mauvais comportement / dangereux au moment de l'arrêt ou un onduleur pourrait d'abord envoyer un SIGHUP puis simplement échouer. Etant donné qu'un tel arrêt peut se produire soudainement et sans avertissement partout d'un système, il n'y a pas moyen d'être sûr qu'il est correct de continuer à courir après un SIGHUP.

Si un processus reçoit SIGHUP vous devez assumer fondamentalement que quelque chose plus méchant suivra bientôt. Si vous voulez faire quelque chose de spécial et d'ignorer partiellement SIGHUP puis a) vous devez coordonner cela avec quel programme fera l'arrêt et b) vous devez être prêt que si un autre système fait l'arrêt et vous tue bientôt mort après une SIGHUP votre logiciel et les données survivront. Écrivez toutes les données que vous avez et seulement continuer à écrire des fichiers append uniquement avec des mises à jour atomiques sûres.

Pour votre cas, je suis presque sûr que votre solution actuelle (traiter tous les SIGHUPs comme un arrêt) est la bonne façon d'aller. Si vous voulez améliorer les choses, vous devriez probablement ajouter une fonctionnalité au programme d'arrêt qui ne Notify par DBUS ou quelque chose de similaire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top