Где мне разместить файл юнита systemd?

Вопрос или проблема

Я прочитал, что существуют две папки для файлов юнитов (не в пользовательском режиме).

/usr/lib/systemd/system/: юниты, предоставляемые установленными пакетами
/etc/systemd/system/: юниты, установленные системным администратором

Этому пониманию противоречит ответ на этот вопрос: Как написать скрипт запуска для Systemd. Может кто-нибудь заполнить недостающую информацию, чтобы я понял, что происходит? (ОБНОВЛЕНИЕ: Ответ был обновлен, и мое понимание больше не противоречит ему.)

Также кажется, что скрипты организованы в подпапки в папке /etc/systemd/system/:

getty.target.wants
multi-user.target.wants

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

/usr/lib/systemd/user/, куда отправляются сервисы, предоставляемые установленными пакетами.
/etc/systemd/user/ куда системные адмнины кладут сервисы для всех пользователей.
~/.config/systemd/user/, куда пользователь кладет свои собственные сервисы.

Обновление от 2015-08-31:

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

Лучшее место для размещения системных файлов юнитов: /etc/systemd/system
Просто убедитесь, что добавили таргет в секции [Install], для подробностей читайте “Как это знает?”. ОБНОВЛЕНИЕ: /usr/local/lib/systemd/system — это другой вариант, читайте “Серая зона” для подробностей.

Лучшее место для размещения пользовательских файлов юнитов: /etc/systemd/user или $HOME/.config/systemd/user,
но это зависит от разрешений и ситуации. Обратите внимание, что пользовательские сервисы будут запускаться только тогда, когда пользователь зарегистрирован, если только вы не включите их явным образом для запуска при загрузке с помощью loginctl enable-linger <username>. “linger” означает продолжать после выхода, но также запускаться при загрузке. В режиме linger при загрузке создается пользовательский менеджер, который сохраняется за пределами жизненного цикла пользовательской сессии.

На самом деле, юниты systemd (или, как их называют в первой фразе, “конфигурации юнитов”) могут находиться где угодно — при условии, что вы готовы создавать символические ссылки вручную и учитываете все предостережения. Удобнее всего размещать юнит там, где его сможет найти systemctl daemon-reload по ряду причин:

  • Использование стандартного расположения означает, что генераторы systemd их находят и их легко можно включить при загрузке с помощью systemctl enable. Это происходит потому, что ваш юнит будет автоматически добавлен в дерево зависимостей юнитов (кэш юнитов).
  • Нет необходимости думать о разрешениях, потому что в специально отведенные области могут писать только пользователи с правами администратора.

Как это знает?

И как же systemctl enable знает, где создать символическую ссылку? Вы жестко указываете это внутри
самого юнита под секцией [install]. Обычно присутствует строка, подобная этой

[Install]
WantedBy = multi-user.target

которая соответствует заранее определенному месту в файловой системе.
Таким образом, systemctl знает, что этот юнит зависит от группы файлов юнитов, называемой multi-user.target (“таргет” — это термин, используемый для обозначения групп зависимостей юнитов. Вы можете перечислить все группы с помощью systemctl list-units --type target). Группа файлов юнитов для загрузки с таргетом помещается в директорию targetname.target.wants. Это просто директория, полная символических ссылок (или реальных файлов). Если ваша секция [Install] указывает, что она WantedBy для multi-user.target, но если символическая ссылка на нее не существует в директории multi-user.target.wants, она не будет загружена. Когда генераторы юнитов systemd добавляют ваш файл юнита в кэш дерева зависимостей при загрузке (вы можете вручную запустить генераторы с помощью systemctl daemon-reload), он автоматически узнает, где разместить символическую ссылку — в данном случае в директории /etc/systemd/system/multi-user.target.wants/, если вы ее включите.

Ключевые моменты в руководстве:

Дополнительные юниты могут быть загружены в systemd (“связаны”) из
каталогов, не входящих в путь загрузки юнитов. См. команду link в systemctl(1).

Под systemctl, ищите Команды работы с файлами юнитов

Путь загрузки файлов юнитов

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

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

Когда переменная $SYSTEMD_UNIT_PATH установлена, содержимое этой переменной переопределяет путь загрузки юнитов. Если $SYSTEMD_UNIT_PATH заканчивается пустым компонентом (“:”), обычный путь загрузки юнитов будет добавлен к содержимому переменной.

