Последнее изменение файла: 2024.10.04
Скопировано с www.bog.pp.ru: 2024.11.21
Bog BOS: Загрузка Linux
В статье описывается процесс загрузки Linux (x86, GRUB, SysV init):
последовательность выполнения, настройка загрузчиков и /etc/inittab, systemctl.
- инициализация контроллера RAM
- декомпрессия BIOS из флеш в RAM
- защита от записи захваченного куска и передача туда управления
- POST (Power On Self Test) - процедура идентификации, тестирования и конфигурации оборудования
- процедура IPL - Initial Program Load (по мотивам BBS, PnP BIOS, PCI Local Bus, PXE Specification)
- BIOS отображает все найденные Option ROM на системную память
- BIOS включает в таблицу IPL (до 16 записей)
встроенные устройства загрузки (BAID - BIOS Aware IPL Device, не имеют своей Option ROM, код хранится на системной плате) и инициализирует их как умеет
- дополнительные устройства имеют в устройстве или на системной плате Option ROM (например, PCI Expansion ROM),
которые должны иметь стандартный формат заголовка (сигнатура 55AAh) с заголовком расширения "$PnP"
(один Option ROM может иметь несколько заголовков расширения, каждый имеет контрольную сумму), который позволяет отнести устройства
к BEV (Bootstrap Entry Vector - смещение программы загрузки, например, контроллер Ethernet)
или BCV (Boot Connection Vector - смещение программы подключения, например, контроллер RAID;
может захватывать прерывания 9h (ввод), 10h (вывод) и 13h (диск));
также содержит идентификатор устройства, имя изготовителя, название продукта
(серийного номера не предусмотрено, поэтому в меню загрузки будет 8 одинаковых названий моделей диска),
тип устройства, подтип устройства, флажки (это устройство ввода, это устройство вывода, включить в IPL, прочее)
- BIOS поочерёдно передаёт управление на вектор инициализации внутри заголовка
(переход, сегментная адресация - 16-bit Real Mode или 16-bit Protected Mode (16:16),
совместимый с адаптированными вызовами в 32-bit Protected Mode (16:32), совместимость с 0:32 Protected Mode (flat) не предполагалась)
каждого Option ROM (сначала видео, ввод и IPL);
инициализация не должна перехватывать прерывания 9h, 10h и 13h;
возвращает флажки: может обслуживать прерывания 9h (ввод), 10h (вывод) и 13h (диск), устройство готово к обслуживанию;
по ходу дела инициализируются требуемые шины и мосты;
программа инициализации BCV после включения устройства ищет подключённые устройства и для каждого добавляет заголовок BCV в памяти
и добавляет свой первый диск в список IPL
- BIOS просматривает все Option ROM (в памяти) и ведёт таблицу BCV контроллеров с приоритетами BCV,
передаёт управление на сегментный адрес программы подключения (перехватывает прерывания 9h, 10h или 13h)
- BIOS просматривает все Option ROM (в памяти) и определяет потенциальные загрузочные устройства из BEV и составляет таблицу IPL:
тип устройства, флажки (индекс последней загрузки в таблице, активное устройство, была ошибка, носитель готов),
сегментный адрес программы загрузки, строка описания ASCIIZ - имя продукта
- приоритет загрузки определяется оператором при настройке BIOS и хранится в NVRAM (по умолчанию, сначала BAID, затем BEV устройства)
- BIOS перебирает в соответствии с приоритетами загрузочные устройства из таблицы IPL и пытается с них загрузиться
(передаёт управление на сегментный адрес программы загрузки);
при неудаче программа загрузки должна выдать INT 18h (когда-то тут был BASIC)
- программе загрузки передаётся номер загрузочного устройства (80h для первого НЖМД)
- программа загрузки действует в зависимости от типа устройства:
- блочное устройство: загрузка загрузочного сектора (512 байт) в память по адресу 0000:7C00h и передача ему управления;
если загрузка с жёсткого диска, то загрузочный сектор лежит в MBR (Master Boot Record)
- CD-ROM: см. описание спецификации El Torito
- сетевой контроллер (BEV): PXE
- первоначальный загрузчик находит и загружает программу загрузки 2 этапа
(stage 2) и передаёт ей управление (GRUB, LILO, SYSLINUX);
используется BIOS API; обычное место загрузчика 2 этапа - /boot/
- загрузчик 2 этапа выбирает, находит и загружает ядро и RAM диск (initrd)
в память;
GRUB читает конфигурацию из /boot/grub/grub.conf;
конфигурация для LILO хранится в MBR;
GRUB и LILO позволяют вывести список возможных загружаемых систем
на экран и выбрать нужную с помощью клавиатуры;
GRUB позволяет изменить параметры загрузки (корневая файловая система,
ядро, RAM диск, параметры ядра) с помощью текстового редактора;
используется BIOS API;
RAM диск содержит образ файловой системы с модулями (драйверами)
устройств, необходимыми для монтирования корневой файловой системы;
в случае со встроенным Linux RAM диск содержит всю систему
- ядро повторно обходит и инициализирует периферийные устройства,
для которых есть встроенные драйвера
- ядро монтирует RAM диск (предварительно разжав) и загружает
с него необходимые модули,
инициализирует соответствующие устройства
- если необходимо, то ядро инициализирует LVM и программный RAID
- ядро размонтирует RAM диск и освобождает занимаемую им память
- ядро монтирует корневую файловую систему в режиме "только чтение";
в процессе дальнейшей работы ядро загружает дополнительные модули
с корневой файловой системы
- запускается процесс /sbin/init (далее описывается загрузка в стиле
System V)
- init разбирает конфигурационный файл /etc/inittab
для определения дальнейших действий;
если при загрузке указан уровень s (или S), то inittab не читается,
а система переходит в однопользовательский режим (shell на
/dev/console с правами root);
строка с действием initdefault определяет
"уровень выполнения" (run level) по умолчанию, т.е. режим работы системы
(однопользовательская, многопользовательская, с доступом в сеть,
с графическим окружением и т.д.);
строка с действием sysinit (/etc/rc.d/rc.sysinit) определяет
скрипт инициализации;
- init выполняет скрипт /etc/rc.d/rc.sysinit (проверка и монтирование
остальных файловых систем, swap и т.д.)
- в "нормальном" /etc/inittab при переходе на любой уровень запускается
скрипт /etc/rc.d/rc с указанием уровня в качестве параметра;
данный скрипт запускает скрипты /etc/rcуровень.d/K*
(в алфавитном порядке) с параметром stop и скрипты
/etc/rcуровень.d/S* с параметром start;
в конце запускается /etc/rc.d/rc.local;
по традиции скрипты являются символьными ссылками
на скрипты в директории /etc/init.d/;
вместо /etc/init.d/ может использоваться /etc/rc.d/init.d/;
вместо /etc/rcуровень.d/ может использоваться /etc/rc.d/rcуровень.d;
реальность несколько сложнее
- инициализация платформы UEFI
- менеджер загрузки UEFI выбирает драйверы и приложения из списка
- загрузка ядра и RAM диска с помощью GRUB 2;
RAM диск содержит образ файловой системы с модулями (драйверами)
устройств, необходимыми для монтирования корневой файловой системы;
в случае со встроенным Linux RAM диск содержит всю систему
- ядро повторно обходит и инициализирует периферийные устройства, для которых есть встроенные драйвера
- ядро монтирует RAM диск (предварительно разжав) и загружает с него необходимые модули,
инициализирует соответствующие устройства - dracut
- ядро размонтирует RAM диск и освобождает занимаемую им память
- ядро монтирует корневую файловую систему в режиме "только чтение";
в процессе дальнейшей работы ядро загружает дополнительные модули с корневой файловой системы
- запускается процесс /usr/lib/systemd/systemd
В различных дистрибутивах и различных ситуациях могут использоваться
следующие загрузчики:
LILO и GRUB работают через BIOS,
а большинство BIOS позволяют доступ только
к первым двум IDE-дискам (считая ATAPI CD-ROM) в пределах первых 1023 цилиндров.
Так что каталог (или раздел) /boot, в котором хранятся как файлы самого
загрузчика, так и загружаемые файлы (ядро, initrd) должен удовлетворять
данным ограничениям.
Формат файла /etc/inittab
(комментарии начинаются с символа '#'):
идентификатор:перечень-уровней-выполнения:действие:процесс
где
- идентификатор - уникальная последовательность от 1 до 4 символов
(в старых версиях до 2); для getty и ему подобных идентификатор
д.б. номером линии tty
- перечень-уровней-выполнения - перечисление (без пробела) уровней
выполнения, для которых выполняется указанное действие
(от 0 до 6 и от A до C, s, S); для sysinit, boot и bootwait
игнорируется; при смене уровня всем процессам, не специфицированным
для этого уровня, посылается сигнал SIGTERM, а через 5 секунд (интервал
задаётся при вызове telinit -t) сигнал SIGKILL
(init предполагает, что процесс не сменил группу процессов, в которой
он его запустил);
пустой список означает "для всех"
- действие (по-моему, тут перемешаны условия и действия)
- respawn (процесс по завершении запускается вновь и вновь;
после 10 перезапусков за 2 минуты делается пауза 5 минут)
- wait (процесс запускается один раз при переходе на уровень,
init ждёт его завершения)
- once (процесс запускается один раз при переходе на уровень)
- boot (процесс запускается при загрузке системы)
- bootwait (процесс запускается при загрузке системы,
init ждёт его завершения)
- off (ничего не делать)
- ondemand (процесс запускается при вызове данного уровня
выполнения (от A до C), но смены уровня не происходит)
- initdefault (на какой уровень выполнения переходить после загрузки;
если не указан, то будет спрашивать на консоли)
- sysinit (процесс запускается при загрузке до boot и bootwait)
- powerwait (вызывается при пропадании питания, например, программой
слежения за UPS,
SIGPWR (подробности в /etc/powerstatus: FAIL),
init ждёт его завершения)
- powerfail (вызывается при пропадании питания, например, программой
слежения за UPS,
SIGPWR (подробности в /etc/powerstatus: FAIL),
init не ждёт его завершения)
- powerokwait (вызывается при возобновлении питания,
SIGPWR (подробности в /etc/powerstatus: OK),
init ждёт его завершения)
- powerfailnow (вызывается непосредственно перед исчерпанием
аккумуляторов UPS, SIGPWR (подробности в /etc/powerstatus: LOW))
- ctrlaltdel (вызывается при получении сигнала SIGINT от ядра)
- kbrequest (ядро посылает SIGWINCH при нажатии определённой
комбинации клавиш)
- процесс - имя файла ('+' перед символом отменяет запись utmp и wtmp),
программа или скрипт
При запуске процесса устанавливаются переменные окружения:
PATH, INIT_VERSION, RUNLEVEL, PREVLEVEL, CONSOLE.
Уровни выполнения для Red Hat Linux:
- 0: halt (неинтереактивный уровень)
- 1: single user (одна виртуальная консоль)
- 2: multiuser (6 виртуальных консолей)
- 3: multiuser + NFS (6 виртуальных консолей)
- 4: не используется
- 5: X11 (6 виртуальных консолей и xdm, gdm или kdm
в зависимости от /etc/X11/prefdm)
- 6: reboot (неинтереактивный уровень)
Переход на другой уровень можно сделать с помощью
программы telinit или прямо через /dev/initctl.
telinit с указанием уровня q (Q) заставляет init
перечитать /etc/inittab. Использование SIGPWR и /etc/powerstatus признано
устаревшим.
Загрузчик может передать процессу init параметры
- -s, S, single (загрузка в однопользовательском режиме)
- от 1 до 5 (явное задание уровня выполнения)
- -b, emergency (однопользовательский режим без выполнения sysinit)
- -a, auto (устанавливается переменная AUTOBOOT)
systemd (LGPL) - управление системой и сервисами.
RHEL/CentOS 7.9 - версия 219. RHEL/RockyLinux 8.10 - версия 239.
Запускается как PID 1 вместо процесса init (initd, SysV init), UpStart, OpenRC, runit, dinitq.
Для совместимости поддерживает скрипты инициализации LSB (/etc/init.d).
Управляет запуском модулей (unit) и отслеживает зависимость между модулями (юнитами).
Предполагается, что в будущем заменит собой все системные сервисы Linux.
Уже имеются замены следующим сервисам:
- сервис журналов (systemd-journal вместо syslog)
- управление сеансами пользователей (systemd-logind вместо ConsoleKit)
- временем и сетевым временем (timedated и systemd-timesyncd вместо ntpd/chronyd)
- именем хоста, /etc/hostname (вместо hostname)
- именами DNS (systemd-resolved вместо библиотеки resolv и /etc/resolv.conf)
- локалью systemd-localed, /etc/locale.conf вместо ?
- загрузка модулей, /etc/modules-load.d/*.conf
- параметры ядра, /etc/sysctl.d/*.conf
- контейнерами и виртуальными машинами (systemd-nspawn, machinectl, systemd-machined.service, portablectl, systemd-portabled)
- разделами и файловыми системами - systemd-repart, systemd-growfs, systemd-growfs@.service, x-systemd.growfs в /etc/fstab,
systemd-makefs@.service, systemd-makeswap@.service, x-systemd.makefs в /etc/fstab
- учётными записями (systemd-sysusers для системных пользователей, systemd-homed для обычных),
JSON User, JSON Group (7 секций, более 100 полей, LDAP слишком сложен говорили они...);
строгий режим задаёт шаблон имён пользователей и групп "^[a-zA-Z_][a-zA-Z0-9_-]{0,30}$"; общий режим - "^[a-z][a-z0-9-]{0,30}$";
0 - root, 65534 - nobody (nfsnobody), 65535 (нельзя использовать), 4294967295 (нельзя использовать);
граница между системными и обычными пользователями: 1000 (UID_MIN/GID_MIN в /etc/login.defs; ранее 500, ещё ранее 100);
предопределённые пользователи и группы в /usr/lib/sysusers.d/basic.conf;
systemd-homed (homectl) определяет перемещаемые домашние каталоги, содержащие описание пользователя в ~/.identity (JSON, подписанные)
- настройками системы
- сетевыми интерфейсами (systemd-networkd, networkctl, /lib/systemd/network/ вместо network-scripts и nmcli)
- монтированием (systemd-mount и systemd-umount вместо /etc/fstab и mount, .mount) и монтированием по требованию, .automount (вместо automount)
- замена chroot
- консоль, /etc/vconsole.conf
- управление загрузкой - systemd-boot: bootctl, systemd-boot-check-no-failures.service - ни одного сбойного сервиса при загрузке,
systemd-bless-boot.service и boot-complete.target, systemd-bless-boot-generator(8) - управление счётчиком перезагрузок (по умолчанию /etc/kernel/tries);
kernel-install добавляет файл для генерации строки меню имя[+число_попыток].conf в /boot/loader/entries/;
механизм позволяет откатиться к загрузке предыдущего ядра при установке плохого нового;
systemd-firstboot;
интерфейс с загрузчиком через EFI переменные с UUID поставщика 4a67b082-0a4c-41cf-b6c7-440b29bb8c4f: LoaderDevicePartUUID, LoaderEntries,
LoaderEntryDefault, LoaderEntrySelected и др.
- systemd-tmpfiles, /etc/tmpfiles.d/*.conf
- systemd-udevd
- юниты .timer (замена cron)
- исполняемые двоичные форматы, /etc/binfmt.d/*.conf
- /etc/os-release (описание дистрибутива))
- /etc/machine-id (UUID)
- pam_systemd
- nss-systemd
- управление питанием systemd-ac-power
- управление секретами (credentials) - вместо привычной передачи через переменные окружения, параметры программы и т.д.;
получаются от гипервизора, менеджера контейнеров, EFI переменных, параметров ядра, initrd;
возможна дешифровка с использованием TPM2 или /var/lib/systemd/credential.secret;
хранятся в файлах в памяти (ramfs), CREDENTIALS_DIRECTORY, недоступны другим сервисам (отдельное пространство имён файловой системы);
настройка сервисов: LoadCredential, ImportCredential, SetCredential, LoadCredentialEncrypted, SetCredentialEncrypted, ConditionCredential, AssertCredential;
systemd-creds
Кстати, Gnome 3.8 и выше не работает без systemd (используется для управления сессиями).
Использует D-Bus и Unix-сокеты для общения между процессами.
Состояния юнитов: активный, неактивный, упавший.
systemd контролирует состояние юнитов и реагирует на их изменение, перезапускает юнит при аварийном завершении, собирает сообщения.
Позволяет активировать сервисы по зависимостям, обращению к портам и сокетам (замена inetd, xinetd.service), обращению D-Bus,
по расписанию (замена cron), по активации обрудования (udev), обращению к файлу или каталогу.
Зависимости (положительные Requires и отрицательные Conflicts) отделены от требований к порядку загрузки (After и Before),
т.е. можно задать порядок, но не требовать активизации упомянутых юнитов (не будут запущены, если не затребовано в другом месте),
и наоборот (будут запущены параллельно).
Сервисы наследуют окружение процесса 1, а не от оболочки, в которой запускается скрипт service.
Юниты могут запросить изменение состояний других юнитов, такие запросы называются заданиями (job) и ставятся в очередь заданий.
Осуществляется проверка добавляемых в очередь заданий на зацикливание зависимостей с попыткой автоматического удаления желаемых (Wants), но не обязательных зависимостей.
systemd аналогично inetd слушает требуемые сервисами сокеты (сетевые порты) используя специальные юниты (.socket) для их создания
и передаёт соединение очередному процессу юнита, возможно вместе со слушающим сокетом,
это также позволяет не терять сообщения при перезапуске сервисов - сообщения встают в очередь к незакрываемому на время перезапуска сокету.
Сервисы, зависимые от базовых сервисов (точнее от интерфейсных сокетов), могут быть запущены без ожидания завершения запуска базового сервиса.
Для ожидания монтирования файловой системы или доступа к конкретному файл используется механизм autofs (.mount, .automount и .path).
При запуске головного процесса юнита помещает его в отдельную контрольную группу (cgroup), в которую попадают все его потомки,
что позволяет аккуратно завершить все процессы юнита (в прошлой жизни использовались setsid, установление лидера группы процессов и т.д.),
а также контролировать потребление ресурсов всем сервисом. Иерарахия cgroup в /sys/fs/cgroup/systemd/.
При монтировании указывается (иерархия без контроллеров):
"-t cgroup -o none,name=systemd,release_agent=/usr/lib/systemd/systemd-cgroups-agent] cgroup /sys/fs/cgroup/systemd".
Лимиты в /etc/security/limits.conf действуют на сеансы через PAM, но не на сервисы systemd.
В cgroups v1 (до systemd 232, RHEL7) для каждого контроллера (cpu, memory, blkio) создаётся отдельная иерархия.
В cgroups v2 (после systemd 232, в RHEL8 не используется?) общая иерархия для контроллеров ? и отдельная cgroup v1 для device, memory, pids.
Посмотреть имена групп можно командой "ps xawf -eo pid,user,cgroup:80,args" или systemd-cgls, которые выводят дерево процессов.
Обещана, но не гарантирована стабильность формата юнитов, документированные ключи systemd, systemctl, loginctl, journalctl и т.п..
Типы юнитов (имя юнита определяется именем файла с его описанием):
- сервисы (.service), systemd.service(5) - запускает и управляет набором процессов, изолируемых средствами cgroups
- работа с сокетами AF_INET, AF_INET6 и AF_UNIX (.socket), systemd.socket(5) и daemon(7) - первоначально сокет слушает сам systemd,
а соответствующий сервис запускается при первом обращении, после чего ему передаётся сокет
- подключение блочного или сетевого устройства (.device) с использованием systemd-udevd, systemd.device(5)
- точка монтирования (.mount), systemd.mount(5), могут динамически создаваться из /etc/fstab
- точка монтирования по запросу (.automount, systemd.automount(5)) имеет соответствующий юнит .mount, systemd.automount(5)
- цель, режим работы (.target), systemd.target(5) - группа сервисов (аналог уровня initd), используется для синхронизации загрузки
- раздел подкачки (.swap), systemd.swap(5)
- запуск других юнитов по расписанию (.timer), systemd.timer(5)
- управление иерархией файловой системы (.path), сервис запускается при изменении или первом обращении, systemd.path(5)
- внутренний (transient, не имеет файла с описанием) юнит .scope создаётся при запуске сервиса и сессии, systemd.scope(5), в него можно поместить внешние процессы;
например, пользовательские процессы помещаются в session-номер.scope (задачи cron в systemd:/user.slice/user-идентификатор.slice/session-номер.scope)
- контейнер cgroups (.slice), systemd.slice(5), в который входят юниты .service, .scope и .slice; корневая группа - "-.slice",
в которую входят user.slice (в нём создаются user-идентификатор.slice, в который входят session-номер_сессии.scope и user@идентификатор.service,
который можно настраивать с помощью юнит-файлов или "systemctl set-property"),
system.slice, machine.slice и init.scope; процесы в .slice не входят
- внутренний юнит .snapshot создаётся автоматически при выполнении "systemctl snapshot" и содержит текущий статус юнитов;
можно откатить командой "systemctl isolate"
- юнит контейнера .nspawn
Цели (.target, режим работы; цель по умолчанию задаётся командой "systemctl set-default ..."
или при загрузке ключом ядра systemd.default=, systemd.unit=):
Файлы настройки в /etc/systemd/ (администраторские, наибольший приоритет), /run/systemd/ (временные),
/usr/lib/systemd/ (дистрибутивные, наименьший приоритет).
Основные настройки systemd в system.conf в этих каталогах.
Описание юнитов в подкаталогах system/ (общесистемные) и user/ (пользовательские, управление сеансами пользователей).
В дополнение к описанию юнита в файле имя.тип можно использовать каталог имя.тип.d/, в который поместить отличия от менее приоритетного описания
(с указанием секций, новые значения переменных замещают значения из менее приоритетных источников).
Сервисы systemd:
- systemd - процесс 1
- systemd-journald - журнализация
- systemd-networkd - управление сетью
- systemd-logind - управление доступом пользователей
- systemd-udevd - управление устройствами
Получить больше информации в журнал можно указав ключи ядра при загрузке:
systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M printk.devkmsg=on, debug, rd.debug (смотреть: journalctl -ab).
Для запуска отладочной оболочки (tty9, CTRL+ALT+F9) надо использовать ключ ядра systemd.debug_shell=1.
Подсистема systemd.generator позволяет преобразовать на ходу
посторонние файлы настройки в юниты при загрузке и перечтении (reload) настройки systemd.
Генераторы ищутся в /run/systemd/system-generators/, /etc/systemd/system-generators/,
/usr/local/lib/systemd/system-generators/, /usr/lib/systemd/system-generators/,
/run/systemd/user-generators/, /etc/systemd/user-generators/, /usr/local/lib/systemd/user-generators/ и /usr/lib/systemd/user-generators/.
Генераторы запускаются в самом начале загрузки до syslog, systemd и монтирования дополнительных файловых систем.
Получившийся юнит можно посмотреть в каталогах /run/systemd/generator{.early,,.late} и $XDG_RUNTIME_DIR/generator{early,,late}
или с помощью "systemctl show имя-скрипта|имя-файловой-системы".
Описание юнита в "родном" формате имеет приоритет над результатом работы генератора.
Генераторы:
- systemd-sysv-generator: скрипты LSB (LSB headers)
преобразуются на ходу в юниты с учётом ключей Required-Start из управляющих комментариев LSB, например:
тип forking, "After=remote-fs.target basic.target network-online.target sysinit.target systemd-journald.socket system.slice",
"Before=multi-user.target graphical.target shutdown.target";
сохранён интерфейс /dev/initctl для работы старых программ (shutdown, poweroff) через сервис транслирующий старые команды в обращение через D-Bus
(systemd-initctl.socket, systemd-initctl.socket(8), systemd-initctl.service, systemd-initctl.service(8));
управляющие комментарии "# chkconfig :" определяют зависимости runlevelУровень.target (устанавливается WantedBy);
управляющие комментарии "# config:" преобразуются в EnvironmentFile;
управляющие комментарии "# pidfile:" преобразуются в PIDFile;
управляющие комментарии "# description:" преобразуются в Description;
управляющие комментарии в скрипте LSB размещаются между строками "### BEGIN INIT INFO" и "### END INIT INFO";
настройки обычных юнитов (в /usr/lib/systemd/system/ и /etc/systemd/system/) имеют приоритет;
время выполнения скриптов LSB ограничено 5 минутами; скрипты не могут читать с stdin (интерактивные запросы);
runlevel и chkconfig работают не совсем так как раньше; нестандартные команды не обслуживаются;
параметры стандартных команд не обслуживаются; сервисы запускаются в очищенном контексте;
restart обслуживается systemd как stop и start; неработающий сервис не останавливается;
выполнение скриптов не должно зависеть от уровня (/sbin/runlevel, /sbin/chkconfig ненадёжны);
ключи управляющих комментариев:
- Provides: имя-сервиса
- Required-Start: имена-сервисов-через-пробел # преобразуются в After и Wants; специальные имена:
- $network преобразуется в "After=network-online.target" и "Wants=network-online.target"
- $local_fs
- $remote_fs преобразуется в "After=remote-fs.target"
- $named преобразуется в After=nss-lookup.target
- $portmap преобразуется в After=rpcbind.target
- $syslog
- $time
- Required-Stop: имена-сервисов-через-пробел # преобразуются в Conflicts; специальные имена: $network $local_fs $remote_fs $named $portmap $syslog $time
- Default-Start: уровни-через-пробел # на каких уровнях запускать сервис по умолчанию
- Default-Stop: уровни-через-пробел # на каких уровнях останавливать сервис по умолчанию
- Short-Description: краткое описание
- Description: описание
- systemd-fstab-generator: /etc/fstab преобразуются на ходу в юниты типа .mount (посмотреть: systemctl cat имя.mount);
только один юнит на файловую систему; все юниты запускаются одновременно, а зависимости строятся автоматически;
если монтирование неудачно и нет ключа nofail, то загрузка останавливается;
автоматически монтируются следующие файловые системы (без настройки в /etc/fstab, но можно настройку туда добавить (systemd-remount-fs.service);
монтирование обеспечивается с помощью юнитов (можно замаскировать): dev-hugepages.mount, dev-mqueue.mount, proc-fs-nfsd.mount, proc-sys-fs-binfmt_misc.mount,
sys-fs-fuse-connections.mount, sys-kernel-config.mount, sys-kernel-debug.mount, tmp.mount, var-lib-nfs-rpc_pipefs.mount):
т.к. генератор запускается в самом начале, то сетевые имена в /etc/fstab не допустимы;
- x-systemd.automount - преобразование в юнит типа .automount в дополнение к .mount;
поиск: "grep auto /proc/mounts"; отсутствует автоматическое размонтирование
- nfs-server-generator
- rpc-pipefs-generator
- selinux-autorelabel-generator.sh
- systemd-cryptsetup-generator
- systemd-debug-generator
- kdump-dep-generator.sh
- lvm2-activation-generator
- systemd-getty-generator: разбирает окружение и console=, использует шаблоны getty@.service, serial-getty@.service,
console-getty.service (/dev/console для контейнера), container-getty@.service для выдачи "login:",
getty запускается только на тех виртуальных консолях, на которые было переключение;
количество виртуальных консолей задаётся параметром NAutoVTs в logind.conf;
tty1 используется для дисплейного менеджера;
параметр ReserveVT в logind.conf определяет резервируемую для текстового сеанса консоль (tty6)
- systemd-gpt-auto-generator
- systemd-hibernate-resume-generator
- systemd-rc-local-generator - проверяет наличие /etc/rc.local (/etc/rc.d/rc.local) и права на выполнение (chmod u+x /etc/rc.d/rc.local),
в этом случае подключает rc-local.service (/usr/lib/systemd/system/rc-local.service) в режим multi-user.target после
network.target (network-online.target в RHEL8);
невозможно обеспечить запуск rc.local "последним";
также проверяет наличие /usr/sbin/halt.local и права на выполнение, включает halt-local.service в процесс выключения
- systemd-system-update-generator
- systemd-veritysetup-generator
- systemd-bless-boot-generator - определяет наличие управления количеством неудачных перезагрузок и активирует systemd-bless-boot.service,
который после boot-complete.target (systemd-boot-check-no-failures.service и graphical-session-good.service)
с учётом успешности текущей загрузки переименовывает файлы .conf в /boot/loader/entries/
- zfs-mount-generator
Сохранена совместимость с utmp/wtmp - systemd-update-utmp.service, ystemd-update-utmp-runlevel.service
(systemd-update-utmp.service(8), systemd-update-utmp-runlevel.service(8), systemd-update-utmp(8)).
Кроме инициализации (init.scope) и управления системой (system.slice) systemd используется для управления сессиями пользователей (user.slice)
Утилиты:
- systemctl - утилита управления
- systemd-analyze:
- blame - сортировка юнитов по затраченному на запуск времени
- plot - дерево запуска юнитов с указанием затраченного на запуск времени (в формате SVG)
- critical-chain [имя-юнита] - критический путь загрузки
- dump - полный отчёт о загрузке
- dot - сериализация запусков юнитов (в формате GraphViz dot: dot -Tsvg; долго; открыл только gwenview);
граф зависимостей целей: "systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target'"
- set-log-level notice - трассировка загрузки
- systemd-delta [--type={masked|equivalent|redirected|overridden|extended|unchanged}] [--diff=no]
- показывает разницу между настройками systemd в дистрибутиве и текущими
- systemd-cgls [имя-cgroup] - выводит дерево процессов в соответствии с иерархией cgroups
- systemd-cgtop - аналог top для групп процессов в соответствии с иерархией cgroups
- machinectl - управление виртуальными машинами и контейнерами, совместимыми с systemd (systemd-machined.service)
- systemd-detect-virt - опеделяет на настоящем ли компьютере мы работаем или нет: виртуальная машина, контейнер, chroot,
пространство имён пользователя (--private-users); определяется тип только внутренней матрёшки
- systemd-nspawn - простой менеджер контейнеров; аналог chroot, но дополнительно создаёт отдельное пространство имён файловых систем (FSNS), номеров процессов (PID NS),
автоматически монтирует /proc и /sys и, возможно, приватную сеть; systemd внутри systemd-nspawn "не делает резких движений" типа reboot()
- systemd-socket-proxyd {хост:порт | путь-к-сокету} --connections-max=256 # перенаправляет траффик от прослушиваемого локально сокета
(IPv4, IPv6, UNIX) к локальному или удалённому сокету;
прокси наследует сокет от systemd (юнит .socket), открывает соединение с обслуживаемым сервером и передаёт данные в обе стороны
- loginctl
- hostnamectl
- timedatectl
- localectl
- busctl
- systemd-run - создать временный юнит (.service, .scope, .path, .socket, .timer) и выполнить команду в его окружении
systemctl - основная управляющая утилита systemd. Файл настройки - /etc/systemd/system.conf.
Параметры system.conf:
- DefaultTimeoutStartSec=90 - лимит ожидания запуска юнита
- RuntimeWatchdogSec - интервал аппаратного таймера
- ShutdownWatchdogSec=600 - интервал аппаратного таймера выключения
- DefaultIPAccounting - учитывать IP траффик для всех
- DefaultController
Общие ключи:
- -H|--hostname [имя-пользователя@]имя-сервера # удалённое управление производится через ssh
(зачем это? почему нельзя просто использовать ssh? задел для замены в будущем ssh?)
- -M имя-контейнера # обратиться к systemd внутри указанного контейнера или виртуальной машины
- -r # рекурсивно обратиться ко всем systemd во всех контейнерах и виртуальных машинах
Вывести документацию по юниту: systemctl help имя-юнита.
Получить список {активных | всех | несгенерированных} юнитов: systemctl [--all] [--type тип-юнита]
[--state={active|failed}] {list-units|list-unit-files} [режим-работы].
Повторное чтение описаний юнитов: systemctl daemon-reload. Необходимо, например, при добавлении сервиса.
Перезапуск systemd: systemctl daemon-rexec.
Управление работой сервисов: systemctl {start|stop|reload|reload-or-restart|reload-or-try-restar|restart|try-restart} имя-юнита.
При запуске сервиса все конфликтующие сервисы (и их зависимые?) останавливаются без запроса и извещения.
Узнать состояние юнита: systemctl {is-active|is-enabled|status [-n число-сообщений|-f]} имя-юнита.
Послать сигнал всем процессам сервиса: systemctl kill [-s имя-сигнала] [--kill-who=main] имя-юнита.
Управление запуском сервисов при загрузке, обращению к сокету и т.п.: systemctl {disable|enable|reenable|preset} имя-юнита.
Маскировка сервиса (сервис останавливается, ручной и автоматический запуск блокируется): systemctl {mask|unmak} имя-юнита (делается ссылка
/etc/systemd/system/имя-юнита на /dev/null и "systemctl daemon-reload").
Управление режимом работы (аналог уровня в inittab): systemctl set-default {graphical.target|multi-user.target|rescue.target}.
Ключ ядра systemd.unit=имя-режима при загрузке.
Узнать режим работы по умолчанию: systemctl get-default.
Какие сервисы запускаются в указанном режиме: systemctl show --no-pager -p "Wants" имя-режима
(systemctl list-dependencies имя-юнита).
Зависимости юнитов: systemctl list-dependencies [{--before|--after} имя-юнита].
Узнать состояние текущих целей (режимов работы): systemctl list-units --type=target.
Выбрать режим работы прямо сейчас: systemctl isolate {graphical.target|multi-user.target|rescue.target}.
Посмотреть содержимое файла с описанием юнита: systemctl cat имя-юнита.
Посмотреть свойства юнита: systemctl show имя-юнита (229 штук в версии 239!).
Изменение свойств юнитов: systemctl set-property имя-юнита имя-свойства=значение.
Состояние системы (дерево системных сервисов и их процессов, а также пользовательских сеансов): systemctl status.
Перезагрузка: systemctl [--no-wall] {reboot|poweroff|halt|suspend|hibernate|hybrid-sleep|rescue|emergency} [--firmware-setup].
7 Ctrl-Alt-Del в течении 2 секунд - немедленная перезагрузка.
Создание снимка текущего состояния юнитов и откатка к снимку: systemctl {snapshot|isolate}.
Показать юниты, которые не удалось запустить: systemctl --failed.
Сброс ошибок: systemctl reset-failed.
Зависшие задачи: systemctl list-jobs.
Вывести список виртуальных машин и контейнеров, совестимых с systemd; указывается состояние и число ошибок: systemctl list-machines.
Ключи /usr/lib/systemd/systemd:
- --test --system --unit=имя.target # default.target; тестирование загрузки (не делать под root-ом!), 36 тысяч строк
- --dump-configuration-items # вывести список параметров настройки юнитов (960 в версии 239)
- --crash-shell # ключ загрузки ядра - systemd.crash_shell; запустить оболочку при падении
- --crash-vt # ключ загрузки ядра - systemd.crash_vt; на какую виртуальную консоль переключиться при падении; от 1 до 63
- --crash-reboot # ключ загрузки ядра - systemd.crash_reboot; перезагрузиться при падении
- --confirm-spawn # запрашивать подтверждение при порождении процессов
- --show-status={auto|on|off} # ключ загрузки ядра - systemd.show_status; показывать состояние запускаемых сервисов при загрузке;
auto - начать показывать после первого сбоя или задержки
- --log-target={console|journal|kmsg|journal-or-kmsg|null}
- --log-level={emerg|alert|crit|err|warning|notice|info|debug}
- --log-color=true
- --default-standard-output={journal|inherit|null|tty|journal|journal+console|syslog|syslog+console|kmsg|kmsg+console}
- --default-standard-error={inherit|journal|null|tty|journal|journal+console|syslog|syslog+console|kmsg|kmsg+console}
- --machine-id
- --service-watchdogs=enabled # включить или отключить сторожевые таймеры всех сервисов; ключ загрузки ядра - systemd.service_watchdogs
Юнит имеет имя, зависимости, описание требуемых ресурсов и прочее.
Описание юнита содержится в файлах подкаталогов system/ каталогов настройки systemd:
/etc/systemd/{system,user}/ (локальные), /run/systemd/{system,user}/ (временные), /usr/lib/systemd/{system,user}/ (дистрибутивные).
Имя и тип юнита определяются именем файла с описанием.
Дополнения к настройкам могут быть помещены в каталог имя-юнита.тип.d в файлах с суффиксом .conf.
Дополнительно в каталогах имя-юнита.тип.wants и имя-юнита.тип.requires могут
быть символьные ссылки на описания юнитов, которые желательно или требуется активировать.
Формат был выбран похожим на формат .ini файлов MS Windows, текстовый файл делится на секции, имя секции на отдельной строке в квадратных скобках,
имя параметра и значение разделены символом "=" на отдельной строке. Несколько значений разделяются пробелами.
Сервисы могут присутствовать в нескольких экземлярах - имя-сервиса@идентификатор-экземпляра.service,
например, getty@tty1.service. В этом случае systemd сначала пытается найти описание сервиса с таким именем,
а при неудаче отбрасывает идентификатор-экземпляра и использует найденный файл как шаблон описания юнита.
Макросы в описании юнитов:
- %i и %I заменяются на идентификатор-экземпляра (экранированную - \xAB - и неэкранированную версию соответственно)
- %n заменяется на полное имя юнита (%N - неэкранированная версия)
- %p - на имя-сервиса (строка до @)
- %H - на имя хоста на момент запуска
- %t - на имя каталога исполнения (/run для системных юнитов)
- %M - идентификатор образа ОС (rocky)
- %A - версия образ ОС ()
Секция Unit описывает юнит, параметры:
- Description - описание юнита
- Documentation - где взять документацию по сервису (например, man:sshd(8))
- After - после каких юнитов запускать, запуск этих юнитов не инициализируется и не требуется
- Before - до каких юнитов запускать, запуск этих юнитов не инициализируется и не требуется
- Want - какие юниты желательно запускать до данного; After/Before необходимо указать всё равно
- Requires - указанные юниты обязательно запустить до данного; After/Before необходимо указать всё равно
- Conflicts - указанные юниты обязательно остановить до запуска данного юнита
- ConditionVirtualization - [!]yes (запускать только [не] в виртуальном окружении), no, vm, kvm и т.д.
- JoinsNamespaceOf -
Секция Service описывает поведение юнита сервиса:
- Type - тип запуска юнита
- simple - сервис состоит из основного процесса, который сразу считается готовым; по умолчанию
- forking - сервис запускает дочерний процесс и завершает родительский, после чего служба считается запущенной, порождённый процесс считается основным
- oneshot - запущенный процесс завершается
- dbus - сервис считается готовым при регистрации указанного в BusName имени в D-Bus, процесс не порождает дочерний и не завершается
- notify - сервис состоит из основного процесса, который извещает systemd о готовности
- idle - сервис состоит из основного процесса, который запускается при простое системы
- ExecStart - имя программы или скрипта, исполняемого при запуске сервиса, с параметрами (можно использовать переменные окружения);
символ "-" перед именем означает игнорировать код возврата;
символ "!" перед именем означает запуск от root невзирая на использование User
- ExecStartPre - имя программы или скрипта, исполняемого перед ExecStart (например, подготовки окружения chroot)
- ExecStartPost - имя программы или скрипта, исполняемого после ExecStart
- ExecStop - имя файла, исполняемого при останове сервиса, с параметрами (можно использовать переменные окружения)
- ExecReload - имя файла, исполняемого при повторной инициализации, с параметрами (можно использовать переменные окружения)
- Restart - условие автоматического перезапуска: on-failure - при аварийном завершении сервиса
- RestartSec - время ожидание до перезапуска
- RemainAfterExit - сервис считается активным даже после завершения всех процессов
- BusName - имя, например, com.redhat.abrt
- EnvironmentFile - откуда брать значения переменных окружения (/etc/sysconfig/...)
- WorkingDirectory - какой каталог сделать текущим
- PIDFile - где хранить номер процесса
- KillMode - как завершить процесс: process - основной процесс, control-group (по умолчанию) - всех
- KillSignal - 15 (SIGTERM)
- StandardInput - откуда брать stdin; можно socket
- StandardOutput - куда направить stdout; можно syslog или socket
- StandardError - куда направить stderr; можно syslog
- SyslogIdentifier
- SyslogFacility
- StartLimitBurst - лимит попыток перезапуска
- StartLimitInterval - интервал времени для подсчёта попыток перезапуска
- StartLimitAction - действие при превышении лимита перезапусков: none - оставить неработающей, reboot,
reboot-force (всех убить, всё размонтировать), reboot-immediate (не убивать и не размонтировать)
- OnFailure - юнит, который надо запустить при аварийном завершении данного юнита
- OnFailureIsolat - режим (target), в который надо перейти при аварийном завершении данного юнита
- User - сервис будет работать от указанного пользователя
- Group - сервис будет работать от указанной группы
- DynamicUser - yes: при запуске сервиса на лету создаётся временный пользователь (из диапазона 61184–65519),
при остановке сервиса пользователь удаляется; используется nss-systemd (/etc/nsswitch.conf) вместо /etc/passwd
- ограничения на доступ к файлам
- RootDirectory - куда делать chroot перед ExecStart, который задаётся относительно каталога chroot
- RootDirectoryStartOnly - делать chroot только перед ExecStart
- PrivateTmp - процессы сервиса получат свой /tmp и /var/tmp (используется filesystem namespaces;
в /tmp создаётся каталог "systemd-private-UUID-имя_службы-случайная_строка с правами root:root 700, а в нём подкаталог tmp/
с правами 777+t)
- ReadOnlyDirectories - процессы сервсиса смогут только читать из указанных каталогов (используется filesystem namespaces)
- InaccessibleDirectories - процессам сервиса указанные каталоги будут недоступны (используется filesystem namespaces)
- ProtectSystem - strict: запрет создавать файлы кроме как в /proc, /sys, /tmp, /var/tmp, /dev
- RuntimeDirectory - указанный подкаталог создаётся в /run, принадлежит пользователю сервиса, удаляется при остановке сервиса
- StateDirectory - указанный подкаталог создаётся в /var/lib, принадлежит пользователю сервиса, не удаляется при остановке сервиса
- LogsDirectory - указанный подкаталог создаётся в /var/log, принадлежит пользователю сервиса, не удаляется при остановке сервиса
- CacheDirectory - указанный подкаталог создаётся в /var/cache, принадлежит пользователю сервиса, не удаляется при остановке сервиса
- ProtectHome - read-only
- DeviceAllow - список допустимых устройств и права доступа к ним
- ограничения на сеть и сокеты
- PrivateNetwork - процессы сервиса будут видеть только интерфейс lo, причём свой собственный (используется network namespaces)
- RemoveIPC - удалять все объекты межпроцессного взаимодействия после остановки сервиса
- RestrictAddressFamilies - список допустимых семейств адресов сокетов (AF_INET AF_INET6 AF_UNIX AF_PACKET)
- RestrictNamespaces - список допустимых пространств имён: yes ipc net
- IPAccounting - yes: включить учёт трафика (используется eBPF); результат по "systemctl status имя-сервиса",
по "systemctl show имя-сервиса -p IPIngressBytes -p IPIngressPackets -p IPEgressBytes -p IPEgressPackets"
или по завершению сервиса в journalctl в метаданных IP_METRIC_INGRESS_BYTES и т.п. последней записи сервиса (MESSAGE_ID=ae8f7b866b0347b9af31fe1c80b127c0);
не действует на AF_PACKET
- IPAddressDeny - чёрный список IP адресов или сетей или any (используется eBPF); сначала проверяется белый список; не действует на AF_PACKET
- IPAddressAllow - белый список IP адресов или сетей или any (используется eBPF); сначала проверяется белый список; не действует на AF_PACKET
- ограничение на использование ресурсов
- LimitNPROC - лимит количества запускаемых процессов (если нет привилегии CAP_SYS_RESOURCE)
- CPUShares (CPUWeight) - доля ЦП от 2 до 262144 (10000, 1024?)
- CPUQuota
- CPUSchedulingPolicy
- CPUSchedulingPriority
- CPUAffinity
- LimitCPU
- MemoryLimit (MemoryMax) - максимальное потребление памяти всеми процессами сервиса в байтах (K, M, G, T - по основанию 1024);
будет создана контрольная группа в иерархии контроллера memory (cgroup v1)
- MemorySoftLimit - максимальное потребление памяти всеми процессами сервиса в байтах, можно превышать, если есть свободная память (удалена)
- MemorySwapMax
- IOSchedulingClass - планировщик ввода/вывода: best-effort
- IOSchedulingPriority
- BlockIOWeight (IOWeight, IODeviceWeight) - доля полосы пропускания ввода-вывода от 10 до 1000 (10000),
перед долей можно уточнить имя блочного устройства или имя файла (блочное устройство будет определено автоматически);
будет создана контрольная группа в иерархии контроллера ioblk (cgroup v1)
- BlockIOReadBandwidth (IOReadBandwidthMax) - имя блочного устройства или имя файла (блочное устройство будет определено автоматически) и
предельную скорость чтения в байтах в секунду
- BlockIOWriteBandwidth (IOReadBandwidthMax) - аналогично для записи
- LimitFSIZE - суммарный лимит на процессы группы (если нет привилегии CAP_SYS_RESOURCE)
- ControlGroupAttribute - регулирование cgroup, не охваченных параметрами, задаётся имя атрибута и его значение
- CapabilityBoundingSet - набор полномочий для процессов сервиса (capabilities(7)); символ "~" запрещает указанные полномочия
- WatchdogSec - интервал программного сторожевого таймера (д.б. поддержка в программе)
- MemoryPressureWatch - переменные окружения MEMORY_PRESSURE_WATCH (при нехватке памяти файл получает событие) и MEMORY_PRESSURE_WRITE
Секция Socket описывает поведение юнита сокета:
- ListenStream - номер порта
- Accept - принимать ли входящее соединение (yes) или доверить сервису
Секция Install (обрабатывается командами enable и disable) описывает когда должен запуститься сервис:
- WantedBy - какие юниты слабо зависят от этого юнита (обычно для .target)
- RequiredBy - какие юниты сильно зависят от этого юнита
- Alias - синонимы имени юнита
- Also - какие юниты установить вместе с этим
- DefaultInstance - экземпляр по умолчанию для шаблона юнита
Пример своего сервиса (/usr/lib/systemd/system/имя-сервиса.service):
[Unit]
Description=Confluence
After=network.target nss-lookup.target
[Service]
Type=forking
WorkingDirectory=/home/confluence/atlassian-confluence-5.9.7
ExecStart=/home/confluence/atlassian-confluence-5.9.7/bin/start-confluence.sh
PIDFile=/home/confluence/atlassian-confluence-5.9.7/work/catalina.pid
ExecStop=/home/confluence/atlassian-confluence-5.9.7/bin/stop-confluence.sh
ExecReload=/home/confluence/atlassian-confluence-5.9.7/bin/stop-confluence.sh | sleep 60 | /home/confluence/atlassian-confluence-5.9.7/bin/start-confluence.sh
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=Confluence
SyslogFacility=daemon
IOSchedulingClass=best-effort
Restart=on-failure
[Install]
WantedBy=multi-user.target
Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru