Есть ли способ определить, был ли сервер RHEL7 перезагружен с помощью systemctl (или псевдонимов перезагрузки / завершения работы) или произошел сбой сервера? До установки системы это было довольно легко определить с помощью last -x runlevel
, а вот с RHEL7 не все так однозначно.
Забавно, я просто случайно перезагрузил систему CentOS 7 прошлой ночью, поэтому у меня есть хороший журнал, на который можно посмотреть.
В случае сбоя очевидно, что между моментом сбоя и перезапуском системы ничего не регистрируется.
В случае перезагрузки это довольно очевидно, поскольку вы получаете журнал (почти) всего, что делает systemd для выключения системы.
Одна такая запись в журнале, которую вы вряд ли увидите ни при каких обстоятельствах, кроме выключения или перехода в однопользовательский режим:
Jul 13 01:27:55 yaungol systemd: Stopped target Multi-User System.
Вы можете перезагрузить собственную систему, чтобы увидеть, что на самом деле регистрируется.
Мне не особенно нравится ответ, но это ответ, который мы получили от Р. Х. Отправляю сюда на случай, если это кому-то поможет.
Один из возможных способов - использовать grep для rsyslogd
в /var/log/messages
. Изящное завершение работы exiting on signal 15
. Аварии не будет.
tac /var/log/messages | grep 'rsyslogd.*start\|rsyslogd.*exit'
Два последовательных start
линии могут указывать на сбой. И start
за которым следует exit
может указывать на перезагрузку.
К сожалению, это также может дать плохие результаты, если rsyslogd выходит из строя или перезапускается вне перезагрузки / сбоя.
Есть несколько способов сделать это, но я расскажу о 4 лучших, которые я могу придумать. (РЕДАКТИРОВАТЬ: я опубликовал очищенную версию этого как общедоступную статью на redhat.com. См.: Как отличить сбой от корректной перезагрузки в RHEL 7.)
Auditd великолепен. Вы можете увидеть все различные события, которые он регистрирует, установив флажок ausearch -m
. Что касается решаемой проблемы, он регистрирует выключение системы и загрузку системы, поэтому вы можете использовать команду ausearch -i -m system_boot,system_shutdown | tail -4
. Если это сообщает SYSTEM_SHUTDOWN за которым следует SYSTEM_BOOT, все хорошо; однако, если он сообщает 2 SYSTEM_BOOT строки подряд, то очевидно, что система не завершила работу корректно, как в следующем примере:
[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'
То же, что и выше, но с простым last -n2 -x shutdown reboot
команда. Пример сбоя системы:
[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)
Или где система корректно перезагрузилась:
[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)
ИМХО, это лучший подход, потому что вы можете адаптировать его под все, что захотите. Есть миллион способов сделать это. Вот один, который я только что придумал. Следующая служба запускается только при выключении.
[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.
Затем, когда система загружается, эта следующая служба будет запускаться только в том случае, если файл, созданный указанной выше службой завершения работы, существует.
[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.
Поэтому в любой момент я могу проверить, была ли предыдущая загрузка выполнена после корректного завершения работы, выполнив systemctl is-active check_graceful
, например:
[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.
Или вот после некорректного выключения:
[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.
Стоит отметить, что если вы настроите systemd-journald
чтобы вести постоянный журнал, вы можете использовать journalctl -b -1 -n
чтобы просмотреть последние несколько (по умолчанию 10) строк предыдущего загрузочного (-b -2
это загрузка перед этим и т. д.). Пример корректной перезагрузки системы:
[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
Если у вас такой хороший результат, значит, система корректно завершила работу. Тем не менее, по моему опыту, это ненадежно, когда случаются плохие вещи (сбои системы). Иногда индексация становится странной.
Похоже, что это работает постоянно для "плавных отключений" (shutdown
, reboot
, systemctl
), а также "сбои" (выключение, сброс, echo c > /proc/sysrq-trigger
):
last -x | grep 'reboot\|shutdown'
А reboot
строка, за которой следует shutdown
Линия указывает на «плавное завершение работы». Два reboot
линии обозначают "крах".