Рубріки: Теория

Применение systemd: только самое главное

Сергей Почекутов

Systemd — это менеджер системы и служб Linux. Он инициализирует другие демоны в системе при загрузке. Основная цель systemd — полный контроль над запуском и выполнением процессов, описанных в его конфигурации. Какая у менеджера архитектура и как его применять — узнаете из этой обзорной статьи.

Источник: habr.com

Содержание:
1. Плюсы и минусы systemd
2. Архитектура systemd
3. Возможности systemd
4. Юниты systemd
5. Структура юнита systemd
6. Редактирование юнитов
7. Создание юнитов
8. Анализ ошибок с помощью journalctl
9. Интерфейс для systemd
10. Основные команды systemd
Итоги

1. Плюсы и минусы systemd

При старте Systemd запускает параллельно столько служб, сколько возможно в зависимости от стадии загрузки. Это заметно ускоряет запуск системы. Если замерить время от включения до входа, то systemd использует его гораздо меньше, чем предшественники — например, SystemV.

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

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

Однако системные администраторы отмечают и минусы менеджера. Главный — он нарушает один из принципов философии UNIX — «Пишите программы, которые делают что-то одно и делают это хорошо». Принцип KISS (акроним для «Keep it simple, stupid» — «Делай проще, тупица») требует максимальной простоты и самодостаточности от используемых инструментов, в этом плане Systemd — это скорее комплексный комбайн, который, помимо инициализации, выполняет еще огромное количество смежных функций. Из-за этого порой он нестабилен и без дополнительной тонкой настройки потребляет много ресурсов.

2. Архитектура systemd

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

Источник: Shmuel Csaba Otto Traian, CC BY-SA 3.0 via Wikimedia Commons

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

3. Возможности systemd

В зависимости от используемых при компиляции параметров systemd включает до 69 файлов. С их помощью выполняются следующие задачи:

  • Systemd как PID 1 осуществляет запуск стольких служб в параллельном режиме, сколько ему нужно. Благодаря этому загрузка ускоряется.
  • Systemd создает журналы для хранения системных логов и дает инструменты для управления записями.
  • Systemctl дает пользовательский интерфейс для управления службами.
  • Обеспечивается обратная совместимость благодаря поддержке SystemV и LSB.
  • Управление службами и логи дают информацию о состоянии служб.
  • Можно управлять сокетами.
  • Таймеры предоставляют расширенные возможности для планирования, включая запуск скриптов по времени от старта системы.
  • Можно монтировать и размонтировать файловые системы с иерархическим уведомлением для безопасного каскадирования.
  • Можно создавать временные файлы и управлять ими, в том числе удалять.
  • Можно запускать скрипты при подключении или отключении устройств.
  • Можно через анализ последовательности загрузки найти службы, запуск которых отнимает больше всего ресурсов или вызывает сбои.

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

4. Юниты systemd

Юнит — это описание сервиса в текстовом виде. В нем указаны операции, которые выполняются до и после запуска службы. По сути, это описание параметров инициализации.

Все юниты разложены по трем каталогам:

  1. /usr/lib/systemd/system/ — юниты из установленных пакетов RPM. Например, Nginx, MySQL, Apache.
  2. /run/systemd/system/ — юниты, созданные в рантайме.
  3. /etc/systemd/system/ — юниты, созданные системными администраторами.

Посмотреть список всех запущенных юнитов можно командой:

systemctl

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

  • UNIT — название юнита.
  • LOAD — информация об успешной загрузке конфигурации.
  • ACTIVE — сообщение о статусе. Может быть также INACTIVE, LOADED и другие.
  • SUB — детальная системная информация об юните.
  • DESCRIPTION — краткое описание юнита.

Юниты бывают разных типов. Например, юнит службы имеет тип *.service. Все виды:

Тип Что делает
.service Описывает, как управлять службой или приложением на сервере.
.socket Описывает сетевой, IPC-сокет или FIFO-буфер, который используется для активации сокета.
.device Описывает устройство, указанное как необходимое для управления systemd с помощью udev или файловой системы sysfs.
.mount Определяет точку монтирования в системе, которой управляет systemd.
.automount Настраивает точку монтирования, которая будет автоматически установлена.
.swap Описывает пространство подкачки в системе (swap-файл).
.target Обеспечивает точки синхронизации для других устройств при загрузке или изменении состояний.
.path Определяет путь, который может использоваться для активации на основе пути.
.timer Определяет таймер, который управляется systemd для задержки или активации по плану.
.snapshot Позволяет восстановить текущее состояние системы после изменений.
.slice Связан с узлами группы управления Linux, что позволяет ограничить ресурсы или назначить их для любых процессов, связанных с slice.
.scope Создается автоматически systemd из информации, которую получил от интерфейса шины.

В этой статье мы будем работать с юнитами *.service. Чтобы отфильтровать их, выполните команду:

systemctl list-units --type=service

Также можно выбрать только неактивные юниты служб:

systemctl list-units --all --state=inactive

Можно использовать другие статусы: active, inactive, running, exited, dead, loaded, not-found, plugged, mounted, waiting, listening.

5. Структура юнита systemd

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

Для наглядности посмотрите на пример юнита sshd:

[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.target
Wants=sshd-keygen.target
 
[Service]
Type=notify
EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
 
[Install]
WantedBy=multi-user.target

Давайте разберем все секции.

Unit

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

  • Description — короткое описание демона.
  • Documentation — страница man, на которой расписан порядок взаимодействия со службой.
  • After — указание на то, после каких демонов и событий демон запускается. Например, юнит Nginx поднимается после запуска сетевых интерфейсов. Можно указать целую группу других сервисов.
  • Requires — какой сервис необходим для запуска юнита.
  • Wants — какой сервис желательно запустить перед стартом юнита.

Если указать сервис в Requires, но не прописать его в After, то он будет запущен параллельно с юнитом, который вы настраиваете.

Пример оформления секции Unit:

[Unit]
Description=MyUnit
After=syslog.target
After=network.target
After=nginx.service
After=mysql.service
Requires=mysql.service
Wants=redis.service

Service

Вторая обязательная секция для описания конфигурации. Здесь вы указываете, какими командами и под каким пользователем запускать сервис.

  1. Type — описывает, как запустится демон. Есть несколько вариантов: simple (по умолчанию) — systemd ожидает, что служба запустится незамедлительно. Процесс не должен разветвляться. forking — после запуска демон ответвляется (делает форк), родительский процесс завершается. Такой подход используется для запуска классических демонов. one-shot — одноразовое выполнение. Используется для скриптов, которые запускаются и завершаются после выполнения. notify — аналог simple, но в этом случае сам процесс сообщит systemd о том, что он закончил загрузку и готов к работе.
  2. PIDFile — ссылка на основной процесс, который отслеживает systemd.
  3. WorkingDirectory — рабочая директория. Становится текущей перед запуском стартап команд.
  4. User — пользователь, под которым надо запускать сервис.
  5. Group — группа, под которой надо запускать сервис.
  6. Environment — переменная окружения.
  7. OOMScoreAdjust — запрет на убийство сервиса из-за нехватки памяти или срабатывания механизма OOM (-1000 — полный запрет).
  8. ExecStart — команда для старта сервиса.
  9. ExecReload — команда для перезапуска сервиса.
  10. ExecStop — команда для остановки сервиса.
  11. TimeoutSec — время в секундах, которое сервис ожидает отработки старт- или стоп-команд.
  12. Restart — настройки перезапуска.

Пример оформления секции Service:

[Service]
Type=forking
PIDFile=/work/www/myunit/shared/tmp/pids/service.pid
WorkingDirectory=/work/www/myunit/current
User=myunit
Group=myunit
Environment=RACK_ENV=production
OOMScoreAdjust=-1000
ExecStart=/usr/local/bin/bundle exec service -C /work/www/myunit/shared/config/service.rb --daemon
ExecStop=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state stop
ExecReload=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state restart
TimeoutSec=300

Install

Третья обязательная секция. В ней описывается на каком уровне запуска стартует настраиваемый сервис.

Переменная WantedBy сообщает, как устройство включится. Например, multi-user.target означает, что при запуске в директории /etc/systemd/system появится каталог multi-user.target.wants. В нем будет ссылка на службу, которая удалится после остановки службы.

Пример оформления секции Install:

[Install]
WantedBy=multi-user.target 

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

man systemd.unit

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

  1. poweroff – отключение системы;
  2. rescue – режим восстановления, однопользовательский (init 1);
  3. multi-user – сетевой режим без графической оболочки, (init 3);
  4. graphical – сетевой режим с графической оболочкой (init 5);
  5. reboot – перезагрузка;
  6. emergency – аварийная командная строка, минимальный функционал.

Цели могут наследоваться. Пример взаимодействия с ними:

#список целей
systemctl list-units --type=target
#перейти в нужную цель (например – загрузится из сетевого режима в графический)
systemctl isolate graphical.target
#выбрать target по умолчанию
systemctl set-default multi-user.target

6. Редактирование юнитов

Юниты нельзя редактировать напрямую. Для этого используется команда edit:

systemctl edit --full nginx.service

Теперь можно добавить в описание юнита несколько переменных. Например, измените секцию Service. Добавьте в нее два параметра:

Restart=on-failure 
RestartSec=60s

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

systemctl daemon-reload

Убедитесь, что конфигурация обновилась. Сначала узнайте PID процесса:

systemctl status nginx.service | grep PID Main PID: 12567 (nginx)

Затем завершите его:

kill -9 12567

Проверьте статус службы:

systemctl status nginx.service

Служба должна находиться в стадии автозапуска. Через 60 секунд (указали именно столько в параметрах юнита) статус изменится на active (running).

7. Создание юнитов

Вы также можете создавать свои юниты. Например, вы написали приложение на Python и хотите добавить его в виде сервиса, которым будете управлять через systemd. В качестве примера создайте юнит item.service:

mcedit /etc/systemd/system/test.service

В описании юнита добавьте обязательные секции:

[Unit] 
Description=test service 
[Service] 
Type=oneshot ExecStart=/bin/echo "Hello World!" RemainAfterExit=yes
[Install]
WantedBy=multi-user.target 

Теперь нужно применить изменения в конфигурации:

systemctl daemon-reload

Следующий шаг — запуск юнита:

systemctl start test.service

Напоследок проверьте его статус:

systemctl status test.service

Навык создания юнитов пригодится и разработчикам, и системным администраторам для установки ПО. Например, в Apache Kafka для управления состоянием кластера и конфигурациями используется служба zookiper. Для нее нужно создавать юнит. И подобные задачи возникают достаточно часто.

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

8. Анализ ошибок с помощью journalctl

Еще одна полезная возможность — логирование запущенных юнитов. При первом запуске сервиса в командной строке отображается очень много информации. В этом «полотне» можно обнаружить ошибки, которые следует исправить. Хороший тон — смотреть логи после каждой перезагрузки сервиса.

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

journalctl -b

Чтобы посмотреть логи всех загрузок:

journalctl

Чтобы увидеть список всех загрузок:

journalctl --list-boots

Если хотите посмотреть лог загрузки за конкретную дату, используйте значение boot_id. Оно отображается после выполнения предыдущей команды. Boot-id добавляется в качестве аргумента:

journalctl -b 9e8736b29ad549ab97923baf470382d6

Можно также посмотреть все загрузки определенного сервиса. Например, проанализируйте работу Nginx:

journalctl -b -u nginx

Чтобы понимать логи, полезно знать уровни ошибок. Всего их восемь:

  • 0 — EMERG (самая критическая ошибка, служба неработоспособна);
  • 1 — ALERT (требует вмешательства);
  • 2 — CRIT (критическая ошибка);
  • 3 — ERR (ошибка);
  • 4 — WARNING (предупреждение);
  • 5 — NOTICE (следует обратить внимание);
  • 6 — INFO (информационное сообщение);
  • 7 — DEBUG.

Используя номера уровней, можно фильтровать логи. Например, получите только ERR:

journalctl -p 3 -b

Посмотрите последние пять записей:

journalctl -n 5

В реальном времени:

journalctl -f

В качестве примера сломаем службу Nginx:

systemctl status nginx.service 
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.default 
systemctl stop nginx.service 
systemctl start nginx.service

Сначала мы проверили статус сервиса, затем переименовали конфигурационный файл, остановили и заново стартовали юнит. В результате вылетела ошибка —

Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

В логах ошибка тоже отмечена:

journalctl -xe

Если проверить статус, то тоже появится сообщение об ошибке:

systemctl status nginx.service

Чтобы исправить ошибку, переименуйте файл обратно.

9. Интерфейс для systemd

Вы можете установить удобную утилиту для управления юнитами systemd — Chkservice. В Debian 10, например, она поставляется в репозитории. Установить ее можно командой:

apt install chkservice

Если в репозитории вашего дистрибутива нет Chkservice, установите утилиту этой командой:

add-apt-repository ppa:linuxenko/chkservice 
apt-get update 
apt-get install chkservice

Интерфейс запускается командой:

chkservice

Для управления используются клавиши вверх и вниз. Запуск юнита — клавиша R, остановка — клавиша S. После нажатия на клавишу сигнал отправляется без уведомлений. Учитывайте это при работе с юнитами.

10. Основные команды systemd

У systemd есть несколько основных команд, которые быстро запоминаются при постоянном использовании менеджера.

  • systemctl start name.service — запустить сервис.
  • systemctl stop name.service — остановить сервис.
  • systemctl restart name.service — перезапустить сервис.
  • systemctl status name.service — узнать статус сервиса.
  • systemctl enable name.service — добавить сервис в автозагрузку.
  • systemctl disable name.service — удалить сервис из автозагрузки.
  • systemctl is-enabled name.service — проверить, находится ли сервис в списке автозагрузки.
  • systemctl mask name.service — запретить запуск сервиса.
  • systemctl umask name.service — разрешить запуск сервиса.
  • systemctl --state=failed — показать службы, которые не запустились.
  • systemctl help name.service — показать страницу руководства сервиса.
  • systemctl daemon-reload — применить конфигурацию после изменения в описании сервиса.

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

systemctl list-unit-files

Для удобства можно отсортировать службы по их текущему статусу. Есть четыре флага:

  1. enabled — автозагрузка включена;
  2. disabled — автозагрузка отключена;
  3. masked — служба скрыта;
  4. static — служба в автозагрузке, вы не можете ей управлять.

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

systemctl list-unit-files --state disabled

Посмотреть полную информацию о незагруженных юнитах:

systemctl list-units --all

С помощью systemctl также можно увидеть зависимости модуля. Например:

systemctl show sshd.service

После выполнения команды в терминале отобразится список зависимостей службы sshd:

sshd.service
├─system.slice
└─basic.target
  ├─microcode.service
  ├─rhel-autorelabel-mark.service
  ├─rhel-autorelabel.service
  ├─rhel-configure.service
  ├─rhel-dmesg.service
  ├─rhel-loadmodules.service
  ├─paths.target
  ├─slices.target

Вы также можете посмотреть свойства любого юнита. Используйте команду:

systemctl show sshd.service

Вывод:

Id=sshd.service
Names=sshd.service
Requires=basic.target
Wants=system.slice
WantedBy=multi-user.target
Conflicts=shutdown.target
Before=shutdown.target multi-user.target
After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice
Description=OpenSSH server daemon

Если нужно отобразить одно свойства, добавьте в команду флаг -p с его именем. Например, посмотрите конфликты модуля sshd:

systemctl show sshd.service -p Conflicts

Вывод:

Conflicts=shutdown.target

Итоги

Споры о плюсах и минусах systemd и сравнения с другими менеджерами продолжаются. Но в пользу этой популярной системы говорит то, что во многих дистрибутивах она используется по умолчанию. Среди них Debian GNU/Linux 8+, Ubuntu 15.10+, CentOS 7+, RHEL 7+ и другие. Без systemd поставляются форки Debian и Arch, Gentoo, Void Linux, *BSD системы.

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

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023