Таблица 1 и Таблица 2 из man systemd.unit хороши.

Пути загрузки при работе в системном режиме (--system).

  • /etc/systemd/system Локальная конфигурация
  • /run/systemd/system Временные юниты
  • /usr/lib/systemd/system Юниты установленных пакетов (или /lib/systemd/system в некоторых случаях, читайте man systemd.unit)

Путь загрузки при работе в пользовательском режиме (--user)

Есть разница между пользовательскими юнитами и всеми/глобальными пользовательскими юнитами.

Зависимые от пользователя

  • $XDG_CONFIG_HOME/systemd/user Конфигурация пользователя (используется только, если $XDG_CONFIG_HOME установлен)

  • $HOME/.config/systemd/user Конфигурация пользователя (используется только, если $XDG_CONFIG_HOME не установлен)

  • $XDG_RUNTIME_DIR/systemd/user Временные юниты (используется только, если $XDG_RUNTIME_DIR установлен)

  • $XDG_DATA_HOME/systemd/user Юниты пакетов, установленных в домашней директории (используется только, если $XDG_DATA_HOME установлен)

  • $HOME/.local/share/systemd/user Юниты пакетов, установленных в домашней директории (используется только, если $XDG_DATA_HOME не установлен)

--global (все пользователи)

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

  • /etc/systemd/user Локальная конфигурация для всех пользователей (systemctl --global enable userunit.service)
  • /usr/lib/systemd/user Юниты пакетов, установленных на уровне всей системы для всех пользователей (или /lib/systemd/system в некоторых случаях, читайте man systemd.unit)
  • /run/systemd/user Временные юниты

Серая зона

С одной стороны, Стандарт иерархии файлов (также man file-hierarchy) указывает, что /etc предназначен для локальных конфигураций, которые не выполняют бинарные файлы. С другой стороны
он указывает, что /usr/local/ “предназначен для использования системным администратором при установке программного обеспечения локально”. Вы также можете утверждать (если не просто для целей организации), что все файлы системных юнитов должны находиться в /usr/local/lib/systemd/system, но это предназначено для файлов юнитов, которые являются частью “программного обеспечения”, не установленного через диспетчер пакетов.
Соответствующие юниты systemd для пользователей на уровне всей системы могут находиться в
/usr/local/lib/systemd/user.

Транзитный юнит

Еще одно забытое место — это вообще нигде! Возможно, менее известная программа – systemd-run. Вы можете использовать ее для запуска временных юнитов на лету. см. man systemd-run.

Например, чтобы запланировать перезагрузку завтра утром в 4:00 (может потребоваться --force для обеспечения перезагрузки):

systemd-run -u restart --description="Перезагрузка машины" --on-calendar="2020-12-18 04:00:00" systemctl --force reboot

Это создаст временный файл юнита restart.service и соответствующий таймер (из-за --on-calendar, и указано transient=yes в определении временного юнита).

/run/systemd/transient/restart.service

# Это временный файл юнита, созданный программно через API systemd. Не редактируйте.
[Unit]
Description=Перезагрузка машины

[Service]
ExecStart=
ExecStart="/usr/bin/systemctl" "--force" "reboot"

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

/etc/systemd/system — это место, куда вы кладете свои скрипты, pacman кладет пакетные скрипты в /usr/lib/systemd/system.

Выполнение команды systemctl enable foo.service создает символические ссылки из /usr в /etc. Смотрите секцию Unit Load Path в man systemd.unit(5) для получения более детальной информации.

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

Используя команду systemd-analyze:

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

Это места, куда вы можете поместить свои пользовательские конфигурации

systemd-analyze --user unit-paths

Пример вывода

/home/username/.config/systemd/user
/etc/systemd/user
/run/systemd/user
/run/user/1000/systemd/generator
/home/username/.local/share/systemd/user
/home/username/.local/share/flatpak/exports/share/systemd/user

Для административных пользователей вы можете предпочесть размещать ваши конфигурации в следующих папках (они будут влиять на всех пользователей):

systemd-analyze --global unit-paths

Пример вывода

/etc/systemd/user
/run/systemd/user
/usr/local/share/systemd/user
/usr/share/systemd/user
/usr/local/lib/systemd/user
/usr/lib/systemd/user

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

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

systemd-analyze --system unit-paths

Пример вывода

/etc/systemd/system
/run/systemd/system
/run/systemd/generator
/usr/local/lib/systemd/system
/usr/lib/systemd/system

Смотрите: страница руководства

Одно заметное различие между /etc/systemd/system и /lib/systemd/system на системах Debian/Ubuntu заключается в том, что файлы сервисов под /lib/systemd/system могут быть замаскированы, в то время как файлы под /etc/systemd/system не могут. Например,

# ls /lib/systemd/system/mytest.service
# systemctl mask mytest
# ls /etc/systemd/system/mytest2.service
# systemctl mask mytest2
Не удалось замаскировать юнит: Файл /etc/systemd/system/mytest2.service уже существует.

Поисковые пути

Существует множество мест, где systemd ищет, когда вы выполняете systemctl enable <unit-name>. Независимо от того, где они найдены, они будут символически связаны с чем-то внутри /etc/systemd.

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

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

Область видимости как пользовательская, глобальная и системная.

Выбор папки

Например, если вы разместите свои файлы юнитов в ~/.config/systemd/user.control, вам нужно будет включить их с помощью systemctl enable --user <unit-file>.

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

pkg-config systemd --variable=systemdsystemconfdir
pkg-config systemd --variable=systemduserunitdir
pkg-config systemd --variable=systemduserconfdir

На моей системе эти команды вернули в порядке:

/etc/systemd/system
/usr/lib/systemd/user
/etc/systemd/user

Я написал 3 файла, один для ntpd, один для второго, статического сетевого интерфейса, и один для запуска p0f, пассивного идентификатора ОС. Я разместил их все в /etc/systemd/system. Похоже, я мог бы, возможно, позволить systemd управлять NTP, но я не думаю, что хочу полагаться на это настолько.

.

Ответ или решение

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

Теория

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

Юнит-файлы могут располагаться в следующих директориях:

  1. /usr/lib/systemd/system: Этот каталог содержит юнит-файлы, предоставляемые пакетами программного обеспечения. Это значит, что данные файлы являются частью программного обеспечения, установленного через пакетный менеджер. Изменения в этих файлах могут быть переписаны при обновлении пакета.

  2. /etc/systemd/system: Это место хранения предназначено для юнит-файлов, создаваемых и модифицируемых системным администратором. Может быть использовано для установки пользовательских настроек, таких как переопределение параметров юнитов из /usr/lib/systemd/system.

  3. /usr/local/lib/systemd/system: Предназначен для юнит-файлов программного обеспечения, установленного вручную (в обход пакетного менеджера). Это место хранения, как правило, находится под контролем системного администратора.

  4. Пути для пользовательских юнитов: Для юнит-файлов, исполняемых от пользователя (а не от системы), используются каталоги типа /etc/systemd/user и ~/.config/systemd/user.

Пример

Предположим, вы создаете юнит для скрипта, который нужно запускать при старте системы. Основной вопрос — где его разместить? Официальная документация и практика подсказывают, что для системных юнитов, управление которыми вы хотите осуществлять вручную, логичнее всего использовать директорию /etc/systemd/system. В этом случае вы можете быть уверены, что ваши изменения не будут перезаписаны при обновлениях системы.

Применение

Рассмотрим на практике, как можно разместить свой системный юнит-файл.

  1. Создание юнит-файла. Создайте файл myscript.service в /etc/systemd/system:

    [Unit]
    Description=My Custom Script
    
    [Service]
    ExecStart=/usr/local/bin/myscript.sh
    
    [Install]
    WantedBy=multi-user.target
  2. Перезагрузка конфигурации systemd. После добавления юнит-файла выполните:

    systemctl daemon-reload
  3. Активация и запуск юнита. Далее активируйте и запустите ваш юнит:

    systemctl enable myscript.service
    systemctl start myscript.service
  4. Проверка статуса. Убедитесь, что сервис работает:

    systemctl status myscript.service

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

Использование правильной директории для ваших юнитов упрощает их управление, делает их независимыми от механизма обновлений пакетов, а также предоставляет вам возможность контролировать запуск вот этих юнитов. Демаркация между /usr/lib/systemd/system и /etc/systemd/system позволяет правильно определить область ответственности администратора, упрощая процесс обслуживания системы в долгосрочной перспективе.

Таким образом, правильнее размещать кастомные системные юнит-файлы в /etc/systemd/system. Это обеспечит их стабильность и независимость от обновлений и даст вам полный контроль над поведением этих сервисов в вашей операционной системе.

Оцените материал
Добавить комментарий

Капча загружается...