Тариф успешно добавлен в корзину
В корзину
url image

Systemd: основы управления службами

На большинстве Linux-серверов для управления службами используется systemd. Он содержит инструменты для работы процессом загрузки и взаимодействия с сервисами системы. Это означает, что systemd является важным механизмом в работе любого сервера. В этой статье мы познакомимся с его функциональностью и как с его помощью можно управлять работой процессов и демонов.

Systemd: что это и для чего используется


Systemd — это фундаментальная подсистема инициализации, менеджер служб и набор инструментов для операционных систем на базе Linux. Её основная задача: управление всеми процессами, службами и ресурсами в современной Linux-системе. 

Ранее для этих задач использовалась система SysVinit или просто init. Она была простой, но и не лишенной недостатков. Давайте кратко рассмотрим основные особенности SysVinit:

  • Использует традиционный линейный подход к инициализации системы (службы запускаются в порядке очереди по порядку), что обеспечивает простоту. Может замедлять загрузку в сложных системах, но подходит для систем с меньшим количеством зависимостей сервисов друг от друга;
  • Управление осуществляется через обычные shell-скрипты;
  • Не обеспечивает логирование по умолчанию. Требуются дополнительные службы.

Systemd фактически вытеснила в 2010-е годы традиционную подсистему SysVinit. Изначально разработанная сотрудниками компании RedHat, уже сейчас эта система содержится почти во всех популярных дистрибутивах Linux. Основные отличия Systemd:

  • Может выполнять инициализацию и запуск служб параллельно, если это допускается их конфигурацией;
  • Управление службами осуществляется через через специальные сущности — юниты (units);
  • По умолчанию поддерживает ведение логов системы.

Есть немало противников systemd, потому что она нарушает один из первоначальных постулатов философии Unix: «Пишите программы, которые делают что-то одно и делают это хорошо». Также у критиков есть ряд других аргументов, например, что исходный код излишне запутанный и содержит множество намеренных багов и уязвимостей. 

Но нельзя отрицать, что управление службами стало удобнее, нагляднее и обеспечило стандартизированный подход к управлению службами в различных дистрибутивах Linux. Эта практическая польза для системных администраторов и разработчиков стала одним из решающих факторов, благодаря которому systemd, несмотря на критику, была принята как основа для подавляющего большинства современных дистрибутивов.

Обзор systemd: место на этапе загрузки, типы юнитов и конфигурации служб


В этом разделе мы разберем, как именно systemd интегрирована в процесс загрузки Linux, познакомимся с основными типами конфигурационных файлов (юнитов), а затем детально изучим строение одного из них на практическом примере. 

При подаче питания на сервер загрузка системы проходит несколько этапов. И на одном из последних управление передаётся от загрузчика (чаще всего это GRUB) к systemd. Systemd становится первым процессом в системе с PID 1 и все остальные процессы порождаются от него. Он инициирует загрузку системы, запуская критически важные процессы и службы в соответствии с конфигурацией. В отличие от SysVinit, запускающего процессы строго последовательно, systemd параллельно инициирует службы, учитывая их зависимости и условия.

Systemd работает с конфигурационными файлами, называемыми юнитами (units), которые описывают службы, сокеты, таймеры и другие компоненты системы.

Юнит — это описание сущности в файле конфигурации, которой управляет systemd. Обычно юниты создаются при установке служб на сервере, но некоторые образуются автоматически из других конфигурационных файлов, динамически — из состояния системы или программно — во время выполнения. 

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

  • service — с этим типом предстоит сталкиваться чаще всего, поскольку именно сервисы управляют демонами в системе. Демон в Linux — это программа, которая работает в фоновом режиме, без прямого участия пользователя, выполняя системные задачи или предлагая службы другим программам.
  • socket — описывает конечную точку связи для обмена данными, например, в сети (сетевой сокет, к которому обращаются извне) или между процессами на одной машине (IPC-сокет, т. е. сокет межпроцессного взаимодействия, как Unix domain socket), и позволяет запускать сервис только тогда, когда к нему обращаются.
  • timer — таймеры запускают сервисы по расписанию (аналог cron, но с точностью до миллисекунд и поддержкой зависимостей). Преимущества перед cron — может срабатывать относительно времени последнего запуска (например, «каждые 12 часов с момента предыдущего запуска»).
  • target — цели, которые определяют текущий и возможные уровни выполнения системы, группируя юниты для достижения определенного состояния системы, т. е. являются аналогом runlevel в SysVinit.

Чтобы увидеть, как устроены юниты на практике, подробно рассмотрим пример конфигурации одного из самых распространенных типов — службы (.service). В качестве примера возьмем конфигурацию для сервера SSH в Ubuntu:

