Понимание целей systemd: основные концепции
Поймите цели systemd, цели загрузки по умолчанию, сопоставления уровней выполнения, изоляцию, пользовательские цели и команды устранения неполадок.
Понимание целей systemd: основные концепции
Цели systemd легче понять, если перестать думать о них как о службах. Служба запускает процесс. Цель группирует модули в именованное состояние системы. Когда машина загружается в multi-user.target, systemd не запускает программу под названием "multi-user". Он пытается достичь состояния, в котором модули, требуемые этой целью, были запущены или, по крайней мере, были предприняты попытки их запуска.
Это различие помогает при отладке проблем с загрузкой. Если graphical.target работает медленно, сама цель редко является проблемой. Один из модулей отображения, входа в систему, сети, монтирования или приложения, включенных в эту цель, работает медленно или дает сбой. Цели дают вам карту.
Что такое цели systemd?
В экосистеме systemd цель — это особый тип файла модуля (например, файлы .service или .socket), который служит критической организационной цели. В отличие от модулей служб, которые определяют, как запустить или остановить конкретный процесс, модули целей определяют состояние системы или набор модулей, которые должны быть активны вместе. Они действуют как логические точки группировки и точки синхронизации для других модулей systemd.
Думайте о целях как о вехах в операционном пути системы. Когда systemd загружается, он не просто запускает список служб произвольно; он работает над достижением конкретной цели. Эта цель, в свою очередь, подтягивает все необходимые службы, сокеты, точки монтирования и другие цели, необходимые для достижения этого состояния. Такой подход, основанный на зависимостях, обеспечивает предсказуемый и эффективный процесс загрузки.
Для тех, кто знаком со старыми системами инициализации Linux, такими как SysVinit, цели systemd являются современным эквивалентом уровней выполнения. В то время как SysVinit имел фиксированный набор уровней выполнения (например, уровень выполнения 3 для многопользовательского текстового режима, уровень выполнения 5 для многопользовательского графического режима), цели systemd более гибкие. Они именованные, а не пронумерованные, и вы можете определять пользовательские цели, что обеспечивает большую детализацию и расширяемость.
Как работают цели: группировка и зависимости
Цели достигают своих возможностей группировки и определения состояния через явные зависимости, определенные в их файлах модулей. Основные директивы, используемые для этого: Wants=, Requires=, After= и Before=.
Wants=: Указывает "слабые" зависимости. Еслицель AWants=модуль B, systemd попытается запуститьмодуль Bпри активациицели A. Однакоцель Aвсе равно запустится, даже еслимодуль Bне запустится. Это обычно используется для группировки связанных служб, которые желательны, но не строго необходимы.Requires=: Указывает "сильные" зависимости. Еслицель ARequires=модуль B, томодуль Bдолжен быть успешно запущен для активациицели A. Еслимодуль Bвыйдет из строя,цель Aтакже выйдет из строя или не запустится. Это используется для критических зависимостей.After=: Определяет упорядочивающую зависимость. Еслицель AимеетAfter=модуль B, тоцель Aзапустится только после запускамодуля B. Это не подразумевает зависимости от успеха, только порядок.Before=: ОбратноеAfter=. Еслицель AимеетBefore=модуль B, томодуль Bзапустится только после запускацели A.Conflicts=: Гарантирует, что определенные модули не активны одновременно. Еслицель AConflicts=модуль B, то активацияцели Aостановитмодуль B, если он запущен, и наоборот.
Эти директивы позволяют целям действовать как надежные оркестраторы, подтягивая службы и другие цели по мере необходимости и определяя порядок их запуска. Например, multi-user.target обычно Wants= network.target и различные другие службы, гарантируя, что они активны, когда система достигает многопользовательского состояния.
Вы можете просмотреть содержимое файла модуля цели, чтобы увидеть его зависимости:
systemctl cat multi-user.target
Эта команда выведет содержимое файла модуля multi-user.target, показывая его Description, Documentation и, что важно, его директивы Wants=, Requires=, After= и другие, которые определяют, что составляет многопользовательское состояние.
Объяснение распространенных целей systemd
Systemd предоставляет множество предопределенных целей, каждая из которых соответствует определенному состоянию системы или функциональности. Понимание их имеет решающее значение для системного администрирования:
default.target: Это самая важная цель, так как она определяет состояние по умолчанию, в которое загрузится ваша система. Обычно это символическая ссылка наgraphical.target(для настольных компьютеров) илиmulti-user.target(для серверов).graphical.target: Эта цель обычно используется для систем с графической средой рабочего стола. Она подтягиваетmulti-user.target, а затем добавляет службы, необходимые для графического менеджера входа и сервера отображения (например, GDM, LightDM, Xorg, Wayland).multi-user.target: Это стандартное состояние для многопользовательских систем без графического интерфейса. Оно распространено для серверов и предоставляет все необходимые службы для доступа через командную строку, сеть и большинства операций демонов.basic.target: Минимальное состояние, которое включает основные системные службы, необходимые для фундаментальных операций, но доmulti-user.target. Обычно подтягиваетsysinit.targetи другие важные службы.sysinit.target: Эта цель достигается очень рано в процессе загрузки. Она отвечает за задачи базовой инициализации системы, такие как монтирование файловых систем/etc/fstab(за исключением удаленных), настройку подкачки и другие инициализации, связанные с оборудованием.local-fs.target: Гарантирует, что все локальные файловые системы, указанные в/etc/fstab, смонтированы.remote-fs.target: Гарантирует, что все удаленные файловые системы (например, NFS, CIFS), указанные в/etc/fstab, смонтированы.network.target: Указывает, что базовая сетевая связь доступна (например, сетевые интерфейсы подняты). Не гарантирует полного подключения к Интернету или назначения IP-адреса.network-online.target: Точка синхронизации для служб, которые хотят подождать, пока сетевой менеджер не сочтет сеть онлайн. Это не доказывает, что Интернет, DNS или удаленный API доступны, и работает только так, как ожидается, когда соответствующая служба ожидания подключения включена.rescue.target: Предоставляет однопользовательскую оболочку с минимальным набором запущенных служб и смонтированными локальными файловыми системами. Полезно для восстановления системы и устранения неполадок.emergency.target: Еще более минимальная среда, чемrescue.target. Предоставляет оболочку в корневой файловой системе, которая обычно монтируется только для чтения. Никакие другие службы не запускаются. Для критических аварийных ситуаций.poweroff.target,reboot.target,halt.target: Эти цели используются для выключения, перезагрузки или остановки системы соответственно. При активации они останавливают большинство служб и подготавливают систему к желаемому состоянию питания.
Управление целями systemd
Взаимодействие с целями systemd в основном включает утилиту командной строки systemctl.
Просмотр активных целей и целей по умолчанию
Чтобы узнать, в какой цели в данный момент работает ваша система:
systemctl get-default
Чтобы вывести список всех загруженных в данный момент модулей целей:
systemctl list-units --type=target
Эта команда показывает активные, загруженные и статические цели, а также их описания.
Изменение цели загрузки по умолчанию
Вы можете изменить цель, в которую ваша система загружается по умолчанию. Например, чтобы установить multi-user.target в качестве цели по умолчанию:
sudo systemctl set-default multi-user.target
Чтобы вернуться к graphical.target:
sudo systemctl set-default graphical.target
Эта команда создает символическую ссылку от /etc/systemd/system/default.target к нужному файлу цели.
Временная загрузка в другую цель
Иногда вам нужно загрузиться в определенную цель только один раз (например, для устранения неполадок). Вы можете добиться этого, добавив параметр ядра во время загрузки. Когда появится меню загрузки GRUB, отредактируйте запись загрузки (обычно нажав e) и добавьте systemd.unit=имя_цели.target в командную строку ядра.
Например, для загрузки в режим восстановления:
systemd.unit=rescue.target
Переключение целей во время выполнения
Вы можете переключиться на другую цель во время работы системы с помощью команды systemctl isolate. Эта команда остановит все службы, не требуемые новой целью, и запустит все службы, требуемые ею.
Предупреждение: Использование systemctl isolate может нарушить работу вашей системы, особенно если вы переключаетесь на цель гораздо более низкого уровня, например multi-user.target, из graphical.target на настольном компьютере. Используйте с осторожностью.
Чтобы переключиться с graphical.target на multi-user.target:
sudo systemctl isolate multi-user.target
Чтобы вернуться к graphical.target (предполагая, что это было предыдущее состояние):
sudo systemctl isolate graphical.target
Создание пользовательских целей
Хотя systemd предоставляет множество полезных целей, вы можете столкнуться с ситуациями, когда создание пользовательской цели будет полезным. Это особенно актуально для сложных развертываний приложений, где вам нужно сгруппировать несколько служб, которые всегда должны запускаться и останавливаться вместе, или определить конкретную среду для вашего приложения.
Чтобы создать пользовательскую цель:
- Создайте файл
.target: Поместите его в/etc/systemd/system/. Например,my-application.target.# /etc/systemd/system/my-application.target [Unit] Description=Моя пользовательская цель приложения Wants=my-database.service my-webserver.service After=my-database.service my-webserver.serviceDescription: Описание, понятное человеку.Wants=: Перечислите службы или другие цели, которые должна подтянуть эта цель.After=: Определите порядок. Цель запустится после этих модулей.
- Создайте службы: Убедитесь, что
my-database.serviceиmy-webserver.service(или любые другие перечисленные вами службы) существуют и правильно настроены. - Перезагрузите systemd: Сообщите systemd о новом файле модуля.
sudo systemctl daemon-reload
4. **Включите и запустите**: Теперь вы можете включить и запустить свою пользовательскую цель, что, в свою очередь, запустит ее требуемые службы. bash
sudo systemctl enable my-application.target
sudo systemctl start my-application.target
```
Это позволяет вам управлять группой связанных служб как единым логическим блоком, упрощая сложные развертывания приложений.
Уровни выполнения и цели без лишних слов
Если вы пришли из SysVinit, примерное сопоставление выглядит так:
| Старая идея уровня выполнения | Обычная цель systemd |
|---|---|
| Однопользовательский режим восстановления | rescue.target |
| Многопользовательский текстовый режим | multi-user.target |
| Многопользовательский графический режим | graphical.target |
| Перезагрузка | reboot.target |
| Выключение питания | poweroff.target |
Относитесь к этому как к вспомогательному средству перевода, а не как к идеальной модели. Уровни выполнения SysV были небольшим фиксированным набором пронумерованных состояний. Цели systemd — это именованные модули с зависимостями, и их может быть много. Пакет может установить свою собственную цель. Вы можете создать ее для рабочего процесса развертывания. Некоторые цели предназначены для изоляции; другие являются просто точками группировки, используемыми во время загрузки.
Вы можете увидеть, какие цели допускают изоляцию, с помощью:
systemctl show multi-user.target -p AllowIsolate
systemctl show basic.target -p AllowIsolate
Это важно, потому что systemctl isolate — это не безобидная команда "переключения вида". Она останавливает модули, которые не являются частью транзакции новой цели. На настольном компьютере изоляция multi-user.target обычно остановит графический сеанс. На удаленном сервере изоляция неправильной цели может остановить сетевые службы или службы входа и заблокировать вам доступ.
Как службы становятся частью цели
Большинство повседневных членств в целях происходит из раздела [Install] файла службы:
[Install]
WantedBy=multi-user.target
Когда вы запускаете:
sudo systemctl enable myapp.service
systemd создает символическую ссылку в каталоге, таком как:
/etc/systemd/system/multi-user.target.wants/myapp.service
Эта символическая ссылка заставляет multi-user.target хотеть эту службу во время загрузки. Файл службы может существовать и быть полностью действительным без включения. В этом случае запуск multi-user.target не подтянет его автоматически.
Вот почему systemctl start myapp.service и systemctl enable myapp.service решают разные проблемы. start запускает ее сейчас. enable подключает ее к будущей цели загрузки. enable --now делает и то, и другое.
Чтобы проверить, включена ли служба для цели:
systemctl is-enabled myapp.service
systemctl list-dependencies multi-user.target | grep myapp
Если служба запускается вручную, но не при загрузке, это одна из первых вещей, которые нужно проверить.
Небольшая пользовательская цель, которая действительно полезна
Пользовательские цели наиболее полезны, когда они дают операторам одну команду для группы связанных модулей. Представьте простой стек приложения:
app-api.service
app-worker.service
app-scheduler.service
Вы можете создать:
# /etc/systemd/system/app-stack.target
[Unit]
Description=Стек приложения
Wants=app-api.service app-worker.service app-scheduler.service
After=network-online.target
Wants=network-online.target
AllowIsolate=no
Затем добавьте каждую службу в цель:
[Install]
WantedBy=app-stack.target
После daemon-reload включите службы или цель в зависимости от желаемого поведения:
sudo systemctl daemon-reload
sudo systemctl enable app-api.service app-worker.service app-scheduler.service
sudo systemctl start app-stack.target
Это дает вам читаемую группировку, не притворяясь, что цель является супервизором процессов. Если app-worker.service выйдет из строя, проверьте эту службу. Цель — это просто точка группировки.
Если вы хотите, чтобы остановка цели останавливала все службы стека, добавьте PartOf=app-stack.target в каждую службу:
[Unit]
PartOf=app-stack.target
Теперь systemctl stop app-stack.target распространяется на службы-члены. Это часто недостающий элемент в примерах пользовательских целей.
Устранение неполадок с помощью целей
Цели также неоценимы для устранения неполадок загрузки или сбоев служб:
- Определение зависимостей: Если служба не запускается, проверка цели, к которой она принадлежит, может выявить отсутствующие или неисправные зависимости. Используйте
systemctl status <имя_службы>иsystemctl list-dependencies <имя_цели>. - Загрузка в минимальные цели: Если ваша система не загружается в
graphical.targetилиmulti-user.target, попробуйте загрузиться вrescue.targetилиemergency.target, используя метод параметра ядра. Это обеспечивает минимальную среду, в которой вы можете диагностировать проблемы без сложности множества запущенных служб. - Проверка журналов: После попытки запустить цель или службу всегда проверяйте журналы
journalctlна наличие ошибок:journalctl -b -u <имя_цели_или_службы>
Лучшие практики и советы
- Используйте
network-online.targetс осторожностью: Если вашей службе требуется сетевая конфигурация перед запуском, объединитеAfter=network-online.targetсWants=network-online.targetи убедитесь, что соответствующий модуль ожидания подключения включен. Все равно сохраняйте логику повторных попыток в приложении для удаленных зависимостей. - Понимайте порядок загрузки: Ознакомьтесь с общим потоком от
sysinit.targetдоbasic.target, затемmulti-user.target/graphical.target. Это помогает в отладке служб, которые выходят из строя на ранних этапах процесса загрузки. - Будьте осторожны с
default.target: Изменениеdefault.targetможет существенно изменить поведение загрузки вашей системы. Всегда сначала тестируйте пользовательские конфигурации в непроизводственной среде. - Используйте
Wants=для некритических зависимостей: Для служб, которые полезны, но не строго необходимы для того, чтобы цель считалась "поднятой", используйтеWants=вместоRequires=. Это предотвращает каскадный сбой одной необязательной службы и предотвращение активации всей цели.
Ментальная модель, которую нужно сохранить
Цель — это именованное состояние, а не демон. default.target определяет обычное место назначения загрузки. multi-user.target — это обычное состояние сервера. graphical.target добавляет стек отображения. rescue.target и emergency.target — это инструменты восстановления. Пользовательские цели — это инструменты группировки, когда они делают операции более понятными.
Когда что-то, связанное с целью, ломается, избегайте сначала обвинять цель. Спросите, какой модуль был подтянут, какое правило упорядочивания его задержало и какая зависимость не удалась. systemctl cat, systemctl list-dependencies, systemctl show и journalctl -b обычно ответят на эти вопросы быстрее, чем чтение общих диаграмм загрузки.