Управление службами в GNU/Linux

Управление службами в GNU/Linux #

Васильев Андрей Михайлович, 2023

Версии презентации


Загрузка системы #

flowchart TB power("Подача питания") bios["Загрузка микрокода материнской платы"] hw_init["Инициализация ключевых компонентов\nРабота BIOS"] loader_search["Поиск загрузчика"] loader_init["Передача управления загрузчику"] os_init["Загрузка ядра ОС"] power --> bios bios --> hw_init --> loader_search --> loader_init --> os_init

Существует несколько стандартов для реализации систем загрузки

  • BIOS, Basic Input Output System
  • UEFI, Unified Extensible Firmware Interface
  • EFI, Extensible Firmware Interface
  • Множество закрытых решений

Решают общие задачи:

  • Первоначальная инициализация устройств
  • Поиск загрузчика ОС на устройствах хранения
  • Поиск загрузчика ОС на сетевых устройствах

Загрузчик ОС #

Задачей загрузчика ОС является поиск ядра ОС с дальнейшей передачей ему управления

Современные загрузчики:

  • Являются отдельными бинарными файлами на ПЗУ
  • Обычно располагаются на ПЗУ в отдельном разделе
  • Настраиваются с помощью внешнего файла
  • Могут считывать данные из файловых систем
  • Могут иметь интерактивный интерфейс для выбора ОС
    • Решение для загрузки разных ОС
    • Решение для загрузки разных ядер внутри одной ОС

Ядро ОС #

flowchart BT subgraph hardware["Техническое обеспечение"] ram["ОЗУ"] hdd["ПЗУ"] etc["..."] net["Сеть"] end os["Ядро операционной системы"] proc_1["Процесс № 1"] proc_2["Процесс № 2"] proc_3["Процесс № 3"] os --> ram os --> hdd os --> etc os --> net proc_1 --> os proc_2 --> os proc_3 --> os

Ядро ОС обеспечивает эффективное использование технического обеспечения множеством конкурирующих друг с другом процессов

Операционная система помимо ядра предоставляет набор системных приложений

  • Позволяющих настраивать параметры работы ядра
  • Позволяющих управлять процессами внутри ОС

Файлы ядра Linux #

В GNU/Linux для загрузки ОС применяется связка из

  • ядра ОС
  • initrd, Initial RAM Disk, образа файловой системы, необходимой ядру для первичной загрузки операционной системы

Оба компонента поставляются файлами, лежащими в ПЗУ

В рамках initrd поставляются:

  • Модули ядра ОС, необходимые для работы с оборудованием на данном компьютере
  • Служебные приложения, нужные для загрузки модулей и настройки системы

Модули могут поставляться отдельно от ядра:

  • Для поддержки проприетарных решений
  • Для решения задачи поддержки множества разных конфигураций оборудования

Процесс загрузки ОС #

В рамках загрузки ядра ОС происходит поиск всего оборудования и его инициализация

После того как всё оборудование инициализировано, ядро запускает процесс-инициализации init

  • Процесс работает до окончания работы ОС
  • Процесс имеет идентификатор, равный 1
  • Процесс запускает все остальные процессы в системе

Существует множество систем инициализации: SysVinit, systemd, openrc, runit, initware

  • Для выбора системы инициализации ядру можно передать аргумент init с полным путём к исполняемому файлу
  • Сравнение разных систем предоставляет проект Gentoo

Задачи системы инициализации #

  • Запуск служб, постоянно работающих фоновых процессов
    • В процессе запуска операционной системы
    • При обращении к службе посредством сети, D-Bus, сокету и т.д.
  • Перезапуск служб в случае их падения

Система инициализации может также выполнять действия других системных служб

  • Подключение файловых систем (обычно да)
  • Настройка сетевых интерфейсов (обычно нет)
  • Запуск задач по расписанию (обычно нет)
  • Журналирование работы служб (обычно нет)
  • Управление входом пользователей в систему (обычно нет)
  • Создание виртуальных файлов для устройств (обычно нет)
  • Управление временем системы (обычно нет)

