Comment faire la distinction entre un crash et un redémarrage sur RHEL7?

10

Existe-t-il un moyen de déterminer si un serveur RHEL7 a été redémarré via systemctl (ou des alias de redémarrage / arrêt) ou si le serveur est tombé en panne? Pré-système, c'était assez facile à déterminer last -x runlevel, mais avec RHEL7 ce n'est pas si clair.

kwb
la source

Réponses:

4

Il y a plus d'une façon de le faire, mais je vais couvrir les 4 meilleures auxquelles je peux penser. (EDIT: J'ai publié une version nettoyée de cela en tant qu'article public sur redhat.com. Voir: Comment faire la distinction entre un crash et un redémarrage gracieux dans RHEL 7. )

(1) journaux d'audit

auditd est incroyable. Vous pouvez voir tous les différents événements qu'il enregistre en vérifiant ausearch -m. Apropos au problème actuel, il enregistre l'arrêt du système et le démarrage du système, vous pouvez donc utiliser la commande ausearch -i -m system_boot,system_shutdown | tail -4. Si cela rapporte un SYSTEM_SHUTDOWN suivi d'un SYSTEM_BOOT , tout va bien; cependant, s'il signale 2 lignes SYSTEM_BOOT d' affilée, il est clair que le système ne s'est pas arrêté correctement, comme dans l'exemple suivant:

[root@a72 ~]# ausearch -i -m system_boot,system_shutdown | tail -4
----
type=SYSTEM_BOOT msg=audit(09/20/2016 01:10:32.392:7) : pid=657 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success' 
----
type=SYSTEM_BOOT msg=audit(09/20/2016 01:11:41.134:7) : pid=656 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success' 

(2) dernier -x

Comme ci-dessus, mais avec la last -n2 -x shutdown rebootcommande simple . Exemple où le système est tombé en panne:

[root@a72 ~]# last -n2 -x shutdown reboot
reboot   system boot  3.10.0-327.el7.x Tue Sep 20 01:11 - 01:20  (00:08)    
reboot   system boot  3.10.0-327.el7.x Tue Sep 20 01:10 - 01:20  (00:09)    

Ou où le système a eu un redémarrage gracieux:

[root@a72 ~]# last -n2 -x shutdown reboot
reboot   system boot  3.10.0-327.el7.x Tue Sep 20 01:21 - 01:21  (00:00)    
shutdown system down  3.10.0-327.el7.x Tue Sep 20 01:21 - 01:21  (00:00)    

(3) créez votre propre unité de service

C'est IMHO la meilleure approche parce que vous pouvez l'adapter à tout ce que vous voulez. Il y a un million de façons de procéder. En voici une que je viens d'inventer. Ce prochain service ne s'exécute qu'à l'arrêt.

[root@a72 ~]# cat /etc/systemd/system/set_gracefulshutdown.service
[Unit]
Description=Set flag for graceful shutdown
DefaultDependencies=no
RefuseManualStart=true
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/bin/touch /root/graceful_shutdown

[Install]
WantedBy=shutdown.target
[root@a72 ~]# systemctl enable set_gracefulshutdown.service 
Created symlink from /etc/systemd/system/shutdown.target.wants/set_gracefulshutdown.service to /etc/systemd/system/set_gracefulshutdown.service.

Ensuite, au démarrage du système, ce service suivant ne démarrera que si le fichier créé par le service d'arrêt ci-dessus existe.

[root@a72 ~]# cat /etc/systemd/system/check_graceful.service 
[Unit]
Description=Check if system booted after a graceful shutdown
ConditionPathExists=/root/graceful_shutdown
RefuseManualStart=true
RefuseManualStop=true

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/rm /root/graceful_shutdown

[Install]
WantedBy=multi-user.target
[root@a72 ~]# systemctl enable check_graceful
Created symlink from /etc/systemd/system/multi-user.target.wants/check_graceful.service to /etc/systemd/system/check_graceful.service.

Donc, à tout moment, je peux vérifier si le démarrage précédent a été fait après un arrêt gracieux en faisant systemctl is-active check_graceful, par exemple:

[root@a72 ~]# systemctl is-active check_graceful && echo YAY || echo OH NOES
active
YAY
[root@a72 ~]# systemctl status check_graceful
● check_graceful.service - Check if system booted after a graceful shutdown
   Loaded: loaded (/etc/systemd/system/check_graceful.service; enabled; vendor preset: disabled)
   Active: active (exited) since Tue 2016-09-20 01:10:32 EDT; 20s ago
  Process: 669 ExecStart=/bin/rm /root/graceful_shutdown (code=exited, status=0/SUCCESS)
 Main PID: 669 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/check_graceful.service

Sep 20 01:10:32 a72.example.com systemd[1]: Starting Check if system booted after a graceful shutdown...
Sep 20 01:10:32 a72.example.com systemd[1]: Started Check if system booted after a graceful shutdown.

Ou voici après un arrêt ingrat:

