Como você pode distinguir entre uma falha e uma reinicialização no RHEL7?

9

Existe uma maneira de determinar se um servidor RHEL7 foi reinicializado via systemctl (ou alias de reinicialização / desligamento) ou se o servidor travou? Antes do sistema, isso era fácil de determinar last -x runlevel, mas com o RHEL7 não é tão claro.

kwb
fonte

Respostas:

3

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 rebootcomando 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-journaldpara manter um diário persistente, poderá usar journalctl -b -1 -nas ú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.

rsaw
fonte
7

Engraçado, por acaso reinicializei um sistema CentOS 7 ontem à noite, e por isso tenho um bom registro disso para ver.

No caso de uma falha, obviamente nada é registrado entre o momento da falha e a reinicialização do sistema.

No caso de uma reinicialização, é bastante óbvio, pois você obtém um log de (quase) tudo o que o systemd está fazendo para desligar o sistema.

Uma dessas entradas de log que você provavelmente não verá em nenhuma circunstância além de desligar ou ir para o modo de usuário único é:

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

Você pode reiniciar seu próprio sistema para ver o que realmente é registrado.

Michael Hampton
fonte
1
Você acreditaria que o CentOS 7 registra isso e o RHEL 7 não? Essa foi a nossa abordagem inicial com base no que vimos nos logs do CentOS (e Fedora). Quando testamos no RHEL7, não há dados.
Kwb
1
@kwb Depois de dar uma olhada no sistema RHEL 7.2, acredito que sim. De fato, parece que muitas coisas que devem ser registradas não estão sendo registradas. Tudo o que posso dizer é: WTF?
22660 Michael JacksonJul
Não tenho certeza do que vocês estão falando. O systemd no RHEL 7.0-7.2 gera as mensagens Stopping Multi-User Systeme Stopped target Multi-User System.
rsaw
@rsaw Estamos cientes de que as mensagens são geradas. O problema é que eles não estão aparecendo no diário.
Michael Hampton
@MichaelHampton, o diário não é persistente por padrão. Você só pode ver registros de sua inicialização atual a menos que você mkdir /var/log/journalou explicitamente definido Storage=persistentem /etc/systemd/journald.conf. Eu postei uma resposta separada.
rsaw
5

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 rsyslogddentro /var/log/messages. Um desligamento gracioso teria exiting on signal 15. Um acidente não faria.

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

Duas startlinhas consecutivas podem indicar uma falha. E um startseguido por um exitpode indicar uma reinicialização.

Infelizmente, também pode dar resultados ruins se o rsyslogd cair ou for reiniciado fora de uma reinicialização / falha.

kwb
fonte
Jogo ruim Red Hat. Existem outros comportamentos que resultarão no mesmo, exiting on signal 15além de uma reinicialização. Um normal service rsyslog restarttambém resulta na mensagem da exiting on signal 15mensagem.
Stefan Lasiewski
Esta é uma resposta válida, mas como alguém que trabalha no suporte técnico da Red Hat, não é com isso que eu teria concordado. Veja minha resposta.
rsaw
1

Isso parece funcionar de forma consistente para "paradas graciosas" ( shutdown, reboot, systemctl), bem como "falhas" (power off, redefinir echo c > /proc/sysrq-trigger):

last -x | grep 'reboot\|shutdown'

Uma rebootlinha seguida por uma shutdownlinha indica um "desligamento normal". Duas rebootlinhas indicam uma "falha".

kwb
fonte