Há mais de uma maneira de fazer isso, mas abordarei as 4 melhores em que posso pensar. (EDIT: publiquei uma versão limpa disso como um artigo público no redhat.com. Veja: Como distinguir entre uma falha e uma reinicialização normal no RHEL 7. )
(1) logs de auditoria
auditd é incrível. Você pode ver todos os diferentes eventos que ele registra, verificando ausearch -m
. A propósito para o problema na mão, ele registra o desligamento do sistema e sistema de boot, então você pode usar o comando ausearch -i -m system_boot,system_shutdown | tail -4
. Se isso relatar um SYSTEM_SHUTDOWN seguido por um SYSTEM_BOOT , tudo estará bem; no entanto, se ele relatar 2 linhas SYSTEM_BOOT em uma linha, claramente o sistema não foi encerrado normalmente, como no exemplo a seguir:
[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) último -x
O mesmo que acima, mas com o last -n2 -x shutdown reboot
comando simples . Exemplo onde o sistema travou:
[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 onde o sistema teve uma reinicialização normal:
[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) crie sua própria unidade de serviço
Esta é a melhor abordagem para IMHO, porque você pode adaptá-la ao que quiser. Existem milhões de maneiras de fazer isso. Aqui está uma que acabei de inventar. Este próximo serviço é executado apenas no desligamento.
[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.
Então, quando o sistema inicializar, o próximo serviço será iniciado apenas se o arquivo criado pelo serviço de desligamento acima existir.
[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.
Portanto, a qualquer momento, posso verificar se a inicialização anterior foi realizada após um desligamento normal systemctl is-active check_graceful
, por exemplo:
[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 então, após um desligamento sem graça:
[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
Vale ressaltar que, se você configurar systemd-journald
para manter um diário persistente, poderá usar journalctl -b -1 -n
as últimas linhas (10 por padrão) da inicialização anterior ( -b -2
é a inicialização anterior, etc). Exemplo em que o sistema foi reiniciado normalmente:
[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
Se você obtiver uma boa saída assim, claramente o sistema foi encerrado normalmente. Dito isto, não é super confiável na minha experiência quando coisas ruins acontecem (o sistema trava). Às vezes, a indexação fica estranha.
Stopping Multi-User System
eStopped target Multi-User System
.mkdir /var/log/journal
ou explicitamente definidoStorage=persistent
em/etc/systemd/journald.conf
. Eu postei uma resposta separada.Não gosto particularmente da resposta, mas é uma resposta que recebemos do RH. Estou postando aqui caso ajude alguém.
Uma maneira possível é grep para
rsyslogd
dentro/var/log/messages
. Um desligamento gracioso teriaexiting on signal 15
. Um acidente não faria.tac /var/log/messages | grep 'rsyslogd.*start\|rsyslogd.*exit'
Duas
start
linhas consecutivas podem indicar uma falha. E umstart
seguido por umexit
pode indicar uma reinicialização.Infelizmente, também pode dar resultados ruins se o rsyslogd cair ou for reiniciado fora de uma reinicialização / falha.
fonte
exiting on signal 15
além de uma reinicialização. Um normalservice rsyslog restart
também resulta na mensagem daexiting on signal 15
mensagem.Isso parece funcionar de forma consistente para "paradas graciosas" (
shutdown
,reboot
,systemctl
), bem como "falhas" (power off, redefinirecho c > /proc/sysrq-trigger
):last -x | grep 'reboot\|shutdown'
Uma
reboot
linha seguida por umashutdown
linha indica um "desligamento normal". Duasreboot
linhas indicam uma "falha".fonte