Systemd за пять минут
Наша компания занимается администрированием веб-серверов на базе CentOS. Довольно часто наши клиенты используют веб-приложения на базе python, ruby или java. Для автозапуска подобных приложений есть готовые шаблоны для написания стартап-скриптов. Но прогресс не стоит на месте, вышел уже второй релиз CentOS 7 и, следуя старой традиции «не ставить dot-zero релизы на продакшен», мы начинаем предлагать клиентам сервера на базе CentOS 7.1 (1503).
В CentOS7, так же как и в его родителе RHEL7, используется systemd — менеджер системы и служб для Linux, совместимый со скриптами инициализации SysV и LSB. systemd обеспечивает возможности агрессивной параллелизации и много всего прочего.
Огромный монстр с множеством возможностей, гибкими настройками и мегабайтами документации…
Но что делать, если стоит задача быстро-быстро, вот прямо вчера, сделать автозапуск некоего сервиса?
Давайте выжмем из документации минимально необходимый набор информации для создания простых старт-стоп скриптов.
Systemd запускает сервисы описанные в его конфигурации.
Конфигурация состоит из множества файлов, которые по-модному называют юнитами.
Все эти юниты разложены в трех каталогах:
/usr/lib/systemd/system/ – юниты из установленных пакетов RPM — всякие nginx, apache, mysql и прочее
/run/systemd/system/ — юниты, созданные в рантайме — тоже, наверное, нужная штука
/etc/systemd/system/ — юниты, созданные системным администратором — а вот сюда мы и положим свой юнит.
[Название секции в квадратных скобках]
имя_переменной = значение
Для создания простейшего юнита надо описать три секции: [Unit], [Service], [Install]
В секции Unit описываем, что это за юнит:
Названия переменных достаточно говорящие:
Далее следует блок переменных, которые влияют на порядок загрузки сервисов:
Запускать юнит после какого-либо сервиса или группы сервисов (например network.target):
After=syslog.target
After=network.target
After=nginx.service
After=mysql.service
В итоге переменная Wants получается чисто описательной.
Если сервис есть в Requires, но нет в After, то наш сервис будет запущен параллельно с требуемым сервисом, а не после успешной загрузки требуемого сервиса
В секции Service указываем какими командами и под каким пользователем надо запускать сервис:
(по умолчанию): systemd предполагает, что служба будет запущена незамедлительно. Процесс при этом не должен разветвляться. Не используйте этот тип, если другие службы зависят от очередности при запуске данной службы.
systemd предполагает, что служба запускается однократно и процесс разветвляется с завершением родительского процесса. Данный тип используется для запуска классических демонов.
Также следует определить PIDFile=, чтобы systemd могла отслеживать основной процесс:
Команды на старт/стоп и релоад сервиса
Тут есть тонкость — systemd настаивает, чтобы команда указывала на конкретный исполняемый файл. Надо указывать полный путь.
Таймаут в секундах, сколько ждать system отработки старт/стоп команд.
Попросим systemd автоматически рестартовать наш сервис, если он вдруг перестанет работать.
Контроль ведется по наличию процесса из PID файла
В секции [Install] опишем, в каком уровне запуска должен стартовать сервис
multi-user.target или runlevel3.target соответствует нашему привычному runlevel=3 «Многопользовательский режим без графики. Пользователи, как правило, входят в систему при помощи множества консолей или через сеть»
Вот и готов простейший стартап скрипт, он же unit для systemd:
myunit.service
Кладем этот файл в каталог /etc/systemd/system/
Смотрим его статус systemctl status myunit
Если нет никаких ошибок в юните — то вывод будет вот такой:
systemd (Русский)
systemd — набор базовых строительных кирпичиков Linux-системы. Представляет собой менеджер системы и служб, который выполняется как процесс с PID 1 и запускает остальную часть системы. systemd обеспечивает возможности агрессивной параллелизации, сокет- и D-Bus-активацию для запуска служб, запуск демонов по запросу, отслеживание процессов с помощью контрольных групп Linux, обслуживание точек (авто)монтирования, а также предлагает развитую транзакционную логику управления службами на основе зависимостей. systemd поддерживает сценарии инициализации SysV и LSB и работает как замена sysvinit. Среди прочих элементов и функций — демон журнала, утилиты управления базовой конфигурацией системы (имя хоста, дата, языковой стандарт), ведение списков вошедших в систему пользователей, запущенных контейнеров, виртуальных машин, системных учётных записей, каталогов и настроек времени выполнения, а также демоны для управления несложными сетевыми конфигурациями, синхронизации времени по сети, пересылки журналов и разрешения имён.
Contents
Основы использования systemctl
Использование юнитов
Юнитами могут быть, например, службы (.service), точки монтирования (.mount), устройства (.device) или сокеты (.socket).
Управление питанием
Для управления питанием от имени непривилегированного пользователя необходим polkit. Если вы находитесь в локальном пользовательском сеансе systemd-logind и нет других активных сеансов, приведенные ниже команды сработают, даже если будут выполнены не от root. В противном случае (например, другой пользователь вошел в систему через tty) systemd автоматически запросит у вас пароль суперпользователя.
| Действие | Команда |
|---|---|
| Завершить работу и перезагрузить систему | $ systemctl reboot |
| Завершить работу и выключить компьютер | $ systemctl poweroff |
| Перевести систему в ждущий режим | $ systemctl suspend |
| Перевести систему в спящий режим | $ systemctl hibernate |
| Перевести систему в режим гибридного сна (suspend-to-both) | $ systemctl hybrid-sleep |
Написание файлов юнитов
Обработка зависимостей
Зависимости обычно указываются для служб, но не для целей. Так, цель network.target будет «подтянута» ещё на этапе настройки сетевых интерфейсов одной из соответствующих служб, и можно спокойно указывать эту цель как зависимость в пользовательской службе, поскольку network.target будет запущена в любом случае.
Типы служб
Службы различаются по типу запуска, и это следует учитывать при написании юнитов. Тип определяется параметром Type= в разделе [Service] :
Редактирование файлов юнитов
Замещение файла юнита
Эта команда откроет файл /etc/systemd/system/юнит в текстовом редакторе (если файл ещё не существует, будет скопирован оригинал) и автоматически перезагрузит юнит после завершения редактирования.
Drop-in файлы
Самый простой способ — использовать команду:
Команда откроет /etc/systemd/system/юнит.d/override.conf в текстовом редакторе (файл будет создан, если его ещё нет) и автоматически перезапустит юнит после завершения редактирования.
Откат изменений
Примеры
Например, если вы просто хотите добавить дополнительную зависимость к юниту, можно создать следующий файл:
Другой пример: для замены ExecStart в юните (кроме типа oneshot ) создайте следующий файл:
Обратите внимание, что ExecStart необходимо очистить перед присвоением нового значения [1]. Это относится ко всем параметрам, которые позволяют прописать несколько значений, вроде OnCalendar в таймерах.
Пример настройки автоматического перезапуска службы:
Получение информации о текущих целях
В systemd для этого предназначена следующая команда (заменяющая runlevel ):
Создание пользовательской цели
Соответствие уровней SysV целям systemd
| Уровнень запуска SysV | Цель systemd | Примечания |
|---|---|---|
| 0 | runlevel0.target, poweroff.target | Выключение системы |
| 1, s, single | runlevel1.target, rescue.target | Однопользовательский уровень запуска |
| 2, 4 | runlevel2.target, runlevel4.target, multi-user.target | Уровни запуска, определенные пользователем/специфичные для узла. По умолчанию соответствует уровню запуска 3 |
| 3 | runlevel3.target, multi-user.target | Многопользовательский режим без графики. Пользователи, как правило, входят в систему при помощи множества консолей или через сеть |
| 5 | runlevel5.target, graphical.target | Многопользовательский режим с графикой. Обычно эквивалентен запуску всех служб на уровне 3 и графического менеджера входа в систему |
| 6 | runlevel6.target, reboot.target | Перезагрузка |
| emergency | emergency.target | Аварийная оболочка |
Изменение текущей цели
В systemd цели доступны посредством целевых юнитов. Вы можете переключать их такой командой:
Изменение цели загрузки по умолчанию
Узнать текущую цель можно так:
Альтернативный способ — добавить один из следующих параметров ядра в загрузчик:
Порядок выбора цели по умолчанию
systemd выбирает default.target в следующем порядке :
Компоненты systemd
Некоторые (не все) составные части systemd:
systemd.mount — монтирование
Примером этих опций может быть т.н. автомонтирование (здесь имеется в виду не автоматическое монтирование во время загрузки, а монтирование при появлении запроса от устройства). Подробнее смотрите fstab#Автоматическое монтирование с systemd.
Автомонтирование GPT-раздела
На UEFI-системах systemd-gpt-auto-generator(8) автоматически монтирует GPT-разделы в соответствии с Discoverable Partitions Specification, поэтому их можно не указывать в файле fstab.
Для автомонтирования раздела /var его PARTUUID должен совпадать с хэш-суммой SHA256 HMAC, вычисленной на основании UUID типа раздела. В качестве ключа хэша используется machine ID. Необходимый PARTUUID можно получить командой:
systemd-sysvcompat
systemd-tmpfiles — временные файлы
Советы и рекомендации
Программы настройки с графическим интерфейсом
Запуск сервисов после подключения к сети
Чтобы запустить сервис только после подключения к сети, добавьте такие зависимости в .service файле:
Также должна быть включена служба ожидания сети того приложения, которое управляет сетью; только тогда network-online.target будет соответствовать состоянию сети.
Подробнее можно почитать в systemd wiki: Running services after the network is up.
Если служба отправляет DNS-запросы, она должна запускаться также после nss-lookup.target :
Чтобы цель nss-lookup.target работала как положено, должна быть служба, которая запускает её параметром Wants=nss-lookup.target и размещает себя перед ней ( Before=nss-lookup.target ). Обычно это выполняет локальный DNS-распознаватель.
Включение установленных юнитов по умолчанию

