10.6.3. Конвертация SysV Init скриптов в файлы юнитов (Unit Files)
Прежде чем заняться преобразованием скрипта SysV (далее – init-скрпт) в файл юнита, убедитесь, что преобразование еще не было выполнено в другом месте. Все основные службы, установленные в Red Hat Enterprise Linux 7, поставляются со стандартными юнит-файлами, и то же самое относится ко многим сторонним программным пакетам.
Преобразование init-скрипта в юнит-файл требует анализа init-скрипта и извлечения из него необходимой информации. На основе полученных данных вы можете создать файл юнита, как описано в разделе 10.6.2 «Создание пользовательских файлов юнита». Поскольку init-скрипты могут сильно различаться в зависимости от типа сервиса, возможно вам потребуется использовать больше параметров конфигурации для конвертации, чем описано в этой главе. Обратите внимание, что некоторые уровни настройки, которые были доступны в init-скриптах, больше не поддерживаются модулями systemd, см. Раздел 10.1.2, «Изменения совместимости».
Большая часть информации, необходимой для конвертации, указана в заголовке скрипта. В следующем примере показан начальный раздел init-скрипта, используемого для запуска службы postfix
в Red Hat Enterprise Linux 6 (пример файла юнита для postfix
можно найти в предыдущей части):
#!/bin/bash
#
# postfix Postfix Mail Transfer Agent
#
# chkconfig: 2345 80 30
# description: Postfix is a Mail Transport Agent, which is the program \
# that moves mail from one machine to another.
# processname: master
# pidfile: /var/spool/postfix/pid/master.pid
# config: /etc/postfix/main.cf
# config: /etc/postfix/master.cf
### BEGIN INIT INFO
# Provides: postfix MTA
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop postfix
# Description: Postfix is a Mail Transport Agent, which is the program that
# moves mail from one machine to another.
### END INIT INFO |
#!/bin/bash
#
# postfix Postfix Mail Transfer Agent
#
# chkconfig: 2345 80 30
# description: Postfix is a Mail Transport Agent, which is the program \
# that moves mail from one machine to another.
# processname: master
# pidfile: /var/spool/postfix/pid/master.pid
# config: /etc/postfix/main.cf
# config: /etc/postfix/master.cf
### BEGIN INIT INFO
# Provides: postfix MTA
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop postfix
# Description: Postfix is a Mail Transport Agent, which is the program that
# moves mail from one machine to another.
### END INIT INFO
В приведенном выше примере обязательны только строки, начинающиеся с #chkconfig
и #description
, поэтому вы можете не найти остальных в разных init-файлах. Текст, заключенный между строками ### BEGIN INIT INFO
и ### END INIT INFO
, называется заголовком Linux Standard Base (LSB). Если LSB-заголовок указан, то он содержит директивы, определяющие описание службы, зависимости и уровни запуска (runlevels). Далее следует обзор аналитических задач, направленных на сбор данных, необходимых для нового юнит-файла. В качестве примера используется init-скрипт postfix
, см. Итоговый файл модуля postfix
в примере 10.17, «Файл юнита postfix.service».
Поиск описания сервиса
Найдите описание скрипта в строке, начинающейся с #description
. Используйте это описание вместе с именем сервиса в опции Description
секции [Unit] в файле юнита. Заголовок LSB может содержать аналогичные данные в строках #Short-Description
и #Description
.
Поиск зависимостей сервиса
Заголовок LSB может содержать несколько директив, которые формируют зависимости между сервисами. Большая часть может быть переведена в опции юнита systemd, см. Таблицу 10.12, «Параметры зависимостей из заголовка LSB».
Таблица 10.12, Параметры зависимостей из заголовка LSB
Опция LSB |
Описание |
Опция юнита |
Provides |
Задает имя сервиса при загрузке, на которое можно ссылаться в других скриптах (с префиксом “$”). Сейчас это не требуется, т.к. юнит-файлы ссылаются на другие юнит-файлы по их именам. |
– |
Required-Start |
Содержит загрузочные имена необходимых сервисов. Т.е. это зависимости упорядочения, имена необходимых сервисов при переводе заменяются на имена юнит-файлов соответствующих сервисов или таргетов, которым они принадлежат. Например, в случае с postfix зависимость Required-Start: $network была переведена в зависимость After=network.target .
|
After, Before |
Should-Start |
Определяет более слабые зависимости, чем Required-Start . Неудачные зависимости Should-Start не влияют на запуск службы. |
After, Before |
Required-Stop, Should-Stop |
Определяет негативные зависимости. |
Conflicts |
Определение таргета для запуска сервиса
Строка, начинающаяся с #chkconfig
, содержит три числовых значения. Для нас важно первое число, которым представлены уровни запуска по умолчанию для данного сервиса. Используйте Таблицу 10.6, «Сравнение уровней запуска SysV с таргетами systemd», чтобы перевести эти уровни выполнения в таргеты systemd. Затем перечислите эти таргеты в опции WantedBy
в разделе [Install] файла юнита. Например, postfix
ранее запускался на уровнях запуска 2, 3, 4 и 5, что соответствует таргетам multi-user.target
и graphical.target
в Red Hat Enterprise Linux 7. Обратите внимание, что graphical.target
зависит от multiuser.target
, поэтому нет необходимости указывать оба, как в примере 10.17, «Файл модуля postfix.service». Вы также можете найти информацию о дефолтных и запрещенных уровнях запуска в строках #Default-Start
и #Default-Stop
в заголовке LSB.
Два других значения, указанные в строке #chkconfig
, представляют приоритеты запуска и завершения init-скрипта. Эти значения интерпретируются systemd, если он загружает init-скрипт, но нет эквивалентного юнит-файла.
Определение файлов, используемых сервисом
Init-скрипты требуют загрузки библиотеки функций из выделенной директории и позволяют импортировать файлы конфигурации, среды и PID файлы. Переменные среды указываются в строке, начинающейся с #config
в заголовке скрипта и соответствует опции EnvironmentFile
в файле юнита. Файл PID, указанный в init-скрипте в строке #pidfile
импортируется в файл юнита с опцией PIDFile
.
Ключевой информацией, которая не включена в заголовок скрипта, является путь к исполняемому файлу сервиса и, возможно, некоторые другие файлы, необходимые для сервиса. В предыдущих версиях Red Hat Enterprise Linux init-скрипты использовали оператор Bash case
, чтобы определить поведение службы при действиях по умолчанию, таких как запуск, остановка или перезапуск, а также при выполнении определенных пользователем действий. Следующий фрагмент из init-скрипта postfix
показывает блок кода, который должен быть выполнен при запуске сервиса.
conf_check() {
[ -x /usr/sbin/postfix ] || exit 5
[ -d /etc/postfix ] || exit 6
[ -d /var/spool/postfix ] || exit 5
}
make_aliasesdb() {
if [ "$(/usr/sbin/postconf -h alias_database)" == "hash:/etc/aliases" ]
then
# /etc/aliases.db might be used by other MTA, make sure nothing
# has touched it since our last newaliases call
[ /etc/aliases -nt /etc/aliases.db ] ||
[ "$ALIASESDB_STAMP" -nt /etc/aliases.db ] ||
[ "$ALIASESDB_STAMP" -ot /etc/aliases.db ] || return
/usr/bin/newaliases
touch -r /etc/aliases.db "$ALIASESDB_STAMP"
else
/usr/bin/newaliases
fi
}
start() {
[ "$EUID" != "0" ] && exit 4
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
conf_check
# Start daemons.
echo -n $"Starting postfix: "
make_aliasesdb >/dev/null 2>&1
[ -x $CHROOT_UPDATE ] && $CHROOT_UPDATE
/usr/sbin/postfix start 2>/dev/null 1>&2 && success || failure $"$prog start"
RETVAL=$?
[ $RETVAL -eq 0 ] && touch $lockfile
echo
return $RETVAL
} |
conf_check() {
[ -x /usr/sbin/postfix ] || exit 5
[ -d /etc/postfix ] || exit 6
[ -d /var/spool/postfix ] || exit 5
}
make_aliasesdb() {
if [ "$(/usr/sbin/postconf -h alias_database)" == "hash:/etc/aliases" ]
then
# /etc/aliases.db might be used by other MTA, make sure nothing
# has touched it since our last newaliases call
[ /etc/aliases -nt /etc/aliases.db ] ||
[ "$ALIASESDB_STAMP" -nt /etc/aliases.db ] ||
[ "$ALIASESDB_STAMP" -ot /etc/aliases.db ] || return
/usr/bin/newaliases
touch -r /etc/aliases.db "$ALIASESDB_STAMP"
else
/usr/bin/newaliases
fi
}
start() {
[ "$EUID" != "0" ] && exit 4
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
conf_check
# Start daemons.
echo -n $"Starting postfix: "
make_aliasesdb >/dev/null 2>&1
[ -x $CHROOT_UPDATE ] && $CHROOT_UPDATE
/usr/sbin/postfix start 2>/dev/null 1>&2 && success || failure $"$prog start"
RETVAL=$?
[ $RETVAL -eq 0 ] && touch $lockfile
echo
return $RETVAL
}
Init-скрипт позволяет указать пользовательские функции, здесь это conf_check()
и make_aliasesdb()
, которые вызываются из функционального блока start()
. В приведенном выше коде упоминаются несколько внешних файлов и директорий: исполняемый файл основного сервиса /usr/sbin/postfix
, директории конфигураций /etc/postfix/
и /var/spool/postfix/
, а также директория /usr/sbin/postconf/
.
Systemd
поддерживает только предопределенные действия, но позволяет выполнять пользовательские исполняемые файлы с помощью ExecStart
, ExecStartPre
, ExecStartPost
, ExecStop
и ExecReload
. В случае с postfix в RHEL 7, /usr/sbin/postfix
выполняется вместе со вспомогательными скриптами при запуске сервиса. Посмотрите файл юнита postfix
в Примере 10.17, «Файл модуля postfix.service».
Преобразование сложных скриптов требует понимания назначения каждого оператора в скрипте. Некоторые операторы относятся к конкретной версии операционной системы, поэтому вам не нужно переводить их. С другой стороны, в новой среде могут потребоваться некоторые корректировки, как в файле юнита, так и в исполняемом файле сервиса и вспомогательных файлах.
10.6.4. Изменение существующих файлов юнитов
Службы, установленные в системе, поставляются с файлами юнитов по умолчанию, которые хранятся в директории /usr/lib/systemd/system/
. Системные администраторы не должны изменять эти файлы напрямую, любые настройки должны быть ограничены файлами конфигурации в директории /etc/systemd/system/
. В зависимости от степени необходимых изменений выберите один из следующих подходов:
- Создайте директори. для дополнительных файлов конфигурации в
/etc/systemd/system/unit.d
/. Этот метод рекомендуется в большинстве случаев. Это позволяет расширить конфигурацию дополнительными функциональными возможностями, ссылаясь при этом на исходный файл юнита. Поэтому изменения в юните, поисходящие при обновлении пакета, применяются автоматически. См. Раздел «Расширение конфигурации юнита по умолчанию» для получения дополнительной информации.
- Создайте копию файла юнита из
/usr/lib/systemd/system/
в /etc/systemd/system/
и делайте изменения в ней. Копия переопределяет исходный файл, поэтому изменения, внесенные обновлением пакета, не применяются. Этот метод полезен для внесения значительных изменений в юниты, которые должны сохраняться независимо от обновлений пакета. Подробнее см. в разделе «Переопределение конфигурации модуля по умолчанию».
Чтобы вернуться к стандартной конфигурации юнита, просто удалите пользовательские файлы конфигурации в /etc/systemd/system/
. Чтобы применить изменения к файлам юнита без перезагрузки системы, выполните:
Опция daemon-reload
перезагружает все файлы юнитов и воссоздает все дерево зависимостей для применения любых изменений в файлах юнитов. Того же результата можно добиться с помощью следующей команды:
Также, если модифицированный юнит-файл принадлежит работающему сервису, необходимо перезапустить сам сервис для применения новых настроек:
systemctl restart name.service |
systemctl restart name.service
Важно
Чтобы изменить свойства (такие как зависимости или тайм-ауты) сервиса, который обрабатывается init-скриптом SysV, не изменяйте сам init-скрипт. Вместо этого создайте системный файл конфигурации systemd
для службы, как описано в разделе «Расширение конфигурации юнита по умолчанию» и в разделе «Переопределение конфигурации юнита по умолчанию». Затем управляйте этим сервисом так же, как обычным сервисом systemd
.
Например, чтобы расширить конфигурацию сервиса network
, не изменяйте init-файл /etc/rc.d/init.d/network
. Вместо этого создайте новую директорию /etc/systemd/system/network.service.d/
и drop-in файл /etc/systemd/system/network.service.d/my_config.conf
(прим. переводчика: для себя я определяю drop-in файлы как дополнительные конфиги. Система заглядывает в каталоги конфигурации и подбирает то, что там лежит). Затем поместите измененные значения в drop-in файл. Заметка: systemd
знает сервис network
как network.service
, поэтому созданный каталог должен называться network.service.d
.
Расширение конфигурации юнитов
Чтобы добавить дополнительные параметры конфигурации в файл юнита, сначала создайте директорию конфигурации в /etc/systemd/system/
. Если вы расширяете юнит сервиса, выполните следующую команду от root:
mkdir /etc/systemd/system/name.service.d/ |
mkdir /etc/systemd/system/name.service.d/
Замените name именем сервиса, который вы хотите расширить. Вышеуказанный синтаксис применяется ко всем типам юнитов.
Создайте файл конфигурации в директории, созданной на предыдущем шаге. Имя файла должно иметь суффикс .conf . Наберите:
touch /etc/systemd/system/name.service.d/config_name.conf |
touch /etc/systemd/system/name.service.d/config_name.conf
Замените config_name на имя файла конфигурации. Этот файл имеет структуру обычного файла юнита, поэтому все директивы должны быть указаны в соответствующих разделах, см. Раздел 10.6.1, «Понимание структуры файла юнита».
Например, чтобы добавить зависимость, создайте файл конфигурации со следующим содержимым:
[Unit]
Requires=new_dependency
After=new_dependency |
[Unit]
Requires=new_dependency
After=new_dependency
Где new_dependency обозначает юнит, который помечен как зависимость. Другой пример файла конфигурации, который перезапускает сервис после того, как основной процесс завершится, с задержкой 30 секунд:
[Service]
Restart=always
RestartSec=30 |
[Service]
Restart=always
RestartSec=30
Рекомендуется создавать небольшие файлы конфигураций, ориентированные на одну задачу. Такие файлы легко переместить или связать (создать линк) с каталогами конфигурации других сервисов.
Чтобы внесенные изменения вступили в силу, выполните от root:
systemctl daemon-reload
systemctl restart name.service |
systemctl daemon-reload
systemctl restart name.service
Пример 10.20. Расширение конфигурации httpd.service
Изменим юнит httpd.service
так, чтобы при запуске Apache
автоматически выполнялся shell-скрипт. Создайте каталог и файл конфигурации:
~]# mkdir /etc/systemd/system/httpd.service.d/
~]# touch /etc/systemd/system/httpd.service.d/custom_script.conf |
~]# mkdir /etc/systemd/system/httpd.service.d/
~]# touch /etc/systemd/system/httpd.service.d/custom_script.conf
Предположим, что /usr/local/bin/custom.sh – путь к скрипту, который вы хотите запустить вместе с Apache, вставьте следующий текст в файл custom_script.conf:
[Service]
ExecStartPost=/usr/local/bin/custom.sh |
[Service]
ExecStartPost=/usr/local/bin/custom.sh
Чтобы принять изменения, выполните:
~]# systemctl daemon-reload
~]# systemctl restart httpd.service |
~]# systemctl daemon-reload
~]# systemctl restart httpd.service
Заметка
Файлы конфигурации из директорий /etc/systemd/system/
имеют приоритет над файлами юнитов в /usr/lib/systemd/system/
. Следовательно, если файлы конфигурации содержат параметр, который может быть указан только один раз, например, Description
или ExecStart
, значение по умолчанию для этого параметра переопределяется. Обратите внимание, что в выходных данных команды systemd-delta
, описанной в разделе «Мониторинг переопределенных юнитов», такие юниты всегда помечаются как [EXTENDED]
, хотя фактически некоторые параметры переопределяются.
Переопределение конфигурации юнита по умолчанию
Чтобы внести изменения в юнит, которые сохранятся после обновления пакета, сначала скопируйте файл в каталог /etc/systemd/system/
. Для этого выполните от root:
cp /usr/lib/systemd/system/name.service /etc/systemd/system/name.service |
cp /usr/lib/systemd/system/name.service /etc/systemd/system/name.service
Где name – имя сервиса, файл юнита которого вы хотите изменить. Этот синтаксис применим ко всем типам юнитов.
Откройте скопированный файл в текстовом редакторе и внесите желаемые изменения. Чтобы принять изменения, выполните от root:
systemctl daemon-reload
systemctl restart name.service |
systemctl daemon-reload
systemctl restart name.service
Пример 10.21. Изменение тайм-аута
Вы можете указать тайм-аут для каждой службы, чтобы предотвратить зависание системы из-за сбоя в работе службы. Обычно, тайм-аут установлен в 90 секунд для обычных сервисов и 300 секунд для SysV-совместимых сервисов.
Например, установим тайм-аут для httpd
сервиса:
- Скопируйте юнит-файл httpd в директорию /etc/systemd/system/:
cp /usr/lib/systemd/system/httpd.service /etc/systemd/system/httpd.service |
cp /usr/lib/systemd/system/httpd.service /etc/systemd/system/httpd.service
- Откройте файл /etc/systemd/system/httpd.service и определите значение TimeoutStartUSec в секции [Service]:
...
[Service]
...
PrivateTmp=true
TimeoutStartSec=10
[Install]
WantedBy=multi-user.target
... |
...
[Service]
...
PrivateTmp=true
TimeoutStartSec=10
[Install]
WantedBy=multi-user.target
...
- Перезагрузите демон systemd:
- Проверьте, что новый тайм-аут установлен:
systemctl show httpd -p TimeoutStartUSec |
systemctl show httpd -p TimeoutStartUSec
Заметка
Чтобы сменить тайм-аут глобально, введите значение DefaultTimeoutStartSec
в файл /etc/systemd/system.conf
. Подробнее см. раздел 10.1, “Введение в systemd”.
Мониторинг переопределенных юнитов
Чтобы просмотреть переопределенные или измененные юниты, используйте следующую команду:
Например, вывод вышеуказанной команды может выглядеть следующим образом:
[EQUIVALENT] /etc/systemd/system/default.target → /usr/lib/systemd/system/default.target
[OVERRIDDEN] /etc/systemd/system/autofs.service → /usr/lib/systemd/system/autofs.service
--- /usr/lib/systemd/system/autofs.service 2014-10-16 21:30:39.000000000 -0400
+++ /etc/systemd/system/autofs.service 2014-11-21 10:00:58.513568275 -0500
@@ -8,7 +8,8 @@
EnvironmentFile=-/etc/sysconfig/autofs
ExecStart=/usr/sbin/automount $OPTIONS --pid-file /run/autofs.pid
ExecReload=/usr/bin/kill -HUP $MAINPID
-TimeoutSec=180
+TimeoutSec=240
+Restart=Always
[Install]
WantedBy=multi-user.target
[MASKED] /etc/systemd/system/cups.service → /usr/lib/systemd/system/cups.service
[EXTENDED] /usr/lib/systemd/system/sssd.service → /etc/systemd/system/sssd.service.d/journal.conf
4 overridden configuration files found. |
[EQUIVALENT] /etc/systemd/system/default.target → /usr/lib/systemd/system/default.target
[OVERRIDDEN] /etc/systemd/system/autofs.service → /usr/lib/systemd/system/autofs.service
--- /usr/lib/systemd/system/autofs.service 2014-10-16 21:30:39.000000000 -0400
+++ /etc/systemd/system/autofs.service 2014-11-21 10:00:58.513568275 -0500
@@ -8,7 +8,8 @@
EnvironmentFile=-/etc/sysconfig/autofs
ExecStart=/usr/sbin/automount $OPTIONS --pid-file /run/autofs.pid
ExecReload=/usr/bin/kill -HUP $MAINPID
-TimeoutSec=180
+TimeoutSec=240
+Restart=Always
[Install]
WantedBy=multi-user.target
[MASKED] /etc/systemd/system/cups.service → /usr/lib/systemd/system/cups.service
[EXTENDED] /usr/lib/systemd/system/sssd.service → /etc/systemd/system/sssd.service.d/journal.conf
4 overridden configuration files found.
В таблице 10.13 «Типы различий systemd-delta» перечислены типы переопределений, которые можно увидеть в выводе systemd-delta
. Обратите внимание, что если файл переопределен, systemd-delta
по умолчанию отображает сводку изменений, аналогичную выводу команды diff
.
Таблица 10.13, Типы различий systemd-delta
Опция LSB |
Описание |
[MASKED] |
Замаскированные юниты. Как замаскировать юнит см. Раздел 10.2.7, “Удаление из автозагрузки”. |
[EQUIVALENT] |
Неизмененные копии, которые переопределяют исходные файлы, но не отличаются по содержанию, как правило, это символические ссылки. |
[REDIRECTED] |
Файлы, которые перенаправляют в другой файл. |
[OVERRIDEN] |
Перезаписанные и измененные файлы. |
[EXTENDED] |
Файлы, которые расширены файлами .conf в директории /etc/systemd/system/unit.d/. |
[UNCHANGED] |
Неизмененные файлы, отображаются при использовании опции --type=unchanged . |
Рекомендуется запускать systemd-delta
после обновления системы, чтобы проверить, есть ли какие-либо обновления для юнитов по умолчанию, которые в настоящее время переопределяются пользовательской конфигурацией. Также можно ограничить вывод только определенным типом различий. Например, чтобы просмотреть только переопределенные блоки [OVERRIDEN], выполните:
systemd-delta --type=overridden |
systemd-delta --type=overridden
10.6.5. Работа с юнитами, созданными из шаблона (Instantiated Units)
Можно создать несколько экземпляров из одного файла конфигурации шаблона во время выполнения. Символ «@» используется для обозначения шаблона и ассоциации юнита с ним. Instantiated units могут быть запущены из другого файла юнита (с использованием параметров Requires
или Wants
) или с помощью команды systemctl start
. Instantiated service units именуются следующим образом:
template_name@instance_name.service |
template_name@instance_name.service
Где template_name – имя файла конфигурации шаблона. Замените instance_name именем экземпляра юнита. Несколько экземпляров могут указывать на один и тот же файл шаблона с параметрами конфигурации, общими для всех экземпляров юнита. Имя шаблона юнита имеет вид:
Например, следующая настройка Wants
в файле юнита:
Wants=getty@ttyA.service,getty@ttyB.service |
Wants=getty@ttyA.service,getty@ttyB.service
сначала выполняет поиск для заданных сервисных юнитов. Если таких юнитов не найдено, часть между “@” и суффиксом типа игнорируется, и systemd
ищет файл getty@.service
, считывает из него конфигурацию и запускает сервисы.
Подстановочные знаки, называемые спецификаторами единиц, могут использоваться в любом файле конфигурации юнитов. Спецификаторы юнита заменяют определенные параметры модуля и интерпретируются во время выполнения. В таблице 10.14 «Важные спецификаторы юнитов» перечислены полезные для юнитов-шаблонов спецификаторы юнитов.
Таблица 10.14, Важные спецификаторы юнитов
Спецификатор |
Значение |
Описание |
%n |
Полное имя юнита |
Полное имя юнита, включая суффикс. %N имеет то же значение, но также заменяет запрещенные символы на коды ASCII. |
%p |
Префикс |
Имя юнита без суффикса типа. Для созданных экземпляров юнитов %p обозначает часть имени юнита перед символом «@». |
%i |
Instance name Имя экземпляра |
Это часть имени экземпляра юнита между символом «@» и суффиксом типа. %I имеет то же значение, но также заменяет запрещенные символы на коды ASCII. |
%H |
Host name Имя хоста |
Имя хоста работающей системы в момент загрузки конфигурации юнита. |
%t |
Runtime directory |
Represents the runtime directory, which is either /run for the root user, or the value of the XDG_RUNTIME_DIR variable for unprivileged users.
Представляет собой runtime-директорию, которая либо /run для пользователя root, либо значение из переменной окружения XDG_RUNTIME_DIR для непривилегированных пользователей. |
Полный список спецификаторов см. в мануале systemd.unit(5).
Например, шаблон getty@.service содержит следующие директивы:
[Unit]
Description=Getty on %I
...
[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
... |
[Unit]
Description=Getty on %I
...
[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
...
Когда создаются экземпляры getty@ttyA.service
и getty@ttyB.service
из вышеприведенного шаблона, Description
= преобразуется в Getty on ttyA и Getty on ttyB.
10.7. Additional Resources – этот раздел я не вижу смысла переводить, так как он просто содержит ссылки на дополнительные источники информации. Но оставлю его тут)