Я создаю файл systemd .service, и мне нужна помощь в понимании разницы между Requires=
и After=
. В страница руководства Говорит, что Requires=
«Настраивает зависимости требований от других модулей». и After=
«Настраивает зависимости порядка между модулями». Какая разница?
After=
настраивает сервисный заказ (X только после Y), а Requires=
государственные зависимости. Если вы не укажете порядок, служба, зависящая от другой, будет запущена одновременно с той, от которой она зависит. Кроме того, насколько я понимаю (хотя сейчас я не могу это проверить и не могу найти ссылку), After=
является «слабой связью», и служба с таким оператором все равно будет работать, если та, что указана в After=
линия вообще не запускается, а Require=
предотвратит запуск, если требование не будет выполнено.
Цитируя https://www.freedesktop.org/software/systemd/man/systemd.unit.html:
Требуется =
Настраивает зависимости требований от других модулей. Если этот отряд активируется, перечисленные здесь юниты также будут активированы. Если один из других блоков будет деактивирован или его активация не удастся, это устройство будет деактивировано. Эта опция может быть указана более одного раза или несколько единиц, разделенных пробелами, могут быть указаны в одной опции, и в этом случае будут созданы зависимости требований для всех перечисленных имен. Обратите внимание, что зависимости требований не влияют на порядок, в котором службы запускаются или останавливаются. Это должно быть настроено независимо с опциями After = или Before =. Если для модуля foo.service требуется модуль bar.service, настроенный с помощью Requires =, а порядок не настроен с помощью After = или Before =, то оба модуля будут запущены одновременно и без какой-либо задержки между ними, если foo.service активирован. Часто лучше использовать Wants = вместо Requires =, чтобы получить более надежную систему при работе с отказавшими службами.
и
До =, После =
Список имен юнитов, разделенных пробелами. Настраивает зависимости порядка между юнитами. Если модуль foo.service содержит параметр Before = bar.service и оба модуля запускаются, запуск bar.service откладывается до запуска foo.service. Обратите внимание, что этот параметр не зависит и ортогонален зависимостям требований, настроенным с помощью Requires =. Распространенным шаблоном является включение имени модуля в опции After = и Requires =, и в этом случае указанный модуль будет запущен раньше, чем модуль, настроенный с этими параметрами. Этот параметр может быть указан более одного раза, и в этом случае будут созданы зависимости упорядочения для всех перечисленных имен. After = является обратным значению Before =, то есть в то время как After = гарантирует, что сконфигурированный модуль запускается после того, как указанный модуль завершил запуск, Before = гарантирует обратное, то есть, что сконфигурированный модуль полностью запускается до запуска указанного модуля. Обратите внимание, что при отключении двух блоков с зависимостью порядка их включения применяется обратный порядку запуска. то есть, если блок настроен с помощью After = на другом блоке, первый останавливается раньше второго, если оба отключены. Для двух блоков с какой-либо зависимостью порядка их выполнения, если один блок выключен, а другой запущен, отключение назначается перед запуском. Не имеет значения, является ли зависимость упорядочивания After = или Before =. Также не имеет значения, какой из двух выключен, если один выключен, а другой запущен. Во всех случаях отключение заказывается перед запуском. Если два блока не имеют зависимостей по порядку между собой, они выключаются или запускаются одновременно, и заказ не производится.
Одно из основных различий в том,
After
только проверяет, активирован ли объект уже, и не активирует явно указанные единицы.Requires
активируются вместе с агрегатом. Если какой-либо из требуемых агрегатов не запускается, агрегат не активируется.Считайте, что у меня есть файл модуля test-app.service
,
[Unit]
Description=test app
After=network-online.target
Вот что произойдет при выполнении этого оператора:
After
проверяет, если network-online.target
.network-online.target
не запустился, будет ждать.test-app
начинается только после network-online.target
активенЕсли бы у меня было Requires
вместо,
[Unit]
Description=test app
Requires=network-online.target
Вот что произойдет при выполнении этого оператора:
network-online.target
и test-app
активируются вместеnetwork-online.target
не запускается test-app
не будет активирован.systemd - менеджер заданий. На странице руководства нет точных сведений о том, как все работает.
Когда вы загружаетесь, systemd создает транзакцию, состоящую из заданий для задания привязки (т.е. запускает задание для default.target). Все эти зависимости и отношения определяют, как и какие задания будут запускаться. Порядок определяет, какие задания будут ждать все остальные. Таким образом, модуль default.target находится в центре всего этого, поэтому при включении модулей вы используете обратную зависимость, которая через systemctl enable создает символическую ссылку файловой системы, обозначающую прямую зависимость, которой systemd может следовать (также почему вам нужны символические ссылки файловой системы в первое место). Аналогично, когда вы вручную запускаете какой-либо модуль, тогда этот модуль является якорем, и транзакция вычисляется по нему.
Не вдаваясь в подробности, я объясню, что делает Requires = и After =.
Requires = заставит systemd запускать стартовое задание для требуемого модуля, когда вы запускаете стартовое задание (явно или через зависимость: нет никаких внутренних различий). Он также имеет свойство запускать для вас задание остановки, когда это устройство остановлено (примечание: остановлено, не выключается само по себе) или перезапускается. Это означает, что если какая-то зависимость / systemctl заставит его остановить / перезапустить, вы также остановитесь / перезапустите. Однако, если он выйдет из строя сам по себе, вы не остановитесь, так как работы не было, а изменение состояния произошло без участия systemd. Вот где вы должны использовать BindsTo = (аналогично устройствам, которые могут переходить в неактивное состояние без участия systemd по очевидным причинам).
Теперь рекомендуется использовать After =, поскольку только Requires = подходит для того, что он делает: отмените требование, если начальное задание не удается. Однако эта отмена работает только с заданиями, то есть, если другой блок не определяет порядок, systemd запускает оба параллельно, и если его стартовое задание завершается до того, как ваше стартовое задание завершится сбоем, оно не будет отменено (фактически, его нельзя отменить) . Использование After = означает, что другое задание продолжает ждать, пока не завершится стартовое задание требуемого устройства, и в зависимости от результата, если оно не удалось, ожидающее стартовое задание вашего устройства отменяется с результатом задания JOB_DEPENDENCY (почему вы используете желтый [DEPEND] при загрузке для таких случаев). Следовательно, этот эффект недействительности недетерминирован без использования After =.
Вот почему использование Wants = без After = нормально, если вы не хотите ждать запуска другого модуля: поскольку здесь нет недействительности, поэтому нет гонки. В этом случае это не более чем механизм синхронизации.
Кроме того, вы также можете включить оба при загрузке и не требовать друг друга, а только определить порядок, в том случае, когда оба извлекаются как часть одной и той же транзакции, они будут упорядочены (или если задание для другого запускается в то время как задание для модуля, после которого он хочет запустить, выполняется, оно сначала будет ждать его завершения между транзакциями).
Теперь, если нет работы, заказ не влияет на указанную единицу. Тем не менее, обычно есть работа, как следствие использования зависимостей, таких как Requires = и Wants =, или обоих, которые втягиваются одновременно и определяют некоторый порядок, и в этом случае они действительно ждут работы другого модуля.