Стадии загрузки ОС #

При запуске системы обычно рассматриваются следующие стадии:

  • Настройка ключевых служб (диски, системы обмена сообщениями и т.д.)
  • Поддержка работы сессии суперпользователя
  • Поддержка работы множества пользователей
  • Запуск служб, обеспечивающих продуктовые функции системы (SSH, Веб-сервер, …)
  • Поддержка работы с графическим пользовательским интерфейсом

Также система инициализации должна выполнять корректное выключение системы, т.е. выключать службы в правильном порядке и сохранить данные на ПЗУ в случаях:

  • Завершения работы
  • Перезагрузки системы

Система инициализации позволяет переходить между стадиями, выбирать разные стадии при запуске


Варианты реализации стадий #

SysV Runlevel systemd Target (Цель) Записки
0 poweroff.target, runlevel0.target Выключить систему.
1, s, single rescue.target, runlevel1.target Режим одного пользователя.
2, 4 multi-user.target, runlevel2.target, runlevel4.target Определённые пользователем (системой). По умолчанию 3
3 multi-user.target, runlevel3.target Многопользовательская инициализация, не графическая. Пользователи могут входить по сети или через терминалы.
5 graphical.target, runlevel5.target Многопользовательская с поддержкой графического интерфейса.
6 reboot.target, runlevel6.target Перезагрузка.
emergency emergency.target Экстренный доступ для суперпользователя.

Службы #

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

  • Приложение реагирует на некоторые сигналы и выполняет некоторые действия
    • Сигнал от ядра ОС о добавлении нового устройства
    • Сигнал по шине взаимодействия, запрос на выполнение операции
    • Сигнал по сетевому интерфейсу, выполнение действия
  • Приложению для работы необходимо, чтобы все его зависимости были доступны на момент запуска:
    • Файловая система с файлами службы уже доступна на момент запуска
    • Сетевой интерфейс уже настроен и готов обрабатывать запросы
    • Служба базы данных запущена и готова обрабатывать запросы

Службы также могут представлять собой действия, выполняющиеся с некоторой регулярностью, например по расписанию


Указание зависимостей #

Точное указание зависимостей позволяет ускорить загрузку системы, избежать проблем при запуске служб

  • В классическом SysVInit необходимо было следить за включением службы в нужный уровень выполнения
    • Подразумевается, что на третьем уровне уже доступны файловая система и сеть
    • На последнем уровне можем надеяться, что служба базы данных тоже доступна
  • Следующие системы инициализации предложили способы для указания зависимостей на уровне конкретных служб
  • В рамках systemd каждая служба указывает список зависимостей:
    • Явные зависимости от других служб
    • Неявные зависимости через включение в конкретную цель

Настройка службы #

Вопрос запуска службы помимо момента запуска достаточно сложный:

  • Где располагается исполняемый файл?
  • Какие аргументы необходимо передать исполняемому файлу?
  • Какие аргументы передавать через переменные окружения?
  • С правами какого пользователя нужно запустить файл?
  • Какие элементы должны быть доступны службы?

Помимо запуска есть много вопросов поддержки работы:

  • Что делать в случае остановки службы?
  • Как корректно выполнить перезапуск службы?
  • Как проверить текущий статус работы службы?

Классическое решение #

Задача настройки параметров запуска службы достаточно сложная, разработчиками SysVInit решена не была, поэтому процесс запуска служб делегировали Shell-скриптам

  • Требует высокой квалификации от разработчика
  • Требуют запуска интерпретатора Shell для своей работы
  • Сложно реализовать систему отслеживания работы
  • Невозможно реализовать другие способы запуска:
    • Запуск службы при обращении по шине D-Bus
    • Запуск службы по расписанию
    • Запуск службы по обращению к порту

Каждый из последних потребуют написания своей конфигурации


Настройка systemd #

Для описания всех компонентов systemd используются файлы модулей (unit), в которых описывается поведение конкретного компонента. В настоящий момент systemd поддерживает следующие виды модулей:

Тип модуля Описание
Target Синхронизационная точка для ряда модулей. Используется во время загрузки системы в определённом состоянии.
Service Модуль, который запускает, останавливает, перезапускает, даёт команду на обновление конфигурации различных служб, например Веб-сервер.
Timer Модуль данного типа активирует или деактивирует указанную службу по времени наступления таймера или истечения времени.
Socket Модуль данного типа активирует или деактивирует службу, когда приходит входящее подключение по указанному сокету.
Device A unit of this type implements device-based activation such as a device driver.

Тип модуля Описание
Mount A unit of this type controls the file-system mount point.
Automount A unit of this type provides and controls on-demand mounting of file systems.
Swap A unit of this type encapsulates/activates/deactivates swap partition.
Path A unit of this type monitors files/directories and activates/deactivates a service if the specified file or directory is accessed.
Snapshot A unit that creates and saves the current state of all running units. This state can be used to restore the system later.
Slice A group of units that manages system resources such as CPU, and memory.
Scope A unit that organizes and manages foreign processes.
busname A unit that controls DBus system.

Каталоги конфигурации systemd #

Список можно посмотреть в man-руководстве systemd.unit

  • Пути для поиска модулей системного уровня
    • /etc/systemd/system.control/*
    • /run/systemd/system.control/*
    • /etc/systemd/system/* — Файлы, созданные администратором
    • /run/systemd/system/*
    • /lib/systemd/system/* — Файлы, установленные вместе с пакетом приложения
  • Пути для поиска модулей пользовательского уровня
    • ~/.config/systemd/user.control/*
    • ~/.config/systemd/user/*
    • $XDG_CONFIG_DIRS/systemd/user/*
    • /etc/systemd/user/*
    • $XDG_RUNTIME_DIR/systemd/user/*
    • /run/systemd/user/*

Настройка systemd-службы #

Конфигурационные файлы служб systemd являются текстовыми файлами в формате INI

flowchart BT service --> unit target --> unit timer --> unit
  • Все типы конфигурационных файлов являются unit-файлами
  • Все элементы конфигурации unit-файлов можно написать в других типах файлов
  • Полную документацию можно найти в страницах systemd.unit, systemd.service, systemd.timer и т.д
  • Ввиду многообразия задач, решаемых systemd, конфигурационные файлы достаточно сложные

Простая служба на systemd #

[Unit]
Description=Start n service
After=default.target

[Service]
Type=simple
ExecStart=/usr/bin/n

[Install]
WantedBy=default.target
  • Секция Unit описывает общую информацию о службе, часть unit-файлов
    • Description — краткое описание назначения службе
    • After — указание зависимости одной службы от другой
  • Секция Install описывает параметры автоматического запуска службы при старте системы, часть unit-файлов
    • Type — поведение приложения после запуска
    • WantedBy — указание зависимости от цели запуска
  • Секция Service описывает детали запуска службы
    • ExecStart — команда для запуска приложения, должна включать полный путь к исполняемому файлу, может включать аргументы

Что нужно настроить #

Требований к параметрам работы служб много — скорее всего на настоящий момент в systemd есть поддержка для решения данной задачи

Указание учётной записи #

Если не указать пользователя, то приложение будет работать с правами суперпользователя, что является проблемой для большинства служб

В секции Service необходимо указать пользователя с помощью параметра User

Настройка параметров перезапуска #

Служба не всегда ведёт себя как следует и может упасть. Политика перезапуска определяется в секции Service с помощью параметра Restart

  • on-failure — перезапускать в случае падения
  • always — перезапускать даже когда хорошо завершилось

Добавление новых служб #

  1. Создайте текстовый файл службы в каталоге /etc/systemd/system
    • Созданный файл должен иметь расширение .service
    • Предположим, что файл называется example.service
  2. Заполните необходимые поля в созданном файле:
    • Заполните секцию [Unit], указав описание и зависимости
    • Заполните секцию [Service], указав параметры запуска приложения
    • Заполните секцию [Install], указав параметры автоматического запуска
  3. Скажите демону systemd перечитать конфигурацию с жёсткого диска, выполнив команду systemctl daemon-reload
  4. Запустите службу средствами systemd, выполнив команду systemctl start example или целиком systemctl start example.service
  5. Посмотрите на статус запущенной службы systemctl status example

Для остановки службы используйте команду systemctl stop example


Автоматический запуск службы #

Команды start и stop приложения systemctl пытаются запустить или остановить процесс, который находится под управлением systemd

Для настройки автоматического запуска необходимо:

  1. Добавить секцию [Install] внутри конфигурационного файла
  2. Выполнить команду systemctl enable example.service

Последняя команда настраивает запуск службы при старте ОС, не запускает её сейчас

  • Для запуска службы необходимо вызвать команду start
  • При включении автоматического запуска можно передать аргумент --now: systemctl enable --now example.start. В этом случае будет настроен автоматический запуск при старте и будет выполнена попытка запуска службы сейчас

Для выключения автоматического systemctl disable example или systemctl disable --now example


Управление службами systemd #

Анализ поведения системы

Дейтвие Команда
Отобразить состояние systemd systemctl status
Отобразить список запущенных модулей systemctl или systemctl list-units
Отобразить список упавших модулей systemctl --failed
Отобразить список конфигурационных файлов модулей systemctl list-unit-files
Отобразить статус модуля по PID процесса systemctl status PID

Анализ поведения службы

Дейтвие Команда Комментарий
Отобразить страницу руководства, ассоциированную с данной службой systemctl help UNIT если указана в конфигурации модуля
Отобразить статус модуля systemctl status UNIT показывает запущен или остановлен модуль
Проверить включён ли модуль systemctl is-enabled UNIT

Управление состоянием службы. Все в данном разделе требуют прав суперпользователя

Дейтвие Команда
Запустить модуль systemctl start UNIT
Остановить работу модуля systemctl stop UNIT
Перезапустить модуль systemctl restart UNIT
Дать команду службе перечитать конфигурацию systemctl reload UNIT
Перечитать конфигурацию systemd systemctl daemon-reload
Настроить автоматический запуск модуля при старте системы systemctl enable UNIT
Настроить автоматический запуск модуля при старте системы и сразу запустить его systemctl enable --now UNIT
Отключить автоматический запуск модуля при старте системы systemctl disable UNIT
Отключить и настроить автоматический запуск модуля systemctl reenable UNIT

Управление состоянием системы #

Данные действия надо выполнять от имени суперпользователя

Дейтвие Команда
Выключить ОС и перезагрузить компьютер systemctl reboot
Выключить ОС и обесточить компьютер systemctl poweroff
Приостановить работу ОС с сохранением данных в оперативной памяти systemctl suspend
Приостановить работу ОС с сохранением данных в разделе подкачки systemctl hibernate
Приостановить работу ОС с гибридным сохранением состояния systemctl hybrid-sleep

Запуск служб по расписанию #

Ряд служб могут быть приложениями, которые выполняют поставленную задачу:

  • Выполняют резервное копирование
  • Выполняют обновление ключей безопасности
  • Очищают каталоги с журналами

Они не работают постоянно, а выполнив свою задачу, отключаются

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


Виды таймеров #

systemd поддерживает следующие таймеры:

  • Таймеры по расписанию: активируются при наступлении некоторого события по времени
  • Монотонные таймеры: выполняют действия через некоторое время после наступления события

Настройка таймера для службы #

  • Конфигурационные файлы таймера располагаются рядом с .service-файлами службы
  • Расширение файла с конфигурацией таймера — .timer
  • Название файлов без расширения должны совпадать
  • Описание полей находится в man-странице systemd.timer

Автозапуск таймера #

systemd предоставляет цель timers.target ….


© A. M. Васильев, 2023, CC BY-SA 4.0, andrey@crafted.su