Ivan Shapovalov, Like-all, Pavlo Rudyi
systemd In Action, volume 2
В этой части мы сосредоточимся на администрировании системы под управлением systemd.Для начала краткий повтор и углубление в материал предыдущей серии.
I. “Repetition needs a friend…” (c) Whitechapel
systemd – это универсальный plumbing layer, или набор служебных программ для совершенно разных задач. Основным компонентом этого проекта является одноимённая система инициализации, построенная на основе концепции юнитов. Каждый юнит описывает какой-либо объект в системе (например, программу/демон, устройство или точку монтирования) и характеризуется текущим состоянием и списком зависимостей. На основании этой информации строится дерево зависимостей (ну, естественно, не дерево, а направленный ациклический граф, но суть та же), в котором для активации каждого юнита требуется активировать все его зависимости.Также существуют юниты-цели, активация которых ничего не означает сама по себе: такие юниты используются для группировки других. Этот механизм можно назвать обобщением концепции уровней запуска из sysvinit.
Основная команда оценки состояния системы и управления юнитами — systemctl
.
Подкоманда | Описание |
---|---|
list-units (--failed ) | (по умолчанию) cписок юнитов (--failed : показывать только сбойные юниты) |
status (без аргументов) | информация о состоянии системы и список всех процессов в виде дерева по контрольным группам |
list-sockets | список сокетов |
list-timers | cписок таймеров |
daemon-reload | перечитать список юнитов |
daemon-reexec | перезапустить сам systemd (с сохранением состояния) |
show | полный список свойств юнита (машиночитаемый) |
cat | эффективный текст юнит-файла, включая все дополнения |
list-dependencies | список зависимостей юнита |
start | запуск сервиса |
stop | остановка сервиса |
status (с аргументами) | статус сервиса |
kill | принудительная остановка всех процессов, принадлежащих юниту |
reload | перезагрузка конфигурации сервиса (если это понятие к нему применимо) |
isolate | изолировать юнит (т. е. остановить все юниты, кроме указанного и его зависимостей) |
enable | “добавить в автозагрузку” (выполнить действия в [Install] -секции юнита) |
disable | “убрать из автозагрузки” (выполнить обратные действия) |
mask | запретить запуск юнита любым способом |
status
имеет два варианта (с аргументами или без них). В первом случае выводится состояние указанных юнитов, а во втором — общая информация о состоянии системы и дерево процессов.Процессы, соответствующие каждому юниту, помещаются в отдельную контрольную группу (cgroup), что значительно упрощает контроль за процессами в системе. На основе этого становится возможным отслеживать и ограничивать потребление ресурсов отдельными юнитами (а точнее, их процессами). Для этого применяются существующие механизмы в ядре Linux.
Команда, отображающая иерархию контрольных групп или её произвольной части — systemd-cgls
.
Команда, показывающая потребление ресурсов по контрольным группам — systemd-cgtop
.
Юниты хранятся в виде файлов с ini-подобным синтаксисом и располагаются в трёх базовых директориях, перечисленных здесь в порядке возрастания приоритета:Директория | Описание |
---|---|
/usr/lib/systemd/system | системные юниты |
/run/systemd/system | временные юниты |
/etc/systemd/system | изменения, внесённые администратором |
systemctl mask
) — это переопределение юнита симлинком на /dev/null
. (Из этого следует, что замаскировать юнит, находящийся в /etc
, нельзя.)Впрочем, юнит-файлы можно дополнять, и не прибегая к их прямому редактированию. Для любого юнит-файла (например,
foo.service
) в любой из вышеперечисленных директорий могут быть созданы три поддиректории:foo.service.d
foo.service.wants
foo.service.requires
.conf
. Они считываются вслед за юнитом в алфавитном порядке и обрабатываются так, как будто “подклеены” в конец юнит-файла. Секции объединяются. При этом правила приоритета продолжают действовать: .conf
-файлы с одинаковым именем перекрывают друг друга.Во второй и третьей должны находиться символьные ссылки на другие юнит-файлы. Юниты по этим ссылкам добавляются к
Wants=
и Requires=
-зависимостям рассматриваемого юнита.К слову, именно таким способом обрабатываются директивы
WantedBy=
в [Install]
-секции. Например, пусть наш юнит foo.service
содержит [Install]
-секцию следующего вида:[Install]
WantedBy=multi-user.target
Тогда после выполнения команды systemctl enable foo.service
будет создана следующая символьная ссылка (предположим, что foo.service
лежит в /etc
):/etc/systemd/system/multi-user.target.wants/foo.service -> /etc/systemd/system/foo.service
Ещё есть юниты-шаблоны. Если существует юнит foo@.service
(знак @ в конце имени), то при обращении к foo@bar.service
будет использоваться юнит foo@.service
, а вхождения спецификаторов %i
и аналогичных в его тексте будут заменены на строку bar
. Да, в некоторых директивах подстановки запрещены — список спецификаторов и ограничения проще всего посмотреть в мане.Теперь рассмотрим различные вспомогательные утилиты, которые systemd привносит в наш
$PATH
. Почти все они начинаются с префикса systemd-
. Набираем этот префикс, нажимаем Tab и видим полный список. Итак,II. “And if you seek vengeance, all you need are instruments of pain.” (c) Dethklok
Для начала (чтобы сразу от них отделаться), systemd-escape
и systemd-path
.
Про них можно сказать достаточно мало. В systemd есть собственный механизм кодирования произвольных строк в имена файлов. Он применяется в двух местах. Во-первых, имя mount-юнита должно соответствовать пути до точки монтирования (а имя device-юнита — пути до узла устройства в /dev
или /sys
). Для того, чтобы внедрить в имя юнита произвольный путь со слешами, и применяется эта схема. Например:Исходная строка | Результирующая строка | Пояснение |
---|---|---|
/ | - | слеши заменяются на дефисы |
/mnt/foo | mnt-foo | первый слеш пропускается, если кроме него в строке ещё что-то есть |
/dev/disk/by-label/bar | dev-disk-by\x2dlabel-bar | символы со специальными значениями передаются с помощью C-подобных escape-последовательностей |
Итак, утилита
systemd-escape
преобразует строки в описанный формат и обратно. Параметр --path
включает описанную выше обработку первого слеша.systemctl start $(systemd-escape --path /mnt/foo).mount
systemctl start foo@$(systemd-escape "string with 'very' (different) characters").service
Зачем нужна утилита systemd-path
в практическом смысле — трудно предположить. Она отображает разные пути из тех, что описаны в file-hierarchy(7), своеобразном обновлённом “аналоге FHS” от разработчиков systemd.Наверное, предлагается писать
$(systemd-path search-binaries)
вместо $PATH
. Или, например, $(systemd-path user-documents)
вместо разбора XDG-шного ~/.config/user-dirs.dirs
(а вот это уже удобно).systemd-run
— выполнение произвольных программ под управлением systemd.
Эта команда создаёт временный юнит в /run/systemd
, указывает ему в ExecStart=
переданную в параметрах команду, опционально дописывает некоторые другие свойства и тут же запускает. Юзкейсов потенциально бесконечное количество.systemd-run --service-type oneshot /bin/echo "this will be run under systemd"
systemd-run --nice 20 -p CPUQuota=200% /bin/resource-hungry-daemon
Конечно, если юнит для демона уже есть, лучше будет запускать именно его, а свойства типа CPUQuota=
устанавливать через systemctl set-property
.Кстати, systemd имеет пользовательский режим работы. Каждый пользователь, залогиненный хотя бы один раз, получает собственный экземпляр systemd, для управления которым не требуются права root (но и запускается он, естественно, от имени пользователя). Соответственно, команды
systemd-run
, systemctl
и прочие имеют параметр --user
с очевидным значением.systemd-run --user /bin/echo "this will be run under systemd user instance"
systemctl --user list-units
С вспомогательными утилитами на этом всё. Рассмотрим теперь команды, относящихся к анализу конфигурации. Помимо systemctl status
и systemctl --failed
, уже упоминавшихся вначале, существуют ещё две.systemd-delta
— посмотреть список дополнений и переопределений юнитов.
Эта команда отображает сводную табличку всех изменений, внесённых в “системные” юниты (те, что находятся в /usr/lib
). Возможны варианты: EXTENDED
(расширен с помощью файла в .d
-директории), OVERRIDDEN
(замещён файлом с тем же названием), MASKED
(симлинк на /dev/null
), REDIRECTED
(симлинк на что-то другое) или EQUIVALENT
(симлинк на то же самое).Есть также параметры
--type
(фильтр по вышеописанным вариантам) и --diff
(показывать дифф между файлами для OVERRIDDEN
-записей).systemd-analyze
— разного рода статистика.
Подкоманда | Описание |
---|---|
time | (по умолчанию) показывает сообщение о времени, затраченном на каждый из этапов запуска системы: прошивка, загрузчик, ядро, initramfs и основная цель (default.target ) |
blame | выводит список юнитов, запуск которых занял наибольшее время (отсортированный по убыванию этого времени) |
critical-chain [ЦЕЛЬ] | выводит цепочку юнитов, которую пришлось ждать дольше всего (проблемные юниты подсвечены красным и указано время ожидания их запуска) |
plot | генерирует bootchart-подобную SVG-диаграмму, позволяющую наглядно оценить порядок запуска юнитов и затраченное на каждый из них время |
dot [ЮНИТЫ...] | генерирует граф зависимостей между юнитами в формате dot |
verify | проверяет указанный юнит-файл на корректность |
III. “The dissecting begins in the chest” (c) The Faceless
Как нетрудно заметить, в systemd очень активно применяется клиент-серверная архитектура с шиной D-Bus в роли универсального транспорта. Практически каждый компонент (за исключением, наверное,systemd-networkd
) имеет свой собственный шинный интерфейс — и отдельную ctl-утилиту в качестве адаптера к этому интерфейсу. Три настроечных утилиты, которые мы сейчас рассмотрим, исключением не являются.К слову, эта клиент-серверная модель часто вызывает недоумение у тех, кто пытается ознакомиться с systemd: “Как, и для управления хостнеймом свой демон?” Так вот, не всё то висит в памяти, что зовётся демоном. Каждый из этих демонов запускается только при получении по шине какого-либо запроса и автоматически завершается через некоторое (весьма малое) время после его обработки. Преимущества такого подхода перед “обычным”, когда все действия выполняются непосредственно утилитой командной строки, очевидны:
- проще писать альтернативные UI (например, настройка того же хостнейма в “панели управления” DE)
- есть возможность более тонкой настройки привилегий, чем с помощью SUID-бита на утилите
- проще отследить/перехватить появление сообщения на шине, чем вызов бинарника
-H
, который позволяет выполнить операцию удалённо, подключившись к указанной машине по SSH.Настройка системных часов, таймзоны и NTP-сервера: timedatectl
Запуск этой утилиты без параметров приводит к отображению “сводки о текущем положении дел”. Под положением дел понимается время (локальное, UTC и то, которое хранится в аппаратных часах), активная таймзона, состояние NTP-сервера, состояние DST и флаг, описывающий, что хранится в аппаратных часах (локальное время или UTC). Local time: Пн 2014-12-15 11:13:17 MSK
Universal time: Пн 2014-12-15 08:13:17 UTC
RTC time: Пн 2014-12-15 08:13:17
Time zone: Europe/Moscow (MSK, +0300)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: n/a
Следует отметить, что, начиная с версии 216, systemd-timedated
управляет только “комплектным” NTP-клиентом (systemd-timesyncd
). Предполагается, что основные юзкейсы его функциональность покрывает, а если вам всё же её не хватило и ввиду этого вы сознательно установили другой NTP-сервер/клиент, то вы уже знаете, как им управлять.Впрочем, на строку
NTP synchronized
описанное ограничение не распространяется: состояние синхронизации времени берётся из ядра и может быть установлено любым NTP-клиентом.Подкоманда | Описание |
---|---|
status | (по умолчанию) показывает вышеописанную сводку |
set-time | устанавливает локальное время (ожидается аргумент в формате ГГГГ-ММ-ДД ЧЧ:ММ:СС ) |
set-timezone | устанавливает таймзону (ожидается аргумент в формате Europe/Moscow ; список таймзон можно получить подкомандой list-timezones ) |
list-timezones | выводит список допустимых таймзон |
set-local-rtc | включает или отключает хранение локального времени в аппаратных часах (true — локальное время, false — UTC) |
set-ntp | включает или отключает “комплектный” NTP-клиент systemd-timesyncd |
Настройка имени хоста и описания системы: hostnamectl
Запуск без параметров — опять же, вывод достаточно информативного статусного сообщения. В него входит имя хоста, несколько описательных полей вроде физического расположения системы, UUID системы и текущей загрузки, имя дистрибутива, версия ядра и так далее. Static hostname: intelfx-laptop
Icon name: computer-laptop
Chassis: laptop
Deployment: development
Location: road to nowhere
Machine ID: 2ec6cf64aaa5446b99b67d87f1557c41
Boot ID: 07fbc3ae2b3a4e0a91b7e8465ae4774d
Operating System: Arch Linux
Kernel: Linux 3.18.0-pf0-intelfx-00204-g2766b40
Architecture: x86-64
Поля “Icon name”, “Chassis”, “Deployment” и “Location” сугубо пассивны: это строки, которые можно установить и узнать по запросу (хранятся они в /etc/machine-info
). “Machine ID” и “Boot ID” — это, соответственно, UUID системы (хранится в /etc/machine-id
) и UUID текущей загрузки. Наконец, “Operating System” считывается из /usr/lib/os-release
.Два вышеуказанных UUID используются, например, в
systemd-journald
: первый — при сборе логов с нескольких машин, а по второму можно фильтровать.Подкоманда | Описание |
---|---|
status | (по умолчанию) показывает вышеописанную сводку |
set-hostname | устанавливает имя хоста: --static — основное, которое хранится в /etc/hostname , --transient — получаемое по сети, --pretty — подробное и человекочитаемое |
set-icon-name | устанавливает поле “Icon name” (допустимы корректные названия пиктограмм согласно Icon Naming Specification) |
set-chassis | устанавливает поле “Chassis” (допустимы значения из фиксированного списка) |
set-deployment | устанавливает поле “Deployment” (допустимы значения из фиксированного списка) |
set-location | устанавливает поле “Location” (допустимы произвольные строки) |
Настройка локали и раскладки клавиатуры: localectl
При запуске утилиты без параметров мы получаем текущие значения системной локали, взятые из /etc/locale.conf
, а также текущие настройки клавиатуры для подсистемы VT ядра Linux и для X11. System Locale: LANG=ru_RU.UTF-8
LC_MESSAGES=en_US.UTF-8
VC Keymap: ruwin_cplk-UTF-8
X11 Layout: us,ru
X11 Variant: ,winkeys
X11 Options: grp:caps_toggle
Здесь всё довольно очевидно. Отметим только, что установка одной из раскладок (для X11 или консоли) автоматически устанавливает другую. Это поведение можно отключить, указав параметр --no-convert
.Подкоманда | Описание |
---|---|
status | (по умолчанию) показывает вышеописанную сводку |
set-locale | устанавливает системную локаль (ожидаются один или несколько аргументов в формате locale(7), т. е. LANG=ru_RU.UTF-8 ) |
list-locales | выводит список доступных локалей |
set-keymap | устанавливает раскладку клавиатуры для подсистемы VT (т. е. в консоли) |
list-keymaps | выводит список доступных раскладок клавиатуры для подсистемы VT |
set-x11-keymap | устанавливает раскладку и опции клавиатуры для X11 (ожидается от одного до четырёх параметров в формате <раскладка> <модель> <варианты> <опции> ) |
list-x11-keymap-models | выводит список доступных “моделей” клавиатуры для X11 |
list-x11-keymap-layouts | выводит список доступных “раскладок” клавиатуры для X11 |
list-x11-keymap-variants | выводит список доступных “вариантов” раскладок клавиатуры для X11 (опционально допускается указание раскладки, для которой нужно вывести список вариантов) |
list-x11-keymap-options | выводит список доступных “опций” клавиатуры для X11 |
/etc/locale.conf
, подсистемы VT — при помощи записи значений в /etc/vconsole.conf
(т. е. предполагается использование systemd-vconsole-setup
), а настройка X11 — при помощи создания файла /etc/X11/xorg.conf.d/00-keyboard.conf
с нужными настройками. Из этого следует, что после задания настроек с помощью localectl
требуется перезапустить соответствующие компоненты системы.Первичная настройка системы: systemd-firstboot
Эта утилита, в отличие от трёх предыдущих, не имеет соответствующего настроечного демона и вносит все изменения напрямую. Это связано с тем, что systemd-firstboot
предназначен для использования при установке ОС (для этого предусмотрен параметр --root
) или при первом её запуске.С помощью этой утилиты можно задать системную локаль, таймзону, имя хоста, UUID системы и пароль суперпользователя, причём одним из нескольких способов:
- установить в неинтерактивном режиме, передав утилите соответствующий параметр (
--locale
,--locale-messages
,--timezone
,--hostname
,--machine-id
,--root-password
или--root-password-file
) - сгенерировать (
--setup-machine-id
) - скопировать из основной системы (параметры
--copy-locale
,--copy-timezone
,--copy-root-password
или--copy
как синоним комбинации всех вышеперечисленных) - спросить у пользователя (
--prompt-locale
,--prompt-timezone
,--prompt-hostname
,--prompt-root-password
или--prompt
как синоним комбинации всех вышеперечисленных)
IV. “Let’s drink more… shell shall we?” (c) Unexpect
Все эти программы объединяет следующее: они выполняют то, ради чего до systemd во время загрузки использовались различного рода шелл-скрипты. Показательно то, что типов действий не так и много, и после ознакомления с нижеприведённым списком утилит использование вместо них командного интерпретатора общего назначения (т. е. шелла) действительно начинает выглядеть оверкиллом.Итак,
systemd-tmpfiles
— выполнение произвольных операций с файлами и директориями
Конфигурация этого компонента — набор последовательно считываемых и обрабатываемых .conf
-файлов в трёх директориях, имеющих друг над другом приоритет по уже известному принципу. Директории таковы: /usr/lib/tmpfiles.d
, /run/tmpfiles.d
и /etc/tmpfiles.d
.Сами файлы представляют собой список действий, по одному на строчку. Формат записи действий можно прочесть в
tmpfiles.d(5)
, и на нём мы останавливаться не будем.systemd-modules-load
— загрузка модулей ядра
Здесь всё предельно аналогично. Конфигурационные файлы systemd-modules-load
располагаются в трёх директориях (/usr/lib/modules-load.d
, /run/modules-load.d
и /etc/modules-load.d
) и содержат имена модулей, предназначенных к загрузке — опять же, по одному на строчку.Стоит отметить, что эти директории не имеют ничего общего с
modprobe.d(5)
и не заменяют их. В modprobe.d
перечисляются опции по умолчанию и “чёрный список” автозагрузки, а modules-load.d
— это список модулей, которые нужно загрузить принудительно.systemd-sysusers
— добавление системных пользователей и групп
Данный компонент используется для создания отсутствующих системных учётных записей и групп, вплоть до регенерации /etc/passwd
, /etc/group
и /etc/shadow
в случае их отсутствия. Основной юзкейс здесь – это запуск системы с пустым /etc
, или (в более общем случае) с пустой корневой ФС, когда /usr
с мастер-образом монтируется из внешнего источника (вполне вероятно, что в read-only), а остальное пересоздаётся при первом запуске. Впрочем, такая автоматизация может быть полезной и в других случаях — например, для того, чтобы обеспечить обновление системы без ручного слияния списков пользователей и групп (как это иногда приходилось делать, например, в Arch Linux).Конфигурируется
systemd-sysusers
аналогично двум вышеописанным компонентам: с помощью .conf
-файлов в директориях /usr/lib/sysusers.d
, /run/sysusers.d
и /etc/sysusers.d
.systemd-binfmt
— регистрация дополнительных форматов исполняемых файлов
В отдельную утилиту это вынесли, надо полагать, для удобства: функциональность systemd-binfmt
полностью реализуется с помощью tmpfiles.d
-директив, по очереди записывающих нужные строчки в псевдофайл /proc/sys/fs/binfmt_misc/register
. Тем не менее, список binfmt-правил теперь можно записывать в .conf
-файлы — в директориях, как нетрудно догадаться, /usr/lib/binfmt.d
, /run/binfmt.d
и /etc/binfmt.d
.Используется такая возможность, например, с Wine: правило
:DOSWin:M::MZ::/usr/bin/wine:
заставит ядро запускать MZ-исполняемые файлы (*.exe
) с помощью Wine. Это правило и приведено в качестве примера в binfmt.d(5)
.systemd-vconsole-setup
— настройка подсистемы VT ядра Linux
Наконец, последний компонент. Он конфигурируется в /etc/vconsole.conf
и занимается тем, что настраивает при загрузке ядерную консоль Linux: в частности, шрифт (FONT=
, FONT_MAP=
и FONT_UNIMAP=
) и раскладку клавиатуры (KEYMAP=
и KEYMAP_TOGGLE=
).К слову, команда
localectl set-keymap
изменяет именно два последних параметра.Примечание: оставлять и смотреть комментарии лучше на основном сайте.
Part 1 • Part 3 • Part 4
Комментариев нет:
Отправить комментарий