Вспомнилось
Прочтите «systemdЫ» с ударением на последний слог и почувствуйте запах казахской степи, терпкий вкус кумыса, просторный уют юрты.
Собственно, всё в названии. Systemd решил просто перестать работать и вообще на всё выдавать ошибку. Я даже запустить систему в tty больше не смог. Пришлось реинсталлить с загрузочной флешки. По ощущениям - случилась какая-то бурятская магия. Если что, произошло всё под управлением CachyOS. Вдруг проблема распространённая, а я просто не слышал.
Хз зачем пост, просто захотелось поделиться радостью. Свершилось - Линь сломалась =)
Комментируя намерение разработчиков Fedora включить по умолчанию фоновый процесс earlyoom для раннего реагирования на нехватку памяти в системе, Леннарт Поттеринг (Lennart Poettering) рассказал о планах по интеграции в systemd другого решения - oomd. Обработчик oomd развивает компания Facebook, сотрудники которой параллельно разрабатывают подсистему ядра PSI (Pressure Stall Information), позволяющую обработчику нехватки памяти в пространстве пользователя проанализировать информацию о времени ожидания получения различных ресурсов (CPU, память, ввод/вывод) для точной оценки уровня загруженности системы и характера замедления работы.
Оomd находится на финальной стадии создания универсального продукта, пригодного для любых рабочих нагрузок без проведения дополнительного тюнинга. После того как в ядро Linux будут добавлены последние недостающие компоненты интерфейса PSI ("iocost"), компания Facebook намерена передать oomd или его упрощённую версию для включения в состав systemd. Ожидается, что это произойдёт через полгода или год. Earlyoom может быть использован в Fedora как временное решение до тех пор, пока oomd не будет доведён до должного вида, но в долгосрочной перспективе Поттеринг считает, что будущее за oomd.
Бенджамин Берг (Benjamin Berg), один из инженеров Rad Hat, занимающийся разработкой GNOME, обобщил результаты работы по переводу GNOME на управление сеансами исключительно средствами systemd, без применения процесса gnome-session.
Для управления входом в GNOME уже достаточно давно применяется systemd-logind, который отслеживает состояния сеансов в привязке к пользователю, управляет идентификаторами сеансов, отвечает за переключение между активными сеансами, координирует многопользовательские окружения (Multi-seat), настраивает политики доступа к устройствам, предоставляет средства для завершения работы и перехода в спящий режим и т.п.
При этом часть связанной с сеансами функциональности оставалась на плечах процесса gnome-session, который занимался управлением через D-Bus, запуском дисплейного менеджера и компонентов GNOME, организацией автозапуска указанных пользователем приложений. В процессе разработки GNOME 3.34 специфичные для gnome-session возможности оформлены в виде unit-файлов для systemd, выполняемых в режиме "systemd --user", т.е. в привязке к окружению конкретного пользователя, а не всей системы. Изменения уже применены в дистрибутиве Fedora 31, выпуск которого ожидается в конце октября.
Использование systemd дало возможность организовать запуск обработчиков по требованию или при наступлении определённых событий, а также более изощрённо реагировать на преждевременное завершения процессов из-за сбоев и расширенно обрабатывать зависимости при запуске компонентов GNОME. Как следствие, можно сократить число постоянно запущенных процессов и снизить потребление памяти. Например, XWayland теперь можно запускать только при попытке выполнения приложения на базе протокола X11, а специфичные для определённого оборудования компоненты, только при наличии такого оборудования (например, обработчики для смарткарт будут запускаться при вставке карты и завершаться при её извлечении).
Для пользователя появились более гибкие инструменты управления запуском сервисов, например, для отключения обработчика мультимедийных клавиш будет достаточно выполнить "systemctl --user stop gsd-media-keys.target". В случае проблем, связанные с каждым обработчиком логи можно просмотреть командой journalctl (например, "journalctl --user -u gsd-media-keys.service"), предварительно включив в сервисе ведение отладочного лога ("Environment=G_MESSAGES_DEBUG=all"). Также появилась возможность запуска в изолированных sandbox-окружениях всех компонентов GNOME, к которым предъявляются повышенные требования к безопасности.
Для сглаживания перехода, поддержку старого способа запуска процессов планируется сохранить в течение нескольких циклов разработки GNOME. Далее разработчики проведут рецензирование состояния gnome-session и скорее всего (отмечено как "likely") удалят из него средства запуска процессов и сопровождения D-Bus API. Затем применение "systemd --user" будет переведено в разряд обязательных функций, что может создать трудности для систем без systemd и потребует подготовки альтернативного решения, как в своё время было с systemd-logind. Тем не менее, в своём выступлении на конференции GUADEC 2019 Бенджамин Берг упомянул о намерении сохранить поддержку старого метода запуска для систем без systemd, но данная информация расходится с планами на странице проекта.
UPD: До активного внедрения systemd куда только можно, и, даже куда нельзя, sysvinit вполне себе в разговоре и в литературе назывался именем systemv, вот например https://www.ibm.com/developerworks/ru/library/l-systemv/ документ от нашумевшей нынче ibm где так и написано "Исторически сложилось так, что традиционно в среде UNIX существуют две системы инициализации – SystemV и BSD.
Зы и да я знаю что это не специально, а особенности поискового движка, но это забавно
При написании предыдущего поста про systemd наткнулся на интересную таблицу, где приводилось соответствие между командами systemd и SysVinit. Единственный "минус" был в том, что таблица была на английском, поэтому решил перевести и выложить, вдруг кому-то надо.
Перевод (кликните для увеличения):
И оригинал (кликните для увеличения):
Взято отсюда - http://linoxide.com/linux-command/systemd-vs-sysvinit-cheatsheet/
Там еще есть и pdf-версия. Русскую pdf-версию кинул на мыльное облако.
Если есть ошибка/неточность - пишите. Исправлю.
ps.
Очень удобно редактировать векторный pdf в Inkscape.
Внимание! Данный пост не для холивара в стиле "нужен/не нужен", "не unix-way", "когда Поттеринг запилит свою ось?" и т.п. Пост содержит исключительно информацию по работе с systemd.
Привет вам, красноглазые братья и сёстры!
Эта статья посвящена, как видно из названия, системе systemd. Первый пост скорее обзорный и начнем мы с вами с исторического экскурса.
----------------------------------------------------
Глава 1. В плену shell-скриптов.
----------------------------------------------------
Давным-давно, в далекой-предалекой галактике примерно 14 млрд. лет назад не было ничего. Ни света, ни пространства, ни времени. Потом произошел Большой взрыв и потребовалось еще очень много времени, пока первый человек встал прямо и начал использовать свой разум. И навострился настолько, что по прошествии еще некоторого времени изобрел транзистор, а потом и компьютер. Компьютер сам по себе штука бесполезная, нужны были проги и операционная система. И родил человек Unix.
Операционной системе нужна была система инициализации (СИ, не путать с языком программирования!). Для совсем новичков, СИ - это действия, совершаемые при загрузке системы. Запуск программ, демонов всего лишь часть СИ.
Думали-думали и придумали в пятой версии Unix систему под названием init (SysVinit). Она позволяла запускать скрипты и вводила концепцию уровней инициализации (т.н. runlevels). Скрипты (обычно они лежат в /etc/init.d/) - это просто скрипты (простите за тавтологию) на языке shell-а, где описаны специальные функции, вроде start(), stop(), reload() и т.п. Это позволяло запускать скрипты вот таким образом (пример - демон web-сервера apache)
/etc/init.d/apache2 start
Запускать, конечно, хорошо, но лучше, чтобы все делалось автоматически при старте. И тут на помощь приходят уровни инициализации (УИииииииии). Всего уровней в системе могло быть до 7 штук (Оффтопик. УИ - это что-то по типу безопасного режима в винде, только тут таких режимов больше и они более настраиваемые). Обычно это:
> 0 - остановка системы;
> 1 - однопользовательский режим (иногда называемый режимом восстановления);
> 2/3 - многопользовательский с/без поддержки сети.
> 5 - графический режим
> 6 - перезагрузка
Для каждого из уровней в каталоге /etc был свой каталог с именем rcN.d, где N - номер уровня. Внутри этих директорий содержались симлинки (символическая ссылка - прим.) на скрипты из каталога /etc/init.d/, которые должны запускаться при переходе на соответ. уровень (или останавливаться при уходе). Какой должен запускаться, а какой останавливаться, а также порядок запуска (остановки) регулировался именем симлинка. В общем случае выглядит это вот так
Snnимя
Knnимя
Здесь S и K - обозначения старта и остановки (S - старт, K - остановка), nn - двухзначное число, используемое для обозначения порядка запуска (чем выше, тем позднее), имя - произвольное имя.
Уровень по умолчанию задавался в файле /etc/inittab, а поменять на лету можно было при помощи команды init номер_уровня. Например,
init 0
для выключения машины. Все скрипты запускались последовательно (это важно!). Позднее Ubuntu запилила свою СИ с блэкджеком и событийной моделью под именем upstart. Но о ней мы говорить не будем, т.к. даже сама Ubuntu отказалась от неё в пользу systemd.
Ладно, переборщил я со вступлением. Держите скрин и переходим к "виновнику торжества".
--------------------------------------------------
Глава 2. Systemd и все-все-все.
--------------------------------------------------
Systemd (в дальнейшем буду использовать сокращение sd) - это "система инициализации". Именно в кавычках, потому что она вобрала в себя огромную кучу функции. Кстати, именно это является главной причиной ненависти некоторых людей к systemd - нарушения принципа "unix-way".
Примечание: unix-way - принцип, согласно которому, одна программа - одна функция. Т.е. каждая программа должна выполнять одну функцию, но делать это достаточно хорошо, а не иметь 100500 плохо написанных функций.
systemd написана немецким программистом Леннартом Поттерингом (старшим братом Гарри Поттера). Основные причины (имхо) появления sd - попытка избавиться от shell-скриптов, распараллелить загрузку и иметь единую точку контроля всего и вся. Отсюда плюсы sd (копипаст с арчвики):
systemd обеспечивает возможности агрессивной параллелизации, использует сокеты и активацию D-Bus для запускаемых служб, предлагает запуск демонов по необходимости, отслеживает процессы при помощи контрольных групп Linux, поддерживает мгновенные снимки и восстановление состояния системы, монтирование и точки монтирования, а также внедряет основанную на зависимостях логику контроля процессов сложных транзакций.
На сегодняшний день sd применяется в Debian (c 8-й версии), Ubuntu (с 15.04 версии), Fedora (c 15 версии), openSUSE (с 12.1), ArchLinux (12.11) и т.д.
Основная базовая единица в sd - это сущность под названием юнит (unit). НЕ стоит думать, что юнит - это просто аналог shell скрипта из SysVinit (см. выше). Юниты бывают разных типов и тип service (наиболее близкий к shell скрипту из SysVinit) всего лишь один из них. Но это я забежал вперед.
Юнит - это текстовой ini-файл с описанием. Файл разделен на секции, внутри секций задаются параметры. Две секции допустимы во всех юнитах, остальные в зависимости от типа юнита. Есть три каталога, где могут храниться юниты.
> /usr/lib/systemd/system - системные юниты, поставляемые обычно вместе с приложениями;
> /run/systemd/system - динамически создаваемые юниты (т.е. на лету);
> /etc/systemd/system - юниты и исправления, внесённые администратором
Расположены директории в порядке повышения приоритета.
Юниты можно запускать и останавливать.
Как я сказал, юниты делятся на типы (с соответ. расширениями файлов):
> service - аналог демона или что-либо, что можно запустить;
> device - факт подключения какого-либо устройства (имя юнита генерируется из sysfs-имени устройства);
> target - ничего не описывает, группирует другие юниты;
> mount - точка монтирования файловой системы (имя юнита должно соотвествовать пути до точки монтирования);
> automount - аналог autofs: точки автомонтирования (должен существовать *.mount-юнит с тем же именем);
> timer - аналог cron. Периодический запуск другого юнита (по умолчанию запускаться будет *.service-юнит с тем же именем);
> socket - аналог xinetd. Запуск юнита при подключении к указанному сокету (по умолчанию запускаться будет *.service-юнит с тем же именем);
> path - запуск юнита по событию доступа к какому-либо пути в файловой системе (по умолчанию запускаться будет *.service-юнит с тем же именем);
> slice - группирует другие юниты в дереве cgroups, позволяя иерархично задавать ограничения по используемым ресурсам;
Примечение: cgroups - это способ объединения процессов, чтобы заюзать для них какие-то правила или ограничения. Например, ограничения на проц или память.
Не пугайтесь, если не все понятно. Москва тоже не сразу строилась. Все типы мы рассматривать не будет, это материал для отдельной статьи. Но для примера, а также чтобы пояснить понятие зависимостей требования/порядка, рассмотрим юнит типа service - sshd.service
Конечно, можно просто открыть файл в текстовом редакторе или использовать утилиту cat, но гораздо удобнее использовать для этого спец. команду;
systemctl cat sshd.service
Как я уже сказал, юнит делится на секции. В данном случае их три - [Unit], [Service] и [Install].
Секции [Unit] и [Install] могут быть в любом юните, а секция [Service] - спец. секция юнитов типа service.
Секция [Unit] содержит основную информацию о юните, а также о зависимостях порядка и зависимостях требования. Итак, параметры:
> Description= - тут просто описывается данный юнит. Набор слов, если проще.
> Wants= - о, интересный параметр. Это так называемые зависимости требования. Еще один из них (его тут нет) - это Requires=. И том и в другом случае, юнит хочет, чтобы сервис (или просто программа), указанный в параметре (назовем его зависимым юнитом), были запущенны, но при этом, если указано Wants=, то юниту пофиг на исход запуска. Пусть даже он упал, при старте. Requires= же таких вольностей не прощает и просто прекратит запуск юнита, если зависимый юнит не стартанул. Конкретно в этом случае, будет предпринята попытка запуска сервиса sshdgenkeys, но исход запуска нам по барабану.
> After= и парный ему Before= - это зависимости порядка. Все довольно просто и понятно, запускать данный юнит до или после.
Важно!
Зависимости порядка и зависимости требования НЕ связаны между собой. В данном примере, сказано, что sshd.service должен запустится после network.target. Но это никоим образом не значит, что network.target будет запущен! Однако если он запущен (допустим, его запустил другой сервис), то стартуем после него, если не запущен, то и фиг с ним.
На основе информации о зависимостях порядка и зависимостях требования sd строит так называемое дерево зависимостей. Чтобы понять это, представьте себе перевернутое дерево с корнем наверху, а вместо листьев у него юниты. Что-то похожее делает и sd при старте (сохр, до выключения/перезагрузки - прим.). Далее (тут только моё предположение) все юниты на одном уровне стартую одновременно (ака параллельно), в отличие от SysVinit, где была последовательная загрузка. Параллельный запуск обеспечивает ускорение запуска (хотя в вике написано, что в последних версиях уже нет).
Но вернемся к sshd. Секция [Service] описывает тип юнита service. В других типах своё. Например, в юнитах типа socket есть секция [Socket]
> ExecStart= - как запустить.
> ExecReload= - как перечитать конфиг, тут все просто.
> KillMode= описывает как будет убит процесс. Конкретно в этом случае сказано, что сигнал убийства (мухахахаа - зловещий смех - прим.) будет послан только главному процессу, а как быть со своими потомками ему решать.
> Restart= - описывает когда сервис будет перезапускать процесс при падении (или других катаклизмах). В мане есть табличка, которая объясняет всё немного лучше (это относится и к ману systemd в целом xD)
man systemd.service
Секцию [Install] пока просто запомним, ниже расскажу, где она используется.
Пока вы должны понять, что есть такая сущность, как юнит, что юниты делятся на типы и что юниты объединяются в дерево зависимостей на основе зависимостей требования и зависимостей порядка.
------------------------------------
Глава 3. Одна за всех.
------------------------------------
Прежде чем начинать описывать команды, хотелось бы пару слов сказать про юнит типа target. Как кратко было сказано выше, этот тип юнита не делает ничего, просто объединяя другие юниты. Технически этот юнит представляет из себя директорию с симлинкми на другие юниты.
Target-ы являются аналогами уровней в SysVinit. Т.е., допустим, target с именем multi-user является аналогом 2/3 уровня и содержит симлинки на юниты, которые будут запущены при выполнении этого target-а. По умолчанию выполняется target с именем default.target, который обычно является псевдонимом для graphical.target (аналог 5 уровня).
Итак команды. Основная команда, это
systemctl
Примечание: В дальнейшем unit_name - имя юнита, заменяйте на нужный. Команды запускались от рута.
systemctl, запущенная без параметров, является псевдонимом для более полной команды systemctl list-units. Она покажет список юнитов, а также их состояния. С помощью ключа -t можно задать тип юнитов, а --all выведет все юниты, в том числе и неактивные. Например:
systemctl list-units -t target --all
Команда
systemctl status
покажет общее состояние системы и перечислит юниты, которым соответствуют какие-либо запущенные процессы. В то же самое время, эта команда, дополненное именем юнита покажет более подробную информацию о юните. Например:
systemctl status sshd.service
Команда
systemctl cat unit_name
покажет содержимое юнита.
Переходим к самому интересному - запуск и остановка юнита. Снова systemctl.
systemctl start unit_name
systemctl stop unit_name
Примечание: по умолчанию принимается тип service. Таки образом команды
systemctl start sshd.service
и
systemctl start sshd
эквивалентны.
Тут все просто и понятно. Единственное, что стоит уточнить, так это то, что эти манипуляции применяются только в текущей сессии. При рестарте все вернется на круги своя.
А что тогда делать, если мы хотим добавить юнит в автозагрузку? Опять systemctl
systemctl enable unit_name
systemctl disable unit_name
Еще помните секцию Install, которую я сказал, что опишу позднее? Если не помните, то вот она:
[Install]
WantedBy=multi-user.target
Ну так вот, эта секция используется командами systemctl enable/disable для добавления симлинка в нужный target (создания иск. зависимости). Конкретно в этом случае, при выполнении команды
systemctl enable sshd.service
в папке multi-user.target будет создан симлинк на sshd.service и при выполнении данного target-a sshd будет запущен.
Кстати, проверить наличие юнита в автозагрузке можно командой
systemctl is-enabled unit_name
Она вернет enabled/disabled. Логично же)
Даже выключенный и убранный из "автозагрузки" unit может быть запущен как зависимость. Но что, если мы хотим совсем выключить юнит, чтобы нельзя было запустить даже как зависимость? Для этого юниты из /usr/lib/systemd/system и /run/systemd/system - можно замаскировать командой
systemctl mask unit_name
Это команда создает симлинк на /dev/null в /etc/systemd/system с именем маскируемого юнита. (Напомню, этот каталог имеет наивысший приоритет). Тут проявляется ограничение - нельзя замаскировать юнит из папки /etc/systemd/system. Обратная команда
systemctl unmask unit_name
просто удаляет симлинк.
Возвращаясь к target-ам. В начале главы я сказал, что target-ы - аналоги уровней в SysVinit и то, что multi-user.target - 3 уровень, а graphical.target - 5 уровень. Вполне логично предположить, что есть и для оставшихся уровней.
> 0 - poweroff.target либо halt.target
> 1 - rescue.target
> 6 - reboot.target
Само собой, что можно просто запустить нужный target. Например:
systemctl start poweroff.target
Но гораздо проще использовать сокращенный аналог, убрав start и target, т.е.:
systemctl poweroff
systemctl halt
systemctl reboot
systemctl rescue
Также у нас имеется "лицензия на убийство"
systemctl kill unit_name
По умолчанию посылается сигнал TERM (не уверен), но можно послать определенный сигнал c помощью опции -s. Имена сигналов можно получить набрав команду kill -l
systemctl kill -s HUP unit_name
Хотите перезапустить все юниты и перестроить дерево зависимостей? Не проблема
systemctl daemon-reload
Разумеется, что описать всё и вся в одной статье не получится. Лично я планировал X статей с описанием systemd, Y статей с самописными примерами и Z c тем, что я наслоупочил. (X,Y,Z - произвольные натуральные числа), но когда это будет я не решусь сказать.
-----------------------------------------------
Использованная литература:
-----------------------------------------------
Арчвики, цикл видеоподкастов "Systemd In Action", цикл статей на Rus-LInux.
Спасибо за внимание.
Bonus. Хозяйке на заметку.
Команда
systemd-analyze
покажет время загрузки системы.