Введение
В данной статье рассказано про необходимость выполнения перезагрузки системы после выполнения процедуры обновления (upgrade) пакета systemd. Нижеописанное также будет относиться и к любым другим системным пакетам, для которых установлены обновления.
Вопрос перезагрузки работающего сервера возникает при необходимости обновления того или иного компонента системы. С сервисами типа веб-серверов или почты всё в целом понятно: после установки апдейта сервис необходимо перезапустить, чтобы в память подгрузилась новая версия. А вот как быть с системными компонентами, в частности, systemd? С учётом того, что эта система инициализации весьма плотно завязана на работу с другими сервисами, может возникнуть логичный вопрос: а нужно ли перезагружать систему после обновления systemd?
Перезагружать или не перезагружать
Для получения достоверного ответа, стоит обратиться к документации. Общеизвестно, что после обновления ядра, ОС необходимо перезапустить. Но существует ещё ряд компонентов системы, при обновлении которых также требуется reboot. Таковыми являются:
Red Hat Enterprise Linux 7:
- kernel
- glibc[^2]
- linux-firmware
- systemd
- udev
- dbus
Red Hat Enterprise Linux 8:
- kernel
- glibc[^2]
- linux-firmware
- systemd
- dbus
Да, среди списка присутствует systemd и казалось бы, что ответ на вопрос в самом начале статьи очевиден, но не всё так просто. Red Hat рекомендует перезагрузить систему после установки обновленного пакета. Это гарантирует, что все процессы и службы, использующие данный пакет, будут работать максимально корректно с учетом новых обновлений. Но при этом нет обязательных требований выполнять перезагрузку.
Так, обновляя openssl, очевидно, что потребуется выполнить перезапуск ещё и связанных сервисов, и от этого никуда не денешься. Но в случае с systemd можно сделать исключение, чтобы не тушить продуктивный сервер, особенно при наличии SLA.
Диагностика
Всё вышеописанное было лишь теорией и рекомендациями. А что насчёт реальной проверки? Для наглядного примера, на одной из ОС под управлением Centos 7 был обновлен пакет systemd до версии 219-78. В дистрибутивах RH-based есть возможность выполнить команду, которая покажет список обновленных пакетов и укажет на необходимость перезагрузки системы:
needs-restarting -r
Core libraries or services have been updated:
systemd -> 219-78.el7_9.3
Reboot is required to ensure that your system benefits from these updates.
Также можно посмотреть список сервисов, которые необходимо перезапустить:
needs-restarting --services
Но встречалась вполне достоверная информация с отсылкой к исходникам, что needs-restarting применительно к systemd не показывает верную информацию.
Поэтому предлагается вариант с использованием известного инструмента lsof, который может предоставить информацию о загруженных файлах в память, которые не соответствуют их копии на диске, т.е. для которых было выполнено обновление. Это хороший показатель того, что необходимо перезапустить службы или сервер:
lsof -nP +L1 | grep '(deleted)'
systemd-j 403 root txt REG 8,3 346152 0 396521 /usr/lib/systemd/systemd-journald;608fe881 (deleted)
systemd-l 611 root txt REG 8,3 635736 0 396523 /usr/lib/systemd/systemd-logind;608fe881 (deleted)
systemd-u 1736 root 6r REG 8,3 8201136 0 787720 /etc/udev/.#hwdb.binH34aaw (deleted)
- -n – запрещает преобразование адресов в доменные имена для сетевых файлов. Это позволяет работать lsof быстрее
- -P – запрещает преобразование номеров портов в имена портов для сетевых файлов, что также позволяет работать lsof быстрее.
- +L1 – указывает, что выборке подлежат только unlinked-файлы.
Для конкретного процесса, если известен PID, подойдет следующая команда:
lsof -p1 | grep deleted
Таким образом, lsof показывает, какие файлы и для каких сервисов были изменены, а дальше уже нужно принять решение о необходимости перезапуска того или иного сервиса (системы). В данном случае, при обновлении systemd команда lsof для p1 вернула пустой результат, что косвенно может говорить о том, что выполнять перезапуск systemd после upgrade не требуется.
Но есть один момент. Если обратиться к документации systemd, то можно узнать о существовании такой команды
daemon-reexec
Reexecute the systemd manager. This will serialize the manager
state, reexecute the process and deserialize the state again. This
command is of little use except for debugging and package upgrades.
Sometimes, it might be helpful as a heavy-weight daemon-reload.
While the daemon is being reexecuted, all sockets systemd listening
on behalf of user configuration will stay accessible.
Которая по всей видимости и решает вопрос “мягкого” перезапуска systemd после его обновления:
systemctl daemon-reexec
В случае возникновения ошибки вида “Failed to read server status: Access denied”, её можно исправить следующим образом. По сути daemon-reexec посылает TERM сигнал, т.е. можно выполнить:
kill -TERM 1
Заключение
В статье был рассмотрен вопрос необходимости перезагрузки системы после обновления пакета systemd. Резюмируя, можно сказать, что такой необходимости нет. При возникновении ситуации, когда нужно обновить и не перезагружать сервер, есть инструменты вида daemon-reexec.
Но всё это применимо, как мне видится, на каких-то системах, где нет ничего критичного. Лучше всегда запланировать даунтайм и выполнить плановую перезагрузку (совместив, например, с какими-то другими работами). Ведь даже Red Hat не зря рекомендует выполнять перезагрузку. А на каких-то крупных хайлоад-проектах есть балансировщики и кластеры с нескольким количеством нод, которые в любом случае можно и нужно обслуживать, а значит выводить из работы с их последующим даунтаймом.
P.S. В моём случае были обновлены следующие пакеты на продуктивных серверах без каких-либо проблем на стороне приложения и запланирован даунтайм для ребута:
- systemd-libs
- systemd
- systemd-sysv
- libgudev1