[root@a72 ~]# systemctl is-active check_graceful && echo YAY || echo OH NOES
inactive
OH NOES
[root@a72 ~]# systemctl status check_graceful
● check_graceful.service - Check if system booted after a graceful shutdown
   Loaded: loaded (/etc/systemd/system/check_graceful.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
Condition: start condition failed at Tue 2016-09-20 01:11:41 EDT; 16s ago
           ConditionPathExists=/root/graceful_shutdown was not met

Sep 20 01:11:41 a72.example.com systemd[1]: Started Check if system booted after a graceful shutdown.

(4) journalctl

Il convient de mentionner que si vous configurez systemd-journaldpour conserver un journal persistant, vous pouvez ensuite utiliser journalctl -b -1 -npour consulter les dernières (10 par défaut) lignes du démarrage précédent ( -b -2c'est le démarrage avant cela, etc.). Exemple où le système a redémarré correctement:

[root@a72 ~]# mkdir /var/log/journal
[root@a72 ~]# systemctl -s SIGUSR1 kill systemd-journald
[root@a72 ~]# reboot
...
[root@a72 ~]# journalctl -b -1 -n
-- Logs begin at Tue 2016-09-20 01:01:15 EDT, end at Tue 2016-09-20 01:21:33 EDT. --
Sep 20 01:21:19 a72.example.com systemd[1]: Stopped Create Static Device Nodes in /dev.
Sep 20 01:21:19 a72.example.com systemd[1]: Stopping Create Static Device Nodes in /dev...
Sep 20 01:21:19 a72.example.com systemd[1]: Reached target Shutdown.
Sep 20 01:21:19 a72.example.com systemd[1]: Starting Shutdown.
Sep 20 01:21:19 a72.example.com systemd[1]: Reached target Final Step.
Sep 20 01:21:19 a72.example.com systemd[1]: Starting Final Step.
Sep 20 01:21:19 a72.example.com systemd[1]: Starting Reboot...
Sep 20 01:21:19 a72.example.com systemd[1]: Shutting down.
Sep 20 01:21:19 a72.example.com systemd-shutdown[1]: Sending SIGTERM to remaining processes...
Sep 20 01:21:19 a72.example.com systemd-journal[483]: Journal stopped

Si vous obtenez une bonne sortie comme ça, alors le système a clairement été arrêté avec élégance. Cela dit, ce n'est pas super fiable selon mon expérience lorsque de mauvaises choses se produisent (le système plante). Parfois, l'indexation devient bizarre.

rsaw
la source
8

Drôle, je viens de redémarrer un système CentOS 7 hier soir, et j'ai donc un joli journal de tout cela à regarder.

En cas de crash, rien n'est évidemment enregistré entre le moment du crash et le redémarrage du système.

Dans le cas d'un redémarrage, c'est assez évident, car vous obtenez un journal de (presque) tout ce que systemd fait pour arrêter le système.

Une telle entrée de journal que vous ne verrez probablement en aucune circonstance autre que l'arrêt ou le passage en mode mono-utilisateur est:

Jul 13 01:27:55 yaungol systemd: Stopped target Multi-User System.

Vous pouvez redémarrer votre propre système pour voir ce qui est réellement enregistré.

Michael Hampton
la source
1
Croiriez-vous que CentOS 7 enregistre cela et que RHEL 7 ne le fait pas? C'était notre approche initiale basée sur ce que nous avons vu dans les journaux CentOS (et Fedora). Lorsque nous avons testé sur RHEL7, pas de dés.
kwb
1
@kwb Après avoir jeté un œil à un système RHEL 7.2, oui, je le crois. En fait, il semble que beaucoup de choses qui devraient être enregistrées ne le soient pas. Tout ce que je peux dire, c'est: WTF?
Michael Hampton
Je ne sais pas de quoi vous parlez. systemd dans RHEL 7.0-7.2 génère les messages Stopping Multi-User Systemet Stopped target Multi-User System.
vu le
@rsaw Nous savons bien que les messages sont générés. Le problème est qu'ils n'apparaissent pas dans le journal.
Michael Hampton
@MichaelHampton le journal n'est pas persistant par défaut. Vous ne pouvez voir les journaux de votre démarrage actuel , sauf si vous mkdir /var/log/journalou explicitement défini Storage=persistentdans /etc/systemd/journald.conf. J'ai posté une réponse séparée.
rsaw
5

Je n'aime pas particulièrement la réponse, mais c'est une réponse que nous avons obtenue de RH. Je le poste ici au cas où cela aiderait quelqu'un d'autre.

Une façon possible est de chercher rsyslogdpour /var/log/messages. Un arrêt gracieux aurait exiting on signal 15. Un crash ne le ferait pas.

tac /var/log/messages | grep 'rsyslogd.*start\|rsyslogd.*exit'

Deux startlignes consécutives peuvent indiquer un crash. Et un startsuivi d'un exitpeut indiquer un redémarrage.

Malheureusement, cela pourrait également donner de mauvais résultats si rsyslogd tombe en panne ou est redémarré en dehors d'un redémarrage / crash.

kwb
la source
Mauvais jeu Red Hat. Il existe d'autres comportements qui entraîneront la même chose en exiting on signal 15plus d'un redémarrage. Une normale service rsyslog restartentraîne également le message du exiting on signal 15message.
Stefan Lasiewski
C'est une réponse valable, mais en tant que personne qui travaille dans le support technique de Red Hat, ce n'est pas ce que j'aurais choisi. Voir ma réponse.
vu le
1

Cela semble travailler de manière cohérente pour « gracieux » (arrêts shutdown, reboot, systemctl) ainsi que des « accidents » (hors tension, remise à zéro, echo c > /proc/sysrq-trigger):

last -x | grep 'reboot\|shutdown'

Une rebootligne suivie d'une shutdownligne indique un "arrêt normal". Deux rebootlignes indiquent un "plantage".

kwb
la source