~# cat /lib/systemd/system/ssh.service
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service

В файле юнита можно увидеть несколько секций:

  • [Unit] — секция для общего описания юнита. Конкретно в этой конфигурации есть краткое описание (Description), ссылки на документацию man (Documentation), указание на порядок запуска (после network.target и auditd.service) и условие запуска (если файл /etc/ssh/sshd_not_to_be_run отсутствует);
  • [Service] — секция для определения запуска и работы сервиса. Конкретно в этой конфигурации есть:
    • определение файла окружения /etc/default/ssh и если он отсутствует, то это не приведёт к проблеме;
    • команды для запуска и перезагрузки конфигурации — ExecStartPre, ExecStart и ExecReload соответственно;
    • правила для завершения процесса и опции для его перезапуска — KillMode, Restart. RestartPreventExitStatus=255 означает, что с завершением процесса с кодом 255 его перезагрузки не будет — этот код обычно означает проблемы с конфигурацией, поэтому в этом случае перезапуск не нужен;
    • тип запуска -type — в этом случае notify будет ждать от процесса сигнала о готовности к подключениям от процесса sshd;
    • указание на каталог для запуска и временных файлов процесса (RuntimeDirectory и RuntimeDirectoryMode);
  • [Install] — другие опции для запуска сервиса. В этом случае секция указывает, какой уровень загрузки системы (runlevel) необходим для запуска (WantedBy) и псевдоним для юнита (Alias).

Из файла конфигурации юнита systemd понимает, в какой момент запускать службу и какие опции необходимо использовать для корректной работы.

Кроме того, в юнитах могут описываются параметры WantedBy или After — именно они показывают systemd, в какой момент запускать юнит. Посмотреть все дерево зависимостей можно через команду:

systemctl list-dependencies UNIT
Дерево зависимостей ssh
Дерево зависимостей ssh от других юнитов

Также можно посмотреть, какие юниты зависят от конкретного юнита с модификацией команды:

systemctl list-dependencies UNIT --reverse
Дерево зависимостей от ssh
Дерево зависимостей от ssh

После краткого обзора конфигурации юнитов можно перейти к рассмотрению способов управления ими.

Основные команды для управления юнитами

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

Просмотр конфигурации

Возвращаясь к примеру с конфигурацией юнита ssh, можем получить её с помощью следующей команды:

systemctl cat UNIT
Вывод команды systemctl cat
Вывод команды systemctl cat

Это бывает удобно, когда нужно быстро посмотреть, какие опции юнит предоставляет, и как systemd им управляет без указания конкретного пути до конфигурации, просто указывая название юнита. Также подобный синтаксис позволяет увидеть включенные в конфигурацию другие файлы, отличные от основного. Синтаксис cat работает не только со службами, но и с таймерами и сокетами. Если вывод команды переполнен различными комментариями и пустыми строками, то убрать все лишнее поможет следующая команда:

systemctl cat UNIT | egrep -v "^$|#"

По сути, предыдущая команда cat выводит только ту информацию, в которой описывается юнит, но это далеко не все параметры, какие используются. Большая часть параметров  systemd определены неявно и применяются по умолчанию. Чтобы посмотреть полный список , используем  команду:

systemctl show UNIT [-p PARAMETR]

Через дополнительный ключ -p можно указать, какой из множества параметров нужно вывести. Допускается выводить сразу несколько параметров. Например, получим те, которые использует systemd для nginx:

Получение значений Restart, Type и SendSIGKILL для nginx
Получаем только значения Restart, Type и SendSIGKILL для nginx

Если мы захотим проверить все параметры, то список будет довольно большим:

Просмотр всех параметров работы для nginx
Просмотр всех параметров работы для nginx

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

man 5 systemd.service
man 5 systemd.unit

Поиск юнитов и их полный список

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

systemctl list-units

По умолчанию эта команда выводит все известные юниты в ОС, группируя их по типу. И, как следствие, сложно найти нужный юнит:

Вывод list-units без фильтров
Вывод list-units без фильтров

Поэтому лучше использовать специальные фильтры при вызове команды:

systemctl list-units [--type=service | --type=socket | --type=timer]

Дополнительно можно указать ключ --no-pager, который позволит вывести весь список сразу, что может быть удобно для поиска через grep. Эту опцию можно использовать во многих командах systemd. В ином случае предыдущая команда переходит в режим просмотра, как при вызове утилиты less, и не даёт полного вывода сразу.

Также можно отфильтровать службы по их статусу, то есть какие юниты запущены, остановлены штатно или же с ошибкой:

systemctl  --state [ running |  exited | failed | dead]

Управление юнитом

Получить текущий статус определенной службы можно с помощью команды:

systemctl status UNIT

Рассмотрим вывод команды status на примере веб-сервера nginx:

Статус службы nginx
Статус службы nginx

На скрине выше цифрами обозначены следующие компоненты в выводе команды:

  1. Краткое описание службы.
  2. Основные параметры службы, такие как конфигурационный файл и наличие службы в автозагрузке.
  3. Дополнительные конфигурации, которые включены в момент запуска.
  4. Параметры работы службы — такие как текущий статус (active) и время с момента последнего запуска, основной PID, использование CPU и RAM, к какому CGroup (control group) служба относится и текущие дочерние PID.

После всех параметров службы отображаются последние записи в journald (системный журнал в составе systemd, который собирает и хранит логи всех компонентов системы).

Остановить, запустить и перезапустить службу можно следующим образом:

systemctl stop UNIT
systemctl start UNIT
systemctl restart UNIT
Остановка и запуск юнита
Остановка и запуск юнита

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

systemctl stop nginx apache2
systemctl start nginx apache2
Остановка и запуск нескольких юнитов
Остановка и запуск нескольких юнитов

В одном из предыдущих примеров взят nginx. И по своей конфигурации он допускает перезагрузку конфигурации без перезапуска службы, поэтому, чтобы выполнить перезагрузку конфигурации юнита, можно воспользоваться командой:

systemctl reload UNIT

Факт перезапуска службы (после команды reload) видно в последних логах journald, которые выводятся при просмотре статуса:

Перезагрузка конфигурации nginx
Перезагрузка конфигурации nginx

Добавление в автозагрузку

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

systemctl disable UNIT # убираем
systemctl enable UNIT # добавляем
Выключение и включение автозагрузки для службы
Выключение и включение автозагрузки для службы

При этих операциях видно, что именно делает systemd. При добавлении службы в автозагрузку он создаёт ссылку из каталога /lib/systemd/system в каталог /etc/systemd/system/multi-user.target.wants.

Проверить, добавлена ли служба в автозапуск, можно по статусу службы в выводе status или через команду проверки (возвращает либо enabled, либо disable):

systemctl is-enabled UNIT

Журнал systemd

Для сбора информации о работе ОС systemd имеет встроенный инструмент journald. С помощью него можно просмотреть основные события в системе и отследить работу определённых служб/юнитов. Управление осуществляется через утилиту journalctl. Разберем основные возможности при работе с журналом. 

Файл конфигурации, место хранения журналов в системе и их очистка


Кратко рассмотрим, где хранятся его логи. По умолчанию (в конфигурации описывается как auto) логи systemd хранятся в каталоге /var/log/journal. Сама конфигурация службы содержится в файле /etc/systemd/journald.conf.

В нем можно указать желаемое поведение службы и настроить хранение логов. После изменения файла необходимо перезапустить службу через systemd:

systemctl restart systemd-journald

Если этого каталога /var/log/journal нет в системе (например, он был ранее удалён через rm), то логи хранятся в каталоге /run/log/journal.

Важный момент.  Удаление каталога /var/log/journal — плохая идея. Так как  события будут записываться исключительно RAM и в псевдофайловом каталоге /run/log/journal, соответственно, после перезагрузки все записи будут утеряны. 

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

journalctl --disk-usage

Чтобы очистить журнал до нужного размера или времени, задайте в команде необходимые лимиты:

journalctl [--vacuum-size= | --vacuum-time=]
Очистка журнала по времени или месту
Очистка журнала по времени или месту

Просмотр журнала


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

journalctl

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

journalctl -u UNIT [--no-pager]

Она выведет все записанные логи в журнале. 

Можно также фильтровать вывод по времени. Например, в случае, если нас интересует конкретное время или интервал, используем следующие команды:

journalctl -u SERVICE --since "YYYY-MM-DD HH:MM:SS" --until "YYYY-MM-DD HH:MM:SS"
journalctl -u SERVICE --since "YYYY-MM-DD HH:MM:SS" # до текущего времени
journalctl -u SERVICE --since "-1d" # события за 1 день
journalctl -u SERVICE --since "-1h" # события за 1 час
journalctl -u SERVICE --since "-1m" # события за 1 минуту

Выводы и итоги

Мы кратко рассмотрели systemd и какими сущностями он может управлять. Разобрали, как использовать systemctl для управления службами и где можно изучить журналы systemd, если возникнет необходимость, показав основные команды и их полезные модификаторы. 

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

Этот материал был полезен?

Скидка новым клиентам
Закажите сервер сегодня и получите скидку на первый месяц аренды!
Наш сайт использует cookies Вы можете отключить их в настройках браузера, но это может ограничить функционал. Оставаясь на сайте, вы соглашаетесь с использованием cookies.