мета-данные страницы
  •  

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
notes:howlinuxworks:vol6 [2026/05/14 15:13] radi0devnotes:howlinuxworks:vol6 [2026/05/14 16:59] (текущий) radi0dev
Строка 160: Строка 160:
 Полный список см. systemd.unit(5) Полный список см. systemd.unit(5)
  
-===== 6.3.4Процесс работы systemd =====+===== 6.3.4 Процесс работы systemd =====
  
 systemctl - основная команда для управления systemd юнитами. systemctl - основная команда для управления systemd юнитами.
Строка 221: Строка 221:
 **Примечание:** Задания (jobs) - это изменения состояния юнитов, не путать с заданиями оболочки. Требуются права суперпользователя для некоторых операций. **Примечание:** Задания (jobs) - это изменения состояния юнитов, не путать с заданиями оболочки. Требуются права суперпользователя для некоторых операций.
  
 +==== 6.3.5 Отслеживание и синхронизация процессов systemd ====
 +
 +systemd использует **cgroups** (группы управления ядра Linux) для отслеживания иерархии процессов. Параметр **Type** в юнит-файле указывает поведение службы при запуске.
 +
 +^ Type ^ Описание ^
 +| **simple** | Процесс не разветвляется, остается основным процессом |
 +| **forking** | Процесс разветвляется; systemd ждет завершения исходного процесса |
 +| **notify** | Служба отправляет уведомление systemd, когда готова |
 +| **dbus** | Служба регистрируется на D-Bus, когда готова |
 +| **oneshot** | Процесс полностью завершается после запуска; RemainAfterExit=yes по умолчанию |
 +| **idle** | Как simple, но запуск отложен до завершения всех активных заданий |
 +
 +**Примечание:** Type=simple не известен время запуска; используйте Type=notify, Type=dbus или отложенный запуск (раздел 6.3.7) для синхронизации зависимых юнитов.
 +
 +==== 6.3.6 Зависимости systemd ====
 +
 +Гибкая система зависимостей требует баланса между строгостью и отказоустойчивостью. Слишком строгие правила могут заблокировать доступ при сбое некритичного сервиса. systemd предлагает несколько типов зависимостей для гибкого управления:
 +
 +^ Тип ^ Описание ^
 +| **Requires** | Строгие зависимости. При сбое зависимости юнит также отключается. |
 +| **Wants** | Зависимости только для активации. Сбой зависимости не влияет на юнит. Рекомендуется использовать по возможности. |
 +| **Requisite** | Юниты, которые уже должны быть активны. Если не активны, юнит не запустится. |
 +| **Conflicts** | Отрицательные зависимости. При активации юнита противоположная зависимость деактивируется. |
 +
 +Просмотр зависимостей:
 +<code bash>
 +systemctl show -p type unit
 +</code>
 +
 +=== Порядок выполнения юнитов ===
 +
 +По умолчанию юниты с Requires и Wants запускаются одновременно. Для упорядочивания используйте:
 +
 +  * **Before** - текущий юнит активируется раньше перечисленных
 +  * **After** - текущий юнит активируется после перечисленных
 +
 +systemd ждет активного статуса юнита перед активацией зависимостей.
 +
 +=== Зависимости по умолчанию ===
 +
 +systemd автоматически добавляет зависимость After к Wants-зависимостям. Эти неявные зависимости вычисляются во время загрузки и не сохраняются в файлах конфигурации.
 +
 +Отключить зависимости по умолчанию:
 +<code bash>
 +DefaultDependencies=no
 +</code>
 +
 +=== Условные зависимости ===
 +
 +Для проверки состояния системы:
 +
 +  * **ConditionPathExists=p** - путь существует
 +  * **ConditionPathIsDirectory=p** - путь является каталогом
 +  * **ConditionFileNotEmpty=p** - файл существует и не пуст
 +
 +При ложном условии юнит не активируется, но другие зависимости активируются независимо от условия.
 +
 +=== Секция [Install] и включение юнитов ===
 +
 +Раздел [Install] позволяет указывать зависимости в обратном порядке без изменения дополнительных файлов. Используйте **WantedBy** или **RequiredBy**.
 +
 +Пример:
 +
 +**test1.target:**
 +<code bash>
 +[Unit]
 +Description=test 1
 +
 +[Install]
 +WantedBy=test2.target
 +</code>
 +
 +**test2.target:**
 +<code bash>
 +[Unit]
 +Description=test 2
 +</code>
 +
 +Включение юнита:
 +<code bash>
 +systemctl enable test1.target
 +# Создаст: /etc/systemd/system/test2.target.wants/test1.target
 +</code>
 +
 +Отключение юнита:
 +<code bash>
 +systemctl disable test1.target
 +</code>
 +
 +**Важно:** включение юнита не активирует его. Юнит с разделом [Install] считается отключенным по умолчанию и включается после перезагрузки.
 +
 +Каталоги .wants и .require в /etc/systemd/system обычно управляются разделом [Install], но можно добавлять символические ссылки вручную для временных зависимостей без редактирования системных файлов юнитов.
 +
 +==== 6.3.7 Запуск по запросу и параллелизация ресурсов в systemd ====
 +
 +systemd позволяет откладывать запуск юнита до момента, когда на него поступит запрос. Процесс:
 +
 +  1. Создается юнит systemd для сервиса (Unit A)
 +  2. Определяется ресурс (сокет, файл, устройство)
 +  3. Создается юнит ресурса (Unit R): .socket, .path или .device
 +  4. systemd мониторит ресурс и активирует Unit A при обращении
 +
 +При обращении к ресурсу:
 +  1. systemd блокирует ресурс и буферизует входные данные
 +  2. Активирует Unit A
 +  3. Unit A берет управление ресурсом и обрабатывает буферизованные данные
 +
 +**Важные замечания:**
 +  * Юнит ресурсов должен охватывать все точки доступа сервиса
 +  * Связь между юнитами может быть неявной (по имени) или явной (параметр Socket=)
 +  * Не все серверы поддерживают взаимодействие с юнитами ресурсов
 +
 +=== Пример: сокет-юнит и служебный юнит ===
 +
 +Echo-сервис на TCP-порту 22222.
 +
 +**echo.socket:**
 +<code bash>
 +[Unit]
 +Description=echo socket
 +
 +[Socket]
 +ListenStream=22222
 +Accept=true
 +</code>
 +
 +**echo@.service:**
 +<code bash>
 +[Unit]
 +Description=echo service
 +
 +[Service]
 +ExecStart=/bin/cat
 +StandardInput=socket
 +</code>
 +
 +Запуск:
 +<code bash>
 +systemctl start echo.socket
 +telnet localhost 22222
 +</code>
 +
 +Остановка:
 +<code bash>
 +systemctl stop echo.socket
 +</code>
 +
 +=== Экземпляры и передача управления ===
 +
 +Символ @ в имени echo@.service означает параллельные экземпляры. При **Accept=true** в сокет-юните systemd принимает входящие соединения и создает отдельный экземпляр для каждого. Каждый экземпляр считывает данные как стандартный ввод.
 +
 +Если сервис может самостоятельно принимать соединения, исключите @ из имени и не устанавливайте Accept=true. Сервис получит полный контроль над сокетом.
 +
 +Документация: systemd.socket(5), systemd.path(5), systemd.device(5), systemd.exec(5)
 +
 +=== Оптимизация загрузки с помощью юнитов ресурсов ===
 +
 +Юниты ресурсов ускоряют загрузку путем параллельной активации:
 +
 +^ Последовательный запуск ^ Параллельный запуск с юнитом ресурса ^
 +| Служба E (ресурс R) запускается | Юнит R активируется немедленно |
 +| Службы A, B, C ждут E | Службы A, B, C, E стартуют параллельно |
 +| Долгое время загрузки | Быстрая загрузка, E берет управление когда готова |
 +
 +systemd предоставляет интерфейс юнита ресурса (R) еще до полной активации служебного юнита (E). Это позволяет зависимым юнитам (A, B, C) стартовать параллельно, а не ждать E.
 +
 +**Побочный эффект:** Одновременный запуск многих юнитов может временно замедлить систему.
 +
 +**Пример:** journald и D-Bus обычно загружаются параллельно этим способом.
 +
 +==== 6.3.8 Вспомогательные компоненты systemd ====
 +
 +systemd включает поддержку задач управления системой, помимо запуска и управления сервисами. Исполняемые файлы расположены в /lib/systemd и имеют префикс **systemd-**.
 +
 +^ Служба ^ Назначение ^
 +| **udevd** | Управление устройствами (см. Глава 3) |
 +| **journald** | Служба логирования; обрабатывает различные механизмы, включая syslog (см. Глава 7) |
 +| **resolved** | Демон кэширования DNS (см. Глава 9) |
 +
 +**Примеры программ:**
 +  * systemd-udevd (интегрированный в systemd demон udevd)
 +  * systemd-fsck (простая обертка для стандартных системных утилит)
 +
 +Некоторые программы в /lib/systemd - обычные обертки, запускающие стандартные утилиты и уведомляющие systemd о результатах.
 +
 +**Справка:** Неизвестную программу в /lib/systemd можно найти в man-страницах, где описаны и утилита, и соответствующий ей тип юнита.
 +
 +===== 6.4. Уровни выполнения в System V =====
 +
 +System V init использует **уровни выполнения** (runlevel) для определения состояния машины - число от 0 до 6. Проверить текущий уровень:
 +
 +<code bash>
 +who -r
 +</code>
 +
 +Выход: ''run-level 5 2019-01-27 16:43''
 +
 +Уровни выполнения различают состояния: запуск, выключение, однопользовательский режим, консоль. Например, 2–4 - текстовая консоль, 5 - графический интерфейс.
 +
 +**Примечание:** systemd поддерживает уровни выполнения как устаревшие, предпочитая им целевые юниты.
 +
 +===== 6.5. System V init =====
 +
 +System V init - одна из старейших систем инициализации Linux. Устанавливается редко (встречается в RHEL < 7.0, встроенных системах), но пакеты могут содержать её сценарии, совместимые с systemd.
 +
 +Состоит из:
 +  * Конфигурационный файл: ''**/etc/inittab**''
 +  * Сценарии загрузки и символические ссылки
 +
 +^ Файл ^ Содержимое ^
 +| /etc/inittab | Четыре поля: идентификатор : уровни выполнения : действие : команда |
 +| /etc/rc.d/rc | Запускает программы из rc*.d в числовом порядке |
 +| /etc/rc*.d | Каталоги со сценариями (rc1.d, rc2.d и т.д.) |
 +
 +**Пример строки inittab:**
 +
 +<code>
 +id:5:initdefault:
 +l5:5:wait:/etc/rc.d/rc 5
 +</code>
 +
 +^ Действие ^ Назначение ^
 +| **initdefault** | Уровень выполнения по умолчанию |
 +| **wait** | Выполнить команду один раз при входе на уровень, ждать завершения |
 +| **respawn** | Перезапустить команду при выходе (например, getty для виртуальных консолей) |
 +| **ctrlaltdel** | Действие при нажатии Ctrl+Alt+Del (обычно shutdown) |
 +| **sysinit** | Первое действие при запуске, до всех уровней выполнения |
 +
 +==== 6.5.1. System V init: последовательность команд при запуске ====
 +
 +Команда ''rc 5'' запускает сценарии из ''/etc/rc5.d'':
 +
 +  * **S** (Start) - выполнить с аргументом ''start''
 +  * **K** (Kill) - выполнить с аргументом ''stop''
 +  * **Числа 00–99** - порядок выполнения
 +
 +**Пример каталога rc5.d:**
 +
 +<code>
 +S10sysklogd      S20ppp           S99gpm
 +S12kerneld       S25netstd_nfs    S99httpd
 +S15netstd_init   S30netstd_misc   S99rmnologin
 +</code>
 +
 +Команда rc выполняет их последовательно:
 +
 +<code bash>
 +S10sysklogd start
 +S12kerneld start
 +S15netstd_init start
 +...
 +S99sshd start
 +</code>
 +
 +Сценарии оболочки запускают программы из ''/sbin'' или ''/usr/sbin''. Для редактирования используйте ''less'' или аналогичные программы.
 +
 +==== 6.5.2. Ферма ссылок System V init ====
 +
 +Содержимое rc*.d - **символические ссылки** на файлы в ''/etc/init.d'':
 +
 +<code>
 +lrwxrwxrwx . . . S10sysklogd -> ../init.d/sysklogd
 +lrwxrwxrwx . . . S12kerneld -> ../init.d/kerneld
 +lrwxrwxrwx . . . S99httpd -> ../init.d/httpd
 +</code>
 +
 +Дистрибутивы используют эту **ферму ссылок (link farm)** для переиспользования одних сценариев на всех уровнях выполнения.
 +
 +=== Запуск и остановка служб ===
 +
 +<code bash>
 +/etc/init.d/httpd start    # Запустить
 +/etc/init.d/httpd stop     # Остановить
 +</code>
 +
 +=== Изменение последовательности загрузки ===
 +
 +**Отключить службу без удаления:**
 +
 +<code bash>
 +mv S99httpd _S99httpd
 +</code>
 +
 +Префикс ''_'' заставит rc игнорировать ссылку.
 +
 +**Добавить службу:** скопируйте сценарий в init.d, создайте символическую ссылку в rc*.d. Несущественные службы - номера 90+, после основных систем.
 +
 +==== 6.5.3. Команда run-parts ====
 +
 +Утилита **run-parts** запускает все исполняемые программы в каталоге в определённом порядке.
 +
 +^ Дистрибутив ^ Функции ^
 +| Fedora | Простая версия - запускает всё подряд |
 +| Debian/Ubuntu | Сложная - фильтр по регулярным выражениям, передача аргументов |
 +
 +Используется в сценариях для массового запуска программ. Большинству пользователей детали неважны.
 +
 +==== 6.5.4. Управление System V init ====
 +
 +**telinit** - команда управления уровнями выполнения:
 +
 +^ Команда ^ Действие ^
 +| ''telinit 3'' | Переключиться на уровень выполнения 3 |
 +| ''telinit q'' | Перечитать ''/etc/inittab'' |
 +| ''telinit s'' | Однопользовательский режим |
 +
 +**Предупреждение:** init завершит процессы, отсутствующие в inittab для нового уровня.
 +
 +==== 6.5.5. Совместимость systemd и System V ====
 +
 +systemd отслеживает System V сценарии:
 +
 +  1. Активирует ''<N>.target'' (N - уровень выполнения)
 +  2. Идентифицирует скрипты в ''/etc/rc<N>.d''
 +  3. Связывает скрипт со служебным юнитом (''foo.service'')
 +  4. Активирует юнит, запускает с аргументом start/stop
 +  5. Связывает процессы со служебным юнитом
 +
 +**Результат:** можно использовать ''systemctl'' для управления, но режим совместимости всё равно запускает сценарии **последовательно**.
 +
 +===== 6.6 Завершение работы системы =====
 +
 +Используйте **shutdown** для корректного завершения:
 +
 +<code bash>
 +shutdown -h now        # Остановить сейчас
 +shutdown -r +10        # Перезагрузить через 10 минут
 +</code>
 +
 +^ Параметр ^ Действие ^
 +| **-h** | Halt - остановка и отключение питания |
 +| **-r** | Reboot - перезагрузка |
 +| **now** | Немедленно |
 +| **+n** | Через n минут |
 +
 +**Перед завершением:** shutdown создаёт ''/etc/nologin'' (запрет входа), уведомляет пользователей.
 +
 +=== Процедура завершения ===
 +
 +  1. init просит каждый процесс завершиться
 +  2. Через время применяет сигнал TERM
 +  3. Если не помогает - KILL для оставшихся процессов
 +  4. Блокирует системные файлы
 +  5. Демонтирует все FS кроме корневой
 +  6. Ремонтирует корневую FS в режиме read-only
 +  7. Синхронизирует буфер (sync)
 +  8. Указывает ядру перезагрузиться/остановиться (reboot(2))
 +
 +**halt/reboot:** вызывают shutdown, или если система уже на уровне выключения - сигналят ядру напрямую. Флаг **-f** (force) - быстрое выключение без проверок.
 +
 +===== 6.7 Начальная файловая система оперативной памяти =====
 +
 +**initramfs** - временное пользовательское пространство перед основной загрузкой. Решает проблему: **ядру нужны драйверы в виде модулей, но модули - это файлы, а FS не смонтирована.**
 +
 +=== Как это работает ===
 +
 +  1. Загрузчик загружает архив с модулями ядра в оперативную память
 +  2. Ядро распаковывает архив во временную RAM-FS
 +  3. Утилиты в initramfs загружают необходимые драйверы
 +  4. Монтируют реальную корневую FS
 +  5. Запускают полноценный init
 +
 +^ Дистрибутив ^ Реализация ^
 +| Простые системы | Shell-скрипт, udev, монтирование корня |
 +| systemd системы | Полная systemd без модулей, minimal udev config |
 +
 +=== Отключение initramfs ===
 +
 +Если все драйверы встроены в ядро - можно пропустить initramfs. Удалите строку ''initrd'' в GRUB (лучше через редактор меню, чем файл конфига).
 +
 +**Примечание:** современные ядра требуют initramfs для UUID-монтирования и других функций.
 +
 +=== Содержимое initramfs ===
 +
 +Распакуйте архив:
 +
 +<code bash>
 +unmkinitramfs /boot/initramfs-*.img .
 +</code>
 +
 +Старые системы использовали **cpio** архивы (см. cpio(1)).
 +
 +=== Создание initramfs ===
 +
 +Обычно создаётся автоматически дистрибутивом. Основные утилиты:
 +  * **mkinitramfs** - простая, распространённая
 +  * **dracut** - более мощная
 +
 +**Примечание:** термин initrd (initial RAM disk) - устаревший, использовал образ диска. Сейчас initramfs (cpio-архив) стандарт. Файлы конфига ещё содержат имя initrd.
 +
 +===== 6.8 Аварийная загрузка системы и однопользовательский режим =====
 +
 +При проблемах с системой используйте **live-образ** дистрибутива или SystemRescueCD на съёмном носителе. Live-образ - полная Linux, загружающаяся без установки.
 +
 +=== Задачи после сбоя ===
 +
 +  * Проверка файловых систем
 +  * Сброс забытого пароля
 +  * Исправление критичных файлов (''/etc/fstab'', ''/etc/passwd'')
 +  * Восстановление резервных копий
 +
 +=== Однопользовательский режим ===
 +
 +**Быстрая загрузка в root-оболочку без служб.**
 +
 +^ Init система ^ Режим ^
 +| System V | Уровень выполнения 1 |
 +| systemd | rescue.target |
 +| Параметр загрузчика | **-s** |
 +
 +**Недостатки:** сеть часто недоступна, нет GUI, терминал может работать некорректно. **Live-образ более предпочтителен.**
 +
 +**Требует:** пароль суперпользователя для входа.