Песочница для приложений
Рекомендации по созданию песочницы с помощью systemd:
Уведомление о неработающих службах
Создайте drop-in верхнего уровня:
Это добавит строку OnFailure=failure-notification@%n в файл каждой службы. Если какой-то_юнит завершится с ошибкой, запустится экземпляр службы failure-notification@какой-то_юнит для создания уведомления (или любой другой задачи, которая была назначена).
Создайте юнит-шаблон failure-notification@ :
Решение проблем
Неудачно запущенные службы
Следующая команда найдёт все службы, которые не смогли выполнить запуск:
Чтобы определить причину, по которой служба не запустилась, необходимо изучить записи её логов. Подробнее см. systemd/Журнал#Фильтрация вывода.
Диагностика загрузки системы
В systemd есть несколько опций для диагностики проблем процесса загрузки. В статье об отладке загрузки описано, как получить доступ к сообщениям, выданным процессом загрузки до того, как systemd перехватил управление. Также смотрите документацию по отладке systemd.
Диагностика службы
Добавьте drop-in файл для службы:
Или, как вариант, пропишите переменную окружения вручную:
Выключение/перезагрузка происходят ужасно долго
Если процесс выключения занимает очень долгое время (или выглядит зависшим), то, вероятно, виновата служба, которая не может завершить свою работу. Systemd ожидает некоторое время, пока каждая служба прекратит работу самостоятельно, и только потом пробует завершить её принудительно. Если вы столкнулись с такой проблемой, обратитесь к Shutdown completes eventually в systemd-вики.
По-видимому, процессы с кратким сроком жизни не оставляют записей в логах
Время загрузки системы увеличивается с течением времени
После использования systemd-analyze некоторые пользователи заметили, что время загрузки системы значительно увеличилось. После использования systemd-analyze blame NetworkManager запускался необычно долго.
systemd-tmpfiles-setup.service не запускается во время загрузки
Начиная с версии Systemd 219, /usr/lib/tmpfiles.d/systemd.conf определяет ACL-атрибуты для каталогов в /var/log/journal и, следовательно, требует включённой поддержки ACL для той файловой системы, в которой находится журнал.
Отключение emergency mode на удалённой машине
Вам может понадобиться отключить emergency mode на удалённой машине, например на виртуальных машинах Azure или Google Cloud. Это связано с тем, что в случае ухода системы в emergency mode она отключится от сети и лишит вас возможности подключения к ней.
SDB:Systemd
Содержание
systemd запускает и контролирует все системные службы. В ее основе лежит понятие «единиц» (units), которые связаны между собой и имеют определенное имя и тип с соответствующими конфигурационными файлами, т. е. это файлы конфигурации хранящие информацию о сервисе, сокете, устройстве и т. д. Каждая единица может требовать другие единицы (Requires), конфликтовать с ними (Conflicts), запускаться до (After) или после (Before) определенной единицы.
Существуют следующие виды единиц:
Концепция systemd по сути схожа с уровнями выполнения (runlevel), но работающая немного по другому. Systemd использует понятие «целей» (target), каждая из которых имеет определенное имя и назначение, с возможностью одновременной работы с несколькими из них, например, для того, чтобы выяснить текущий уровень выполнения нужно выполнить:
| Уровень загрузки SysV | Цель systemd | Описание |
|---|---|---|
| 0 | runlevel0.target, poweroff.target | Остановка системы |
| 1, s, single | runlevel1.target, rescue.target | Однопользовательский режим (single user mode). Базовая система сконфигурирована, но демоны не запущены. |
| 2 | runlevel2.target, multi-user.target | Пользовательский/Специфический уровень. Сконфигурирован также как уровень выполнения 3, но без поддержки сети |
| 3 | runlevel3.target, multi-user.target | Многопользовательский режим (multiuser mode) с поддержкой сети |
| 4 | runlevel4.target, multi-user.target | Не используется |
| 5 | runlevel5.target, graphical.target | Многопользовательский графический режим с поддержкой сети |
| 6 | runlevel6.target, reboot.target | Перезагрузка системы |
| emergency | emergency.target | Аварийный режим, который является аналогом 1-го уровня |
Как уже отмечалось выше, в systemd уровни выполнения доступны через «целевые единицы«. Сменить текущий уровень выполнения можно с помощью следующей команды:
Заметьте, что понятие уровней загрузки (runlevel) устарело, и, как правило, лучше воспользоваться современным именем, например:
Для изменения уровня загрузки по умолчанию, используйте символические ссылки или systemctl, например:
Метод изменения уровня загрузки с помощью systemctl возможен только, если целевой файл конфигурации содержит следующие строки:
В настоящий момент вышеприведенные строки присутствуют в нескольких файлах (целевых единиц): multi-user.target, graphical.target.
systemctl — централизованное средство управления службами (и не только) являющееся основным инструментом. При использовании systemctl всегда необходимо указывать полное имя файла (единицы), в том числе суффикс (например, bluetooth.target). Далее приводится ряд наиболее часто используемых команд. Для просмотра дополнительных опций обратитесь к странице руководства man systemctl.
Просмотр списка запущенных единиц:
Просмотр списка единиц, запуск которых завершился неудачей:
Просмотр списка активных служб:
Запуск, остановка и перезапуск служб:
Перезагрузка конфигурации без перезапуска службы:
Текущее состояние службы:
Проверка, будет ли запущена служба при загрузке системы:
Включение/отключение автоматического запуска службы при загрузке системы, соответственно:
Сообщить systemd об изменении конфигурации, т.е. перечитать конфигурацию:
Зависимости необходимые единице, например, для целевой единицы multi-user.target:
cgroups — это контрольные группы распределяющие между процессами ресурсы и позволяющие осуществлять контроль, приоритизацию и управление системными ресурсами. Контрольные группы организованы иерархически, где каждый процесс помещается в группу с именем родителя, породивший этот процесс. Это позволяет установить точное происхождение определенного процесса.
systemd-cgls — это утилита, позволяющая наглядно оценить принадлежность группы процессов к их службам или процессов вошедших в сеанс пользователя с помощью регистрации пользовательских сессий (pam_systemd)
Подробности о службах, процессах и управления ресурсами Вы можете узнать здесь
systemd-analyze — это инструмент помогающий найти виновников медленной загрузки системы.
Для просмотра суммарного времени загрузки:
Для получения древовидного списка профилирования единиц (выявления медленных по времени):
Чтобы получить список активированных при загрузке единиц systemd, отсортированных по времени для каждой из них, выполните:
Для наглядности параллелизации служб воспользуйтесь графической диаграммой:
Более подробную информацию о виновниках медленной загрузки можно найти здесь.
Присутствие systemd-journalctl позволяет также просматривать последние сообщения журнала для определенной службы, например:
Структурирование отображаемой информации журнала обеспечивается параметрами в формате «переменная=значение«, например, для просмотра всех сообщений от конкретной единицы выполните:
Более подробную информацию о параметрах запуска systemd-journalctl, а также переменных Вы можете узнать из страницы руководства man systemd-journalctl, systemd.journal-fields.
Как загрузиться в другой уровень выполнения?
По умолчанию при загрузке systemd активизирует целевую единицу default.target, работа которой заключается в загрузке служб и других единиц c учетом зависимостей. Эту цель по умолчанию можно изменить, добавив в командной строке ядра (параметры загрузки в меню GRUB Legacy или в строке ядра для GRUB 2) опцию systemd.unit= Это может быть использовано для однократной загрузки системы, например, чтобы загрузиться в 3-ий уровень выполнения (согласно классической системе инициализации), добавьте следующее:
Как настроить автоматический вход в систему на виртуальной консоли?
Создайте новый сервис аналогичный getty@.service:
Отредактируйте следующие строки файла autologin@.service, например:
Перезапустите конфигурацию менеджера systemd и запустите службу:
Обратите внимание, что если Вы выйдите с tty8 сессии, то не сможете использовать ее до следующей перезагрузки или ручного запуска, systemctl, за исключением, автоматической перезагрузки упавшей службы «Restart=always».
Как изменить количество работающих по умолчанию getty?
Создайте символическую ссылку на другой экземпляр getty в каталоге getty.target.wants/ :
Для удаления getty, избавьтесь от символических ссылок, которые по Вашему мнению не нужны, например:
Обратите внимание, что по умолчанию запускается только один getty-процесс, но при этом Вы можете запускать дополнительные процессы agetty, переключаясь на другой терминал вручную. Если же Вы хотите запретить переход на неиспользуемые по умолчанию терминалы, тогда раскомментируйте строку NautoVTs= файла /etc/systemd/systemd-logind.conf и укажите значение равное 0. Более подробную информацию о конфигурации менеджера входа в систему можно найти на странице руководства (man systemd-logind.conf).
Как заставить работать консоль на последовательном порту?
Как автоматически запустить службу на определенном уровне выполнения?
Создайте символические ссылки файла службы в необходимых каталогах, например, чтобы запустить службу foobar.service на 3-ем уровне выполнения (будет соответствовать каталогу multi-user.target.wants/ ):
Какой файл для запуска службы имеет более высокий приоритет, systemd или SysV?
Если в системе присутствуют два файла для запуска службы, например, /usr /lib/systemd/system/foobar.service против /etc/init.d/foobar и оба файла доступны системе, то файл службы systemd имеет более высокий приоритет, чем SysV сценарий, при этом сам SysV сценарий игнорируются, независимо от того, как включается или отключается определенная служба. Обратите внимание, что запуская SysV сценарий, происходит автоматическое перенаправление (redirecting to systemctl).
Как изменить файл службы, который перезаписывается при обновления rpm пакета?
Как выключить машину?
Вы можете использовать следующую команду:
Для остановки системы, не выключая питания, воспользуйтесь:
Если Вы находитесь в сессии локального пользователя и при этом никакого другого активного сеанса нет, то вышеприведенные команды будут работать без привилегий суперпользователя.
Как вернуть классическую систему инициализации SysV?
Нижеприведенные действия могут быть необходимы в openSUSE 12.2/12.1, где systemd используется по умолчанию.
Воспользуйтесь одним из нижеприведенных действий:
Документация
С полной документацией openSUSE о systemd можно ознакомиться перейди по этой ссылке.
![]() | Эта статья содержит фрагменты на иностранном языке. Вы можете помочь переведя её до конца. (cм. руководство по переводу) |
Services not starting as expected
Even though chkconfig cron shows that cron should be enabled, it seems not to be started after boot. systemctl start cron.service starts it just fine. See Bug #660493.
systemctl enable cron.service helps here.
Цикличное монтирование (loop mounts) не работает без ручной загрузки модуля «loop»
См. Bug #661715. With SysV init, the loop module was unconditionally loaded by /etc/init.d/boot.localfs which is not used anymore. Для активации автоматичекской загрузки этого модуля выполните:
Отладка в systemd
To get debug from systemd, you can either :
serial console isn’t working
By default, systemd starts a minimal set of getty to let the system accessible.
When specifying on kernel command line which serial console should be used, only the last one in the list (which define the «active» console), will get a getty started :
Выполните для принудительного запуска консоли на последовательном порту:
Диагностика проблем загрузки
Если Ваша система при загрузке зависает, то сначала проверьте, проблема возникает до или после того, как управление предается systemd. Попробуйте загрузиться, удалив quiet в командной строке ядра. Это можно сделать в то время, когда отображается заставка меню grub: Esc → e → Выберите строку «kernel» → e → Удалите quiet и приведите к виду фрагмент «splash=verbose» → Enter → b.
Если при загрузке Вы увидите строки, подобные этим:
значит systemd работает.
Если же Вы не можете войти ни в одну из виртуальных консолей, тогда попробуйте войти через => 5 мин. Существует вероятность того, что проблемные службы будут остановлены после этого тайм-аута и загрузка продолжится.
Вывод информации на последовательной консоли
Если у Вас есть устройство, доступное через последовательную консоль, то для отладки загрузитесь со следующими параметрами:
Загрузка в однопользовательский или аварийный режим
Чтобы загрузиться в режиме одного пользователя, Вам необходимо добавить в командной строке ядра systemd.unit=rescue.target или 1. Этот режим может быть полезен в том случае, если проблема возникает где-то после загрузки базовой система, во время загрузки служб. Если это так, то здесь Вы можете отключить проблемную службу. В случае, если Вы не можете загрузиться в режиме одного пользователя, попробуйте загрузиться в систему с минимальным окружением (аварийный режим).
Заблаговременная оболочка (shell)
У Вас есть доступ к оболочке (shell)
Если systemd работает в той степени, что может предоставить Вам оболочку, то для того, чтобы извлечь полезную информацию для отладки, Вам необходимо добавить в командной строке ядра следующие параметры:
После загрузки оболочки сохраните буфер сообщений ядра в файл:
Для проверки списка зависших служб, которые могут быть виновниками остановки процесса загрузки и завершения работы системы, выполните:
Диагностика проблемы Shutdown
Так же, как с проблемами загрузки, когда Вы сталкиваетесь с зависанием, убедитесь в том, что прошло не менее 5 мин., чтобы отличить постоянные зависания от поломки системы. После этого попробуйте, реагирует ли система на комбинацию клавиш Ctrl+Alt+Del. Если перезагрузка/выключение Вашей системы надолго зависает, то в качестве теста исправности ядра можно перезагрузить или выключить систему принудительно с помощью одной из следующих команд:
Если ни одна из команд не работает, то это ошибка ядра, а не systemd.
Shutdown долго завершается
Shutdown никогда не завершается
Если перезагрузка/отключение не завершается, даже после ожидания нескольких минут, то для закрытия ведения лога, описанного выше, необходимо воспользоваться одним из двух нижеприведенных методов:
Файл конфигурации systemd
Для увеличения детализации сообщений systemd необходимо раскомментировать следующие строки файла /etc/systemd/system.conf :
Подробности о возможных аргументах Вы можете узнать из страницы руководства man systemd.
