Systemd для самых маленьких. Часть I. Знакомство

Systemd для самых маленьких. Часть I. Знакомство Linux, Systemd, Урок, Длиннопост

Внимание! Данный пост не для холивара в стиле "нужен/не нужен", "не unix-way", "когда Поттеринг запилит свою ось?" и т.п. Пост содержит исключительно информацию по работе с systemd.


Systemd для самых маленьких. Часть I. Знакомство Linux, 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.

Ладно, переборщил я со вступлением.  Держите скрин и переходим к "виновнику торжества".

Systemd для самых маленьких. Часть I. Знакомство Linux, 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) и т.д.

Systemd для самых маленьких. Часть I. Знакомство Linux, Systemd, Урок, Длиннопост

Основная базовая единица в 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

Systemd для самых маленьких. Часть I. Знакомство Linux, Systemd, Урок, Длиннопост

Как я уже сказал, юнит делится на секции. В данном случае их три - [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


Systemd для самых маленьких. Часть I. Знакомство Linux, Systemd, Урок, Длиннопост

Секцию [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

покажет содержимое юнита.

Systemd для самых маленьких. Часть I. Знакомство Linux, Systemd, Урок, Длиннопост

Переходим к самому интересному - запуск и остановка юнита. Снова 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

Systemd для самых маленьких. Часть I. Знакомство Linux, Systemd, Урок, Длиннопост

Разумеется, что описать всё и вся в одной статье не получится. Лично я планировал X статей с описанием systemd, Y статей с самописными примерами и Z c тем, что я наслоупочил. (X,Y,Z - произвольные натуральные числа), но когда это будет я не решусь сказать.


-----------------------------------------------

Использованная литература:

-----------------------------------------------


Арчвики, цикл видеоподкастов "Systemd In Action", цикл статей на Rus-LInux.



Спасибо за внимание.


Bonus. Хозяйке на заметку.

Команда

systemd-analyze

покажет время загрузки системы.

GNU/Linux

1K постов15.5K подписчика

Добавить пост

Правила сообщества

Все дистрибутивы хороши.

Будьте людьми.

Вы смотрите срез комментариев. Показать все
7
DELETED
Автор поста оценил этот комментарий

Данный пост не для холивара в стиле

А о чем можно холиварить? Кучу непойми-как связанного дерьма заменили одной однородной и понятной системой. К тому же очень производительной. И объединяющей разные дистрибутивы.


Там, где я раньше писал несколько десятков длинных нечитабельных строк, теперь хватит и пяти простых и понятных.

раскрыть ветку (15)
13
Автор поста оценил этот комментарий

Всегда есть о чём холиварить.
Конкретно тут, о том, что "не Unix-way".
Кучу разнофункциональных утилит заменили одной комплексной неделимой системой.

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

раскрыть ветку (12)
5
Автор поста оценил этот комментарий
"не Unix-way"
Да и хуй с ним. Напридумали догматов, как фанатики. Линус насчёт всех этих священных принципов хорошо выразился однажды.
раскрыть ветку (4)
2
Автор поста оценил этот комментарий

>Линус насчёт всех этих священных принципов хорошо выразился однажды.

А можно привести цитату? Интересно же.

раскрыть ветку (3)
5
Автор поста оценил этот комментарий

Цитату привести не смогу, смысл был такой, что "дрочить на красивые теории и концепции - тупо, нужно делать работающие, эффективные решения". То есть, инженерный подход, а не академический.

раскрыть ветку (2)
3
Автор поста оценил этот комментарий

Это поэтому он отказался принимать какие-либо патчи от Сиверса? :)

1
Автор поста оценил этот комментарий

Спасибо.

Иногда можно наблюдать даже не академический, а религиозный подход )))

3
DELETED
Автор поста оценил этот комментарий

Конкретно тут, о том, что "не Unix-way".

Linux (ядро) тоже не Unix-way.

А вот ядро в OS X (Mach) - это Unix-way.

Неожиданно?


а в потере гибкости.

В какой потере?

1
Автор поста оценил этот комментарий
одной комплексной неделимой системой

Один из мифов http://0pointer.de/blog/projects/the-biggest-myths.html


в потере гибкости. Пользователя лишили выбора

Аналогично.

раскрыть ветку (5)
4
Автор поста оценил этот комментарий
Один из мифов

чистейшая правда. Когда уже сраный гном без системд нельзя загрузить - это и есть "комплексная неделимая система". Все больше и больше в рамках проекта появляется компонент, которые друг без друга жить не могут.

Попробуйте заюзать отдельно networkd, или hostnamed (это вообще пиздец), или любое_другое_d.

раскрыть ветку (3)
1
Автор поста оценил этот комментарий
Когда уже сраный гном без системд нельзя загрузить - это и есть "комплексная неделимая система".

systemd - не неделимая система, независимо от вашего недовольства сторонними продуктами, которые его используют частично или полностью.


Попробуйте заюзать отдельно networkd, или hostnamed (это вообще пиздец), или любое_другое_d.

В смысле заюзать? Это программы, которые были написаны для работы с systemd, они не обязательны для работы systemd, и многим из них не обязательно наличие systemd.


Так что в чём проблема? Вот код этого самого hostnamed(https://cgit.freedesktop.org/systemd/systemd/tree/src/hostna...), покажите на строчку, которая запрещает программе работать без systemd.


API открыто, стабильно, документация есть, бери и пользуйся тем, что тебе нравится, меняй или убирай то, что тебе не нравится, многие так и делают.


https://gitweb.gentoo.org/proj/openrc-settingsd.git/

https://launchpad.net/ubuntu/yakkety/+source/ubuntu-system-s...

https://github.com/gentoo/eudev

https://github.com/wingo/elogind

и прочие, менее известные.


В общем: https://www.freedesktop.org/wiki/Software/systemd/InterfaceS... и https://www.freedesktop.org/wiki/Software/systemd/InterfaceP...


systemd безусловно комплексный, но абсолютно не неделимый. Из неделимого там только сам systemd с udevd и journald, да и то, было бы желание.

раскрыть ветку (2)
3
Автор поста оценил этот комментарий
покажите на строчку, которая запрещает программе работать без systemd

103


Остальное, извините, но это жонглирование словами в духе Леннарта, не более. Технологически - да, из него можно выбрасывать куски. На практике это огромный комбайн, который везде идет неделимым куском.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

>103


А вы попробуйте.


>Остальное, извините, но это жонглирование словами в духе Леннарта, не более. Технологически - да, из него можно выбрасывать куски. На практике это огромный комбайн, который везде идет неделимым куском.


Как угодно.

Автор поста оценил этот комментарий

интересная статья, спасибо за ссылку

4
Автор поста оценил этот комментарий
Холиварить можно о том, что например ночью надо спать(ну или дела делать), а не консоль дрочить, красноглазый. Сильно не бейте, я не хейтер.
раскрыть ветку (1)
DELETED
Автор поста оценил этот комментарий

Я разработчик ПО под линукс, это для меня работа.

А по вечерам я отдыхаю ;)

Вы смотрите срез комментариев. Чтобы написать комментарий, перейдите к общему списку