Администрирование

Как работать с systemd

Systemd - это система инициализации, широко распространенная в дистрибутивах Linux и де-факто ставшая новым стандартом. Поэтому ее изучение может значительно облегчить администрирование компьютера.

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

Обратите внимание: systemd установлена по умолчанию во многих дистрибутивах Linux, но не во всех. Поэтому, если в процессе знакомства терминал выдает ошибку (bash: systemctl is not installed), значит, на вашем компьютере установлена другая система инициализации.

Критика

С момента создания systemd является постоянным объектом критики многих пользователей Linux. Особенно активное их сообщество даже создало специальный сайт "Без systemd", на котором перечислены ее недостатки и описываются проблемы при внедрении:
- перенасыщенность и чрезмерная сложность в освоении,
- наличие критичных багов, не исправляемых довольно долгое время,
- проблемы с безопасностью, обусловленные архитектурой все-в-одном,
- агрессивное внедрение в дистрибутивы и зачастую отсутствие альтернативы,
- завязанность его компонентов на самом себе и несовместимость с другими библиотеками,
и т.д.
Подробнее:
Чем плох systemd?
Чем для меня может быть плох systemd?
systemd 219 (1, 2;)
Отдельно стоит отметить перевод с канувшего в лету сайта "Бойкот systemd".
Почему systemd — это плохо?

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

Главная задача данной системы - инициализировать компоненты для запуска после загрузки ядра Linux, традиционно называемые "компонентами пользовательского пространства". Система также используется для управления службами и демонами во время работы ОС. Имея это в виду, начнем с базовых операций управления службами.

Главным объектом управления в systemd являются "модули". Они разделяются по типу представляемых ими ресурсов и существуют в виде файлов. Тип каждого модуля можно узнать по суффиксу в конце файла. Управление службами затрагивает модули служб, находящиеся в файлах модуля с суффиксом .service. Однако в большинстве команд вы можете убрать суффикс .service - systemd достаточно умна и поймет, что ваши команды работают именно со службой.

Запуск и остановка служб

Для запуска службы systemd путем выполнения инструкций в файле модуля службы используйте команду start. Если вы не работаете от пользователя с правами root, вам придется добавить в команду sudo:

sudo systemctl start application.service

Как было указано ранее, systemd умеет искать файлы *.service для управления службами, поэтому команду можно выполнить в таком виде:

sudo systemctl start application.service

Хотя такой формат можно использовать, мы рекомендуем добавлять суффикс .service для большей уверенности, что вы работаете с нужной службой.
Для остановки уже запущенной службы выполним команду stop:

sudo systemctl stop application.service

Перезапуск и перезагрузка

Для перезапуска уже запущенной службы выполним команду restart:

sudo systemctl restart application.service

Если служба может перезагрузить свои файлы конфигурации (без перезапуска), для этого можно выполнить команду reload:

sudo systemctl reload application.service

Если вы не уверены, есть ли в службе функция перезагрузки ее файлов конфигурации, можете выполнить команду reload-or-restart. При возможности будут просто перезагружены файлы конфигурации, иначе будет перезапущена вся служба вместе с новыми файлами конфигурации:

sudo systemctl reload-or-restart application.service

Включение и выключение служб

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

Для включения автозапуска службы выполним команду enable:

sudo systemctl enable application.service

Будет создана символическая ссылка из системной копии файла службы (обычно в /lib/systemd/system или /etc/systemd/system) в путь на диске, используемый systemd для автозапуска файлов (обычно /etc/systemd/system/some_target.target.wants, позже в руководстве мы разберемся с тем, что такое target).

Для отключения автозапуска службы выполним команду disable:

sudo systemctl disable application.service

Символическая ссылка для автозапуска службы будет удалена.

Имейте в виду, что включение службы не запускает ее в текущей сессии. Если вы хотите запустить службу и также включить ее, вам придется выполнить обе команды - start и enable.

Проверка статуса служб

Для проверки статуса службы в системе можно выполнить команду status:

systemctl status application.service

Она выведет статус службы, иерархию cgroup и первые несколько строк в журнале.
Например, при проверке статуса службы Nginx, вы можете увидеть примерно следующее:

Output
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago
Main PID: 495 (nginx)
CGroup: /system.slice/nginx.service
├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; error_log stderr;
└─496 nginx: worker process
Jan 27 19:41:23 desktop systemd[1]: Starting A high performance web server and a reverse proxy server...
Jan 27 19:41:23 desktop systemd[1]: Started A high performance web server and a reverse proxy server.

Это хороший вывод текущего статуса службы с уведомлением о возможных проблемах и соответствующих действиях.
Также есть способы проверки конкретного статуса. Например, чтобы проверить, активна (работает) ли служба в данный момент, можно выполнить команду is-active:

systemctl is-active application.service

Она выведет текущее состояние модуля - активное или неактивное. Если оно активное, то код выхода будет “0” для упрощения его считывания shell-скриптами.
Чтобы проверить включен ли модуль, можно выполнить команду is-enabled:

systemctl is-enabled application.service

Она покажет, включена или выключена служба, и выведет соответствующий код выхода - “0” or “1”.
Существует и третья проверка модуля - на неработоспособность, которая показывает возможное наличие проблем при запуске модуля:

systemctl is-failed application.service

Она выведет статус "активный", если все работает нормально, или "неработоспособный" при наличие ошибок. Если служба была остановлена намеренно, может быть выведен статус "неизвестно" или "неактивно". Код выхода “0” сообщает о случившемся отказе, а "1" принадлежит к любому другому статусу.

Обзор состояний системы

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

Список текущих модулей

Чтобы увидеть список всех активных модулей, о которых знает systemd, можно использовать команду list-units:

systemctl list-units

Она выведет список всех модулей systemd, активных в данный момент. Он будет выглядеть примерно так:

Output
UNIT LOAD ACTIVE SUB DESCRIPTION
atd.service loaded active running ATD daemon
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
dbus.service loaded active running D-Bus System Message Bus
dcron.service loaded active running Periodic Command Scheduler
dkms.service loaded active exited Dynamic Kernel Modules System
getty@tty1.service loaded active running Getty on tty1
. . .

В выводе есть следующие столбцы:

UNIT: Название модуля systemd
LOAD: Был ли загружены файлы конфигурации модуля в systemd. Если модуль загрузился, они сохраняются в памяти.
ACTIVE: Общее состояние активности модуля. Самый простой способ понять, запустился ли модуль успешно или нет.
SUB: Состояние более низкого уровня, показывающее более подробную информацию о модуле. Часто зависит от типа модуля, его состояния и метода его запуска.
DESCRIPTION: Короткое текстовое описание функций модуля.

Поскольку команда list-units по умолчанию показывает только активные модули, все записи выше будут показывать loaded в столбце LOAD и active в столбце ACTIVE. Это поведение systemctl по умолчанию при вызове без дополнительных команд, поэтому вы увидите то же самое при ее вызове без аргументов:

systemctl

Можно приказать systemctl вывести другую информацию, добавив дополнительные флаги. Например, чтобы увидеть все модули, которые systemd загрузила (или попыталась загрузить), можно использовать флаг --all:

systemctl list-units --all

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

Для фильтрации результатов можно использовать другие флаги. Например, флаг --state= показывает состояния LOAD, ACTIVE или SUB, которые мы хотим увидеть. Для этого нужно оставить флаг --all, чтобы systemctl выводила неактивные модули:

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

Еще один общий фильтр - это --type=. Можно приказать systemctl показывать модули только нужного нам типа. Например, чтобы увидеть только активные модули служб, выполним:

systemctl list-units --type=service

Показ всех файлов модулей

Команда list-units показывает только те модули, которые systemd пыталась считать и загрузить в память. Поскольку systemd считывает только нужные по ее мнению модули, вывод будет включать не обязательно все модули, доступные в системе. Чтобы увидеть все файлы модулей, находящиеся по путям systemd (включая те, которые systemd не пыталась загрузить), можно использовать команду list-unit-files:

systemctl list-unit-files

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

Output
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
dev-hugepages.mount static
dev-mqueue.mount static
proc-fs-nfsd.mount static
proc-sys-fs-binfmt_misc.mount static
sys-fs-fuse-connections.mount static
sys-kernel-config.mount static
sys-kernel-debug.mount static
tmp.mount static
var-lib-nfs-rpc_pipefs.mount static
org.cups.cupsd.path enabled
. . .

Обычно состояние может быть enabled, disabled, static или masked. В данном контексте static означает, что файл модуля не содержит раздел установки, используемый для включения модуля. Поэтому данные модули не могут быть включены. Обычно это означает, что модуль выполняет однократное действие или используется только в качестве зависимости для другого модуля и не должен запускаться сам по себе.

Сейчас расмотрим состояние masked.

Управление модулями

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

Просмотр файла модуля

Для просмотра файла модуля, загруженного systemd в систему, можно использовать команду cat (ее добавили в systemd версии 209). Например, для просмотра файла модуля демона планировщика atd мы можем выполнить:

systemctl cat atd.service
Output
[Unit]
Description=ATD daemon
[Service]
Type=forking
ExecStart=/usr/bin/atd
[Install]
WantedBy=multi-user.target

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

Отображение зависимостей

Для просмотра дерева зависимостей модуля можно выполнить команду list-dependencies:

systemctl list-dependencies sshd.service

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

Output
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
. . .

Рекурсивные зависимости отображаются только для модулей .target, которые показывают состояние системы. Чтобы вывести все зависимости рекурсивно, добавьте флаг --all.

Чтобы показать обратные зависимости (модули, зависящие от конкретного модуля), можно добавить флаг --reverse в команду. Другие полезные флаги - это --before и --after, которые можно использовать для отображения модулей, зависящих от конкретного модуля, запускаемого до и после них соответственно.

Проверка свойств модуля

Чтобы увидеть низкоуровневые свойства модуля, можно выполнить команду show, которая выведет список свойств, заданных для конкретного модуля с помощью формата key=value:

systemctl show sshd.service
Output
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.service, можно ввести:

systemctl show sshd.service -p Conflicts
Output
Conflicts=shutdown.target

Маскировка и демаскировка модулей

В разделе управления службами мы рассмотрели, как остановить или отключить службу, однако systemd также может отметить модуль как незапускаемый (автоматически или вручную), создав на него символическую ссылку в /dev/null. Это называется "маскировка модуля" и выполняется командой mask:

sudo systemctl mask nginx.service

Это не позволит запускать службу Nginx ни автоматически, ни вручную, пока она замаскирована.
Если вы проверите list-unit-files, то увидите, что сервис отмечен как masked:

systemctl list-unit-files
Output
. . .
kmod-static-nodes.service static
ldconfig.service static
mandb.service static
messagebus.service static
nginx.service masked
quotaon.service static
rc-local.service static
rdisc.service disabled
rescue.service static
. . .

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

sudo systemctl start nginx.service

Output
Failed to start nginx.service: Unit nginx.service is masked.

Для демаскировки модуля и возможности использовать его снова введите команду unmask:

sudo systemctl unmask nginx.service

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

Редактирование файлов модулей

Хотя разбор конкретного формата файлов модулей не входит в рамки данной статьи, systemctl предоставляет встроенные механизмы настройки и редактирования файлов модулей при необходимости внести в них изменения. Связанная с этим функциональность была добавлена в systemd версии 218.

Команда edit по умолчанию открывает фрагмент файла для нужного юнита:

sudo systemctl edit nginx.service

Она выдаст пустой файл, с помощью которого заместить или добавить директивы в определение модуля. По пути /etc/systemd/system будет создана папка, содержащий имя модуля с добавлением .d. Например, для nginx.service будет создана папка nginx.service.d.

В данной папке будет создан фрагмент под названием override.conf. При загрузке модуля systemd будет объединять в памяти замещающий фрагмент с полным файлом модуля. Директивы во фрагменте будут иметь больший приоритет, чем в оригинальном файле модуля.

Если нужно редактировать весь файл модуля, а не создавать фрагмент, можно добавить флаг --full:

sudo systemctl edit --full nginx.service

Текущий файл модуля будет загружен в редактор, и его можно изменить. При выходе из редактора измененный файл будет записан в /etc/systemd/system и будет иметь больший приоритет, чем модули системы (обычно находятся где-то в /lib/systemd/system).
Чтобы удалить любые сделанные изменения, удалите или папку конфигурации модуля .d или измененный файл службы из /etc/systemd/system. Например, для удаления фрагмента можно ввести:

sudo rm -r /etc/systemd/system/nginx.service.d

Для удаления всего измененного файла модуля можно ввести:

sudo rm /etc/systemd/system/nginx.service

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

sudo systemctl daemon-reload

Подробнее о редактировании файлов модулей можно прочитать здесь.

Настройка состояния системы (уровня запуска) с помощью целей

Цели - это специальные файлы модуля, описывающие состояние системы или точку синхронизации. Как и другие модули, файлы, определяющие цели, имеют свой суффикс - в данном случае это .target. Цели сами почти ничего не делают, вместо этого они группируют другие модули.

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

Например, есть swap.target, который показывает, что подкачка готова к использованию. Модули, являющиеся частью данного процесса, могут синхронизироваться с данной целью, показывая в своих файлах конфигурации, что они желаемы (WantedBy=) или требуются (RequiredBy=) для работы swap.target. Модули, требующие доступной подкачки, могут указать данное условие с помощью атрибутов "желает" (Wants=), "требует" (Requires=) и "после" (After=), чтобы определить их взаимодействие.

Получение и установка цели по умолчанию

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

systemctl get-default
Output
multi-user.target

Если нужно установить другую цель по умолчанию, можно использовать команду set-default. Например, если у вас установлен графический рабочий стол и вы хотите загружать систему по умолчанию в него, можно изменить цель по умолчанию соответственно:

sudo systemctl set-default graphical.target

Вывод доступных целей

Можно получить список доступных целей в системе, выполнив:

systemctl list-unit-files --type=target

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

systemctl list-units --type=target

Изоляция целей

Есть возможность запускать все связанные с целью модули и останавливать модули, не входящие в дерево зависимостей. Нужная для этого команда называется соответственно isolate. Это схоже с изменением уровня запуска в других системах инициализации.

Например, если вы работаете в графическом окружении с активной graphical.target, вы можете выключить графическую систему и перевести ОС в многопользовательское состояние командной строки, изолировав multi-user.target. Так как graphical.target зависит от multi-user.target, но не наоборот, все графические модули будут остановлены.

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

systemctl list-dependencies multi-user.target

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

sudo systemctl isolate multi-user.target

Использование ярлыков для важных событий

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

Например, чтобы загрузиться в режим восстановления (однопользовательский), можно выполнить команду rescue вместо isolate rescue.target:

sudo systemctl rescue

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

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

sudo systemctl halt

Для инициализации полного отключения можно использовать команду poweroff:

sudo systemctl poweroff

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

sudo systemctl reboot

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

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

sudo reboot

Заключение

Теперь вы знакомы с некоторыми основными возможностями команды systemctl, которые позволят вам управлять вашей запущенной systemd. Программа systemctl будет вашим главным инструментом взаимодействия со службами и изменения состояния системы.
В то время как systemctl главным образом работает с основным процессом systemd, у последней есть и другие компоненты, управляемые другими программами. Другие возможности (например, управление журналами и сеансами пользователей) контролируются другими демонами и программами управления (journald/journalctl и logind/loginctl соответственно). С дополнительным изучением этих других инструментов управление станет более легким.

Источник: DigitalOcean