Linux и watchdog

Существует интересный механизм — watchdog. Позволяет отслеживать работоспособность системы, а в случае сбоя — произвести перезагрузку.

С помощью программной эмуляции ядром можно вызвать перезагрузку если таймер не будет сброшен в течение определённого времени.

При наличии аппаратной поддержки добавляется возможность мониторинга даже самого ядра (например загрузка системы идёт слишком долго, kernel panic или задержки при перезагрузке).

Мне в руки попался древний сервер HP Proliant ML150 G3 с аппаратным watchdog на борту. Поэтому эксперименты будут проводиться в полном объёме.

Наиболее подходящим вариантом инструментом является sys-apps/ipmiutil

Посмотреть состояние аппаратного watchdog можно следующей командой:

ipmiutil wdt -c

Для systemd поставляются штатные файлы service, которые запускают обычные скрипты инициализации, которые используют cron, создавая и удаляя для него файлы. В общем то ещё порно. Сделаем всё native systemd, раз уж в нём напилили кучу плюшек.

Итак, watchdog для монитора загрузки ОС нуждается в сервисе, который банально отключит обратный отчёт и погаснет:

#/etc/systemd/system/ipmiutil_wdt-os.service

[Unit]
Description=ipmiutil Watchdog Timer Service for OS Boot
Conflicts=ipmiutil_wdt-rt.serviceAfter=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/ipmiutil wdt -d

[Install]
WantedBy=multi-user.target

Для мониторинга работы системы надо периодически сбрасывать счётчик. Итак для запуска сервиса и настройки счётчика на 180 секунд для мягкой перезагрузки и 300 секунд для жёсткой перезагрузки (например, в случае kernel panic):

#/etc/systemd/system/ipmiutil_wdt-rt.service

[Unit]
Description=ipmiutil Watchdog Timer Service for runtime
Conflicts=ipmiutil_wdt-os.service
Requires=ipmiutil_wdt-timer.service ipmiutil_wdt-timer.timer
Before=ipmiutil_wdt-timer.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/ipmiutil wdt -e -p 3 -q 180 -a 1 -t 300
ExecStop=/usr/bin/ipmiutil wdt -d

[Install]
WantedBy=multi-user.target

Для сброса счётчика делаем следующий сервис:

#/etc/systemd/system/ipmiutil_wdt-timer.service

[Unit]
Description=ipmiutil Watchdog Timer Service for runtime timer

[Service]
Type=oneshot
ExecStart=/usr/bin/ipmiutil wdt -r >> /dev/null 2>&1

[Install]
WantedBy=multi-user.target

Ну и для того, чтобы обнуление проходило по таймеру воспользуемся штатным механизмом systemd:

#/etc/systemd/system/ipmiutil_wdt-timer.timer

[Unit]
Description=ipmiutil Watchdog Timer Service for runtime timer

[Timer]
OnUnitActiveSec=60

[Install]
WantedBy=timers.target

Для запуска достаточно набрать: systemctl start ipmiutil_wdt-rt && systemctl enable ipmiutil_wdt-rt

Далее на работу таймера можно посмотреть командой systemctl list-timers

Рыская по интернету так же нашёл ещё один метод собрать watchdog на Python:

#!/usr/bin/python2.7
from time import sleep
from watchdogdev import *

wd = watchdog('/dev/watchdog')

try:
    while True:
        print "Send Keep alive"
        wd.keep_alive()
        for j in range(10): #Chage to 15 to see RPi reboot ...
            print "... Waiting ",j,", Left :",wd.get_time_left()
            sleep(1)
except KeyboardInterrupt:
    print
    print "Magic Close"
    wd.magic_close()
    print "Done !"

https://www.freedesktop.org/software/systemd/man/systemd.unit.html
https://www.freedesktop.org/software/systemd/man/systemd.service.html
https://www.freedesktop.org/software/systemd/man/systemd.timer.html
https://wiki.archlinux.org/index.php/Systemd/Timers
http://ipmiutil.sourceforge.net/
https://www.kernel.org/doc/Documentation/watchdog/watchdog-api.txt
https://www.kernel.org/doc/Documentation/misc-devices/mei/mei.txt
http://raspberrypi.werquin.com/post/44890705367/a-hardware-watchdog-to-monitor-a-deamon-running
http://www.jann.cc/2013/02/02/linux_watchdog.html