wiki-js/sysadmin/Linux/Bases systemD/bases-systemd.md

14 KiB
Raw Blame History

alt text

Источник: https://habr.com/ru/companies/timeweb/articles/824146/

Что бы кто не говорил, systemD становится стандартом систем инициализацией в линуксе. И с 80% вероятностью все сервера будут с systemD. Не факт, конечно, есть и личные сервера, на которых может стоять хоть Gentoo, хоть Devuan, хоть NixOS.

Некоторые дистрибутивы хотят даже перейти с загрузчика Grub на systemd-boot! Потому знать, как работать с данной системой инициализации, должен каждый сисадмин и просто программист, ибо сейчас он практически везде.

В этой статье мы разберем — создание сервисов и юнитов, как облегчить работу при помощи systemd, отслеживать состояние системы и управлять ей.

А также напишем небольшой скрипт на Python для автомизации некоторых задач. Приятного чтения, господа линуксоиды и просто пользователи!

Systemd менеджер системы и сервисов в операционной системе Linux. При разработке eго стремились спроектировать обратно совместимым со скриптами инициализации SysV init и предоставить полезные функции, такие, как параллельный запуск системных сервисов во время загрузки, активацию демонов по требованию, поддержку снепшотов состояния системы и логику управления сервисами, основанную на зависимостях.

SystemD был создан для централизации линукса, и я думаю, это пошло линуксу на пользу. Ведь так стало намного легче администрировать и настраивать сервера. А вы представьте, какой хаос творился бы, если на одном дистрибутиве стоял OpenRC, на другом runit, а не третьем sinit?

Можно долго мусолить тему systemD, но факт остается фактом — эта самая распространенная и популярная система инициализации.

Итак, вот вы находитесь в терминале. Мерцающая белая строка на черном фоне. Давайте начнем с малого, а именно загрузки системы.

Итак, перед появлением рабочего стола происходит следующий алгоритм:

Загрузка прошивки (bios или uefi). Загрузчик (чаще всего GRUB). Именно он принимает управление после прошивки (P. S. если используется UEFI, то эта прошивка может напрямую запустить систему, без загрузчика). Загрузчик перемещает ядро и файлы initramfs в память и запускает ядро. Предпоследний момент — монтирование настоящего корневого каталога и запуск /sbin/init, то есть системы инициализации. И последний — getty. init запускает для каждого виртуального терминала (обычно их шесть) программу getty, которая инициализирует терминалы и запрашивает имя пользователя и пароль. Предоставленные входные данные getty проверяет по файлам /etc/passwd и /etc/shadow, после чего вызывает логин или запускает менеджер экрана, если таковой имеется.

Мы будем обсуждать предпоследний момент, в частности — систему инициализации. В Linux после загрузки ядра начинается загрузка сервисов, системы, юнитов и других компонентов. За это отвечает специальный процесс с PID 1, который называется init process или процесс инициализации. Он запускается сразу после запуска ядра и завершается с последним вздохом системы.

alt text

Вообще, systemD — это не только один процесс. Systemd — подсистема инициализации и управления службами в Linux, фактически вытеснившая в 2010-е годы традиционную подсистему init. Основная особенность — интенсивное распараллеливание запуска служб в процессе загрузки системы, что позволяет существенно ускорить запуск операционной системы. А также это многие другие сервисы, программы и службы для управления системой.

alt text

Сюда входит и systemd-resolve (определяет режим работы автоматически в зависимости от того, является ли /etc/resolv.conf символической ссылкой на файл заглушки или содержит адреса серверов), и systemctl (утилита для управления через командную строку) и многие другие. Из-за этого, кстати, многие считают, что systemD перегружен.

История systemd

Давайте поговорим об истории создания и популяризации systemd в линуксе. 14 лет назад, в далеком 2010 году systemd был разработан Ленартом Поттерингом. Вообще, он довольно известный программист, приложил свою руку к созданию Avahi и PulseAudio. Когда-то работал в Red Hat, но после уволился и перешел в Microsoft. Эта система инициализации устроила революцию в мире линукса. Сколько жарких споров и холиваров было разведено…

В издании UNIX от 1979 года задач у init — процесса с PID 1 — две, это выполнить при старте /etc/rc и создать процессы getty и login. Позже, по мере развития линукса, к задачам стали прибавляться все новые и новые. И в конце концов осталась одна основная задача инициализатора — привести систему в полную готовность к работе, запустить базовые процессы и пользовательское пространство.

Но время неумолимо двигалось вперед. Теперь стали появляться сервисы, с множествами юнитами и скриптами, и при помощи старой SysV init стало неудобно управлять системой. Сервисы в SysV запускались последовательно, так что если захочется контролировать время запуска одного сервиса — придется контролировать все сервисы. А также это было просто медленно. Зависимости между сервисами в SysV были сложными.

Также SysV просто запускал и отключал сервисы, он не имел ни контроля ресурсов, не журналирования, не управления сетью. Также SysV имел множество разрозненных утилит, в отличии от systemD.

И под конец — SysV имел проблемы с надежностью и безопасностью. Пример ненадежности — это небезопасное выключение системы. SysVinit полагается исключительно на загрузочные скрипты, чтобы отмонтировать файловые системы и остановить процессы. Это крайне небезопасно и может вылиться в потерю данных в худших случаях.

Кроме SysV был еще UpStart, разработанный Canonical. Его главная концепция — event-driven подход. Запуск системы — это событие, новое устройство — событие, запуск демона — событие. Процессы могли подписываться на события и запускаться только при явной необходимости. Upstart совместим с sysvinit-скриптами, благодаря этому он был быстро интегрирован во многие дистрибутивы Linux. Тем не менее, после того, как большинство дистрибутивов Linux по тем или иным причинам перешли на systemd, разработка сошла на нет: последний релиз был в 2014-м году, и сегодня Upstart используется только в Chrome OS.

После всего этого Ленарт в своем блоге опубликовал https://0pointer.de/blog/projects/systemd.html

В этом сообщении были сказаны несколько основополагающих вещей современного systemD:

Параллельный запуск сервисов, а не поочередный Запускать меньше демонов и сервисов. Если требуется сетевые — то подключаем их, и так далее. Инициализатор должен быть динамичным, реагировать на любые изменения, а после перезапускать или останавливать службы.

В то же время Поттеринг подчёркивает, что эти идеи не новые, и уже известна система с такими возможностями — launchd от Apple, система инициализации в macOS. launchd имеет схожие с Upstart event-driven идеи, но более того, он вобрал в себя задачи других системных сервисов, таких, как cron и inetd.

Другие возможности, которыми должен обладать хороший, по мнению Поттеринга, PID 1:

Распараллеливание задач файловых систем. Проверка на ошибки, монтирование и квотирование. Что, если монтировать файловые системы одновременно, или только при доступе к ним? Отслеживание процессов. Одна из задач системы управления сервисами — это мониторинг процессов. Перезапускать, если они упали. Собрать информацию, если они крашнулись. Кроме того, система должна уметь останавливать сервисы, что может быть непросто, если процесс сделал двойной вызов fork(). Управление ресурсами сервисов. В идеале, init должен настроить окружение updatedb (обновление БД команды locate) так, чтобы процесс выполнялся только при полном бездействии. Логирование также является важной частью выполнения сервисов. Несмотря на то, что логи — сложная штука, простые сценарии типа вывода в stdout/stderr или обработка логов ядра (dmesg) должны решаться компонентами init.

Подведем итог. После нескольких месяцев борьбы, дистрибутивы стали мало-помалу принимать systemd — Fedora, OpenSuSE. В августе 2012 года Arch Linux переключился также на systemd. Позже systemd начал проникать в другие дистрибутивы — Ubuntu, Debian (2015, в 8 версии). И так творение Поттеринга стало стандартом инициализации в линуксе.

Итак, вернемся к systemd.