Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1fbbf08cf | ||
|
|
0905f9aa1d | ||
|
|
50c0e1a158 | ||
|
|
c64fc681b2 | ||
|
|
adf3ff6581 | ||
|
|
61330d78c8 | ||
|
|
b853acbc75 | ||
|
|
51dbc5ede3 | ||
|
|
eb7a6ce4b1 | ||
|
|
6ddc14e9e7 | ||
|
|
df5abe6fc6 |
628
s4a.tex
628
s4a.tex
@@ -16,6 +16,11 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
|||||||
% Несколько сокращений
|
% Несколько сокращений
|
||||||
\newcommand{\sectiona}[1]{\section*{#1}\addcontentsline{toc}{section}{#1}}
|
\newcommand{\sectiona}[1]{\section*{#1}\addcontentsline{toc}{section}{#1}}
|
||||||
\newcommand{\hreftt}[2]{\href{#1}{\texttt{#2}}}
|
\newcommand{\hreftt}[2]{\href{#1}{\texttt{#2}}}
|
||||||
|
\newcommand{\tbs}{\textbackslash}
|
||||||
|
% Примерный аналог символа \testSFii (присутствует в листингах),
|
||||||
|
% но без использования пакета pmboxdraw, средствами graphicx
|
||||||
|
\newcommand{\mytextSFii}{\raisebox{0pt}[0pt][\depth]{%
|
||||||
|
\reflectbox{\rotatebox[origin=t]{270}{$\neg$}}}}
|
||||||
% Настройка макета страницы
|
% Настройка макета страницы
|
||||||
\setlength{\hoffset}{-1.5cm}
|
\setlength{\hoffset}{-1.5cm}
|
||||||
\addtolength{\textwidth}{2cm}
|
\addtolength{\textwidth}{2cm}
|
||||||
@@ -580,6 +585,7 @@ systemd именует группы в соответствии с назван
|
|||||||
последующих статьях мы обсудим этот вопрос более подробно.
|
последующих статьях мы обсудим этот вопрос более подробно.
|
||||||
|
|
||||||
\section{HOW-TO: преобразование SysV init-скрипта в systemd service-файл}
|
\section{HOW-TO: преобразование SysV init-скрипта в systemd service-файл}
|
||||||
|
\label{sec:convert}
|
||||||
|
|
||||||
Традиционно, службы Unix и Linux (демоны) запускаются через SysV init-скрипты.
|
Традиционно, службы Unix и Linux (демоны) запускаются через SysV init-скрипты.
|
||||||
Эти скрипты пишутся на языке Bourne Shell (+/bin/sh+), располагаются в
|
Эти скрипты пишутся на языке Bourne Shell (+/bin/sh+), располагаются в
|
||||||
@@ -706,7 +712,7 @@ WantedBy=multi-user.target
|
|||||||
во-вторых, указание, что данный юнит рекомендуется активировать после запуска
|
во-вторых, указание, что данный юнит рекомендуется активировать после запуска
|
||||||
демона системного лога\footnote{Строго говоря, эту зависимость здесь
|
демона системного лога\footnote{Строго говоря, эту зависимость здесь
|
||||||
указывать не~нужно~--- в системах, в которых демон системного лога активируется
|
указывать не~нужно~--- в системах, в которых демон системного лога активируется
|
||||||
через сокет, эта зависимость является избыточной. Современные реализации
|
через сокет, данная зависимость является избыточной. Современные реализации
|
||||||
демона системного лога (например, rsyslog начиная с пятой версии)
|
демона системного лога (например, rsyslog начиная с пятой версии)
|
||||||
поддерживают активацию через сокет. В системах, использующих такие
|
поддерживают активацию через сокет. В системах, использующих такие
|
||||||
реализации, явное указание +After=syslog.target+ будет избыточным, так
|
реализации, явное указание +After=syslog.target+ будет избыточным, так
|
||||||
@@ -1175,10 +1181,10 @@ chroot-окружения требует глубокого понимания
|
|||||||
встроенную поддержку chroot. К сожалению, в системе Fedora, установленной с
|
встроенную поддержку chroot. К сожалению, в системе Fedora, установленной с
|
||||||
параметрами по умолчанию, таких демонов всего два:
|
параметрами по умолчанию, таких демонов всего два:
|
||||||
\href{http://avahi.org/}{Avahi} и RealtimeKit. Оба они написаны одним очень
|
\href{http://avahi.org/}{Avahi} и RealtimeKit. Оба они написаны одним очень
|
||||||
хитрым человеком ;-) (Вы можете собственноручно убедится в этом, выполнив
|
хитрым человеком ;-) (Вы можете собственноручно убедиться в этом, выполнив
|
||||||
команду +ls -l /proc/*/root+.)
|
команду +ls -l /proc/*/root+.)
|
||||||
|
|
||||||
Возвращаясь к тема нашего обсуждения: разумеется, systemd позволяет помещать
|
Возвращаясь к теме нашего обсуждения: разумеется, systemd позволяет помещать
|
||||||
выбранных демонов в chroot, и управлять ими точно так же, как и другими.
|
выбранных демонов в chroot, и управлять ими точно так же, как и другими.
|
||||||
Достаточно лишь указать параметр +RootDirectory=+ в соответствующем
|
Достаточно лишь указать параметр +RootDirectory=+ в соответствующем
|
||||||
service-файле. Например:
|
service-файле. Например:
|
||||||
@@ -1857,6 +1863,622 @@ shed)~--- если первое из этих решений принимает
|
|||||||
этих разработчиков планируют обеспечить поддержку новой конфигурации даже в
|
этих разработчиков планируют обеспечить поддержку новой конфигурации даже в
|
||||||
системах без systemd.
|
системах без systemd.
|
||||||
|
|
||||||
|
\section{О судьбе /etc/sysconfig и /etc/default}
|
||||||
|
|
||||||
|
В дистрибутивах, основанных на Red Hat и SUSE, это каталог называется
|
||||||
|
+/etc/sysconfig+. В дистрибутивах на базе Debian, его зовут +/etc/default+.
|
||||||
|
Во многих других дистрибутивах также присутствуют каталоги похожего назначения.
|
||||||
|
Связанные с ними вопросы неоднократно появляются в дискуссиях пользователей и
|
||||||
|
разработчиков systemd. В этой статье мне хотелось бы рассказать, что я, как
|
||||||
|
разработчик systemd, думаю об этих каталогах, и пояснить, почему, на мой взгляд,
|
||||||
|
от них лучше отказаться. Стоит отметить, что это мое личное мнение, и оно
|
||||||
|
может не~совпадать с позицией проекта Fedora или моего работодателя.
|
||||||
|
|
||||||
|
Начнем с небольшого исторического экскурса. Каталог +/etc/sysconfig+ появился в
|
||||||
|
дистрибутивах Red Hat и SUSE задолго до того, как я присоединился к этим
|
||||||
|
проектам~--- иными словами, это было очень давно.
|
||||||
|
Некоторое время спустя, в Debian появился аналогичный по смыслу каталог
|
||||||
|
+/etc/default+. Многие дистрибутивы используют такие каталоги, называя их
|
||||||
|
по-разному. Они имеются даже в некоторых ОС семейства Unix. (Например, в SCO.
|
||||||
|
Если эта тема вас заинтересовала~--- рекомендую обратиться к вашему знакомому
|
||||||
|
ветерану Unix, он расскажет гораздо подробнее и интереснее, чем я.) Несмотря на
|
||||||
|
то, что подобные каталоги широко используются в Linux и Unix, они совершенно
|
||||||
|
не~стандартизированы~--- ни в POSIX, ни в LSB/FHS, и результате мы имеем целый
|
||||||
|
зоопарк их различных реализаций в разных дистрибутивах.
|
||||||
|
|
||||||
|
Назначение этих каталогов определено весьма расплывчато. Абсолютное большинство
|
||||||
|
находящихся в них файлов являются включаемыми\footnote{Прим. перев.: здесь автор
|
||||||
|
использует термин sourcable, происходящий от bash'овской директивы +source+,
|
||||||
|
обеспечивающей включение в скрипт кода из внешнего файла. В классическом POSIX
|
||||||
|
shell это соответствует оператору-точке <<+.+>>. В отличие от прямого запуска
|
||||||
|
одного скрипта из другого, включаемый код исполняется той же самой оболочкой,
|
||||||
|
что и основной код, и при возвращении в основной скрипт сохраняются переменные
|
||||||
|
окружения, определенные во включаемом коде. Как правило, код для включения
|
||||||
|
не~содержит shebang'а (+#!/bin/sh+ в начале файла).} shell-скриптами, содержащими,
|
||||||
|
главным образом, определения переменных. Большинство файлов из этих каталогов
|
||||||
|
включаются в одноименные скрипты SysV init. Этот принцип отражен в
|
||||||
|
\href{http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit}{Debian
|
||||||
|
Policy Manual (раздел 9.3.2)} и в
|
||||||
|
\href{http://fedoraproject.org/wiki/Packaging:SysVInitScript}{Fedora Packaging
|
||||||
|
Guidelines}, однако в обоих этих дистрибутивах иногда встречаются файлы,
|
||||||
|
не~соответствующие такой схеме, например, не~имеющие соответствующего
|
||||||
|
init-скрипта, или даже сами не~являющиеся скриптами.
|
||||||
|
|
||||||
|
Но почему вообще появились эти каталоги? Чтобы ответить на этот вопрос,
|
||||||
|
обратимся к истории развития концепции SysV init-скриптов. Исторически,
|
||||||
|
сложилось так, что они располагаются в каталоге под названием +/etc/rc.d/init.d+
|
||||||
|
(или что-то похожее). Отметим, что каталог +/etc+ вообще-то предназначен для
|
||||||
|
хранения файлов конфигурации, а не~исполняемого кода (в частности, скриптов).
|
||||||
|
Однако, в начале своей истории, init-скрипты рассматривались именно как файлы
|
||||||
|
конфигурации, и редактирование их администратором было общепринятой практикой.
|
||||||
|
Но со временем, по мере роста и усложнения этих скриптов, их стали рассматривать
|
||||||
|
уже не~как файлы конфигурации, а как некие программы. Чтобы упростить их
|
||||||
|
настройку и обеспечить безопасность процесса обновления, настройки были вынесены
|
||||||
|
в отдельные файлы, загружаемые при работе init-скриптов.
|
||||||
|
|
||||||
|
Попробуем составить некоторое представление о настройках, которые можно сделать
|
||||||
|
через эти файлы. Вот краткий и неполный список различных параметров, которые
|
||||||
|
могут быть заданы через переменные окружения в таких файлах (составлен мною по
|
||||||
|
результатам исследования соответствующих каталогов в Fedora и Debian):
|
||||||
|
\begin{itemize}
|
||||||
|
\item Дополнительные параметры командной строки для бинарника демона.
|
||||||
|
\item Настройки локали для демона.
|
||||||
|
\item Тайм-аут остановки для демона.
|
||||||
|
\item Режим остановки для демона.
|
||||||
|
\item Общесистемные настройки, например, системная локаль, часовой пояс,
|
||||||
|
параметры клавиатуры для консоли.
|
||||||
|
\item Избыточные информация о системных настройках, например, указание,
|
||||||
|
установлены ли аппаратные часы по Гринвичу или по местному
|
||||||
|
времени.
|
||||||
|
\item Списки правил брандмауэра, не~являются скриптами (!).
|
||||||
|
\item Привязка к процессорным ядрам для демона.
|
||||||
|
\item Настройки, не~относящиеся к процессу загрузки, например,
|
||||||
|
информация по установке пакетов с новыми ядрами, конфигурация
|
||||||
|
nspluginwrapper, разрешение на выполнение
|
||||||
|
предварительного связывания (prelinking) библиотек.
|
||||||
|
\item Указание, нужно ли запускать данную службу или нет.
|
||||||
|
\item Настройки сети.
|
||||||
|
\item Перечень модулей ядра, которые должны быть подгружены
|
||||||
|
принудительно.
|
||||||
|
\item Нужно ли отключать питание компьютера при остановке системы
|
||||||
|
(+poweroff+) или нет (+halt+).
|
||||||
|
\item Права доступа для файлов устройств (!).
|
||||||
|
\item Описание соответствующей SysV службы.
|
||||||
|
\item Идентификатор пользователя/группы, значение umask для демона.
|
||||||
|
\item Ограничения по ресурсам для демона.
|
||||||
|
\item Приоритет OOM killer'а для демона.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
А теперь давайте ответим на вопрос: что же такого неправильного в
|
||||||
|
+/etc/sysconfig+ (+/etc/default+) и почему этим каталогам нет места в мире
|
||||||
|
systemd?
|
||||||
|
\begin{itemize}
|
||||||
|
\item Прежде всего, утрачены основная цель и смысл существования этих
|
||||||
|
каталогов: файлы конфигурации юнитов systemd не~являются
|
||||||
|
программами, в отличие от init-скриптов SysV. Эти файлы
|
||||||
|
представляют собой простые, декларативные описания конкретных
|
||||||
|
задач и функций, и обычно содержат не~более шести строк. Они
|
||||||
|
легко могут быть сгенерированы и проанализованы без
|
||||||
|
использования Bourne shell. Их легко читать и понимать. Кроме
|
||||||
|
того, их легко модифицировать: достаточно скопировать их из
|
||||||
|
+/lib/systemd/system+ в +/etc/systemd/system+, после чего внести
|
||||||
|
необходимые изменения в скопированный файл (при этом можно быть
|
||||||
|
уверенным, что изменения не~будут затерты пакетным менеджером).
|
||||||
|
Изначальная причина появления обсуждаемых каталогов~---
|
||||||
|
необходимость разделять код и параметры конфигурации~--- больше
|
||||||
|
не~существует, так как файлы описания юнитов не~являются кодом.
|
||||||
|
Проще говоря, обсуждаемые каталоги являются решением проблемы,
|
||||||
|
которой уже не~существует.
|
||||||
|
\item Обсуждаемые каталоги и файлы в них очень сильно привязаны к
|
||||||
|
специфике дистрибутивов. Мы же планируем, используя systemd,
|
||||||
|
способствовать стандартизации и унификации дистрибутивов. В
|
||||||
|
частности, одним из факторов такой стандартизации является
|
||||||
|
рекомендация распространять соответствующие файлы конфигурации
|
||||||
|
юнитов сразу с апстримным продуктом, а не~возлагать эту работу
|
||||||
|
на создателей пакетов, как это делалась во времена SysV.
|
||||||
|
Так как расположение обсуждаемых каталогов и настраиваемые через
|
||||||
|
них параметры сильно отличаются от дистрибутива к дистрибутиву,
|
||||||
|
пытаться поддерживать их в апстримных файлах конфигурации юнитов
|
||||||
|
просто бессмысленно. Хранение параметров конфигурации в этих
|
||||||
|
каталогах~--- один из факторов, превращающих Linux в зоопарк
|
||||||
|
несовместимых решений.
|
||||||
|
\item Большинство настроек, задаваемых через эти каталоги, являются
|
||||||
|
избыточными в мире systemd. Например, различные службы позволяют
|
||||||
|
задать таким методом параметры исполнения процесса, в частности,
|
||||||
|
идентификатор пользователя/группы, ограничения ресурсов,
|
||||||
|
привязки к ядрам CPU, приоритет OOM killer'а. Однако, эти
|
||||||
|
настройки поддерживаются лишь некоторыми init-скриптами, причем
|
||||||
|
одна и та же настройка в различных скриптах может называться
|
||||||
|
по-разному. С другой стороны, в мире systemd, все эти настройки
|
||||||
|
доступны для всех служб без исключения, и всегда задаются
|
||||||
|
одинаково, через одни и те же параметры конфигурационных файлов.
|
||||||
|
\item Файлы конфигурации юнитов имеют множество удобных и простых в
|
||||||
|
использовании настроек среды исполнения процесса, гораздо
|
||||||
|
больше, чем могут предоставить файлы из +/etc/sysconfig+.
|
||||||
|
\item Необходимость в некоторых из этих настроек весьма сомнительна.
|
||||||
|
Например, возьмем вышеупомянутую возможность задавать
|
||||||
|
идентификатор пользователя/группы для процесса. Эту задачу
|
||||||
|
должен решать разработчик ПО или дистрибутива. Вмешательство
|
||||||
|
администратора в данную настройку, как правило, лишено
|
||||||
|
смысла~--- только разработчик располагает всей информацией,
|
||||||
|
позволяющий предотвратить конфликты идентификаторов и имен
|
||||||
|
пользователей и групп.
|
||||||
|
\item Формат файлов, используемых для сохранения настроек, плохо
|
||||||
|
подходит для данной задачи. Так как эти файлы, как правило,
|
||||||
|
являются включаемыми shell-скриптами, ошибки при их чтении очень
|
||||||
|
трудно отследить. Например, ошибка в имени переменной приведет к
|
||||||
|
тому, что переменная не~будет изменена, однако никакого
|
||||||
|
предупреждения при этом не~выводится.
|
||||||
|
\item Кроме того, такая организация не~исключает влияния
|
||||||
|
конфигурационных параметров на среду исполнения: например,
|
||||||
|
изменение переменных +IFS+ и +LANG+ может существенно повлиять
|
||||||
|
на результат интерпретации init-скрипта.
|
||||||
|
\item Интерпретация этих файлов требует запуска еще одного экземпляра
|
||||||
|
оболочки, что приводит к задержкам при загрузке\footnote{Прим.
|
||||||
|
перев.: Здесь автор несколько заблуждается. Скрипты, включенные
|
||||||
|
через директиву +source+, исполняются тем же экземпляром
|
||||||
|
оболочки, что и вызвавший их скрипт.}.
|
||||||
|
\item Файлы из +/etc/sysconfig+ часто пытаются использовать в качестве
|
||||||
|
суррогатной замены файлов конфигурации для тех демонов, которые
|
||||||
|
не~имеют встроенной поддержки конфигурационных файлов. В
|
||||||
|
частности, вводятся специальные переменные, позволяющие задать
|
||||||
|
аргументы командной строки, используемые при запуске демона.
|
||||||
|
Встроенная поддержка конфигурационных файлов является более
|
||||||
|
удобной альтернативой такому подходу, ведь, глядя на ключи
|
||||||
|
<<+-k+>>, <<+-a+>>, <<+-f+>>, трудно догадаться об их
|
||||||
|
назначении. Очень часто, из-за ограниченности словаря, на
|
||||||
|
различных демонов одни и те же ключи действуют совершенно
|
||||||
|
по-разному (для одного демона ключ <<+-f+>> содержит указание
|
||||||
|
демонизироваться при запуске, в то время как для другого эта
|
||||||
|
опция действует прямо противоположным образом.) В отличие от
|
||||||
|
конфигурационных файлов, строка запуска не~может включать
|
||||||
|
полноценных комментариев.
|
||||||
|
\item Некоторые из настроек, задаваемых в +/etc/sysconfig+, являются
|
||||||
|
полностью избыточными. Например, во многие дистрибутивах
|
||||||
|
подобным методом указывается, установлены ли аппаратные часы
|
||||||
|
компьютера по Гринвичу, или по местному времени. Однако эта же
|
||||||
|
настройка задается третьей строкой файла +/etc/adjtime+,
|
||||||
|
поддерживаемого во всех дистрибутивах. Использование
|
||||||
|
избыточного и не~стандартизированного параметра конфигурации
|
||||||
|
только добавляет путаницу и не~несет никакой пользы.
|
||||||
|
\item Многие файлы настроек из +/etc/sysconfig+ позволяют отключать
|
||||||
|
запуск соответствующей службы. Однако эта операция уже
|
||||||
|
поддерживается штатно для всех служб, через команды
|
||||||
|
+systemctl enable+/+disable+ (или +chkconfig on+/+off+).
|
||||||
|
Добавление дополнительного уровня настройки не~приносит никакой
|
||||||
|
пользы и лишь усложняет работу администратора.
|
||||||
|
\item Что касается списка принудительно загружаемых модулей ядра~--- в
|
||||||
|
настоящее время существуют куда более удобные пути для
|
||||||
|
автоматической подгрузки модулей при загрузке системы. Например,
|
||||||
|
многие модули автоматически подгружаются +udev+'ом при
|
||||||
|
обнаружении соответствующего оборудования. Этот же принцип
|
||||||
|
распространяется на ACPI и другие высокоуровневые технологии.
|
||||||
|
Одно из немногих исключений из этого правила~--- к сожалению, в
|
||||||
|
настоящее время не~поддерживается автоматическая загрузка
|
||||||
|
модулей на основании информации о возможностях процессора,
|
||||||
|
однако это будет исправлено в ближайшем будущем. В случае, если
|
||||||
|
нужный вам модуль ядра все же не~может быть подгружен
|
||||||
|
автоматически, все равно существует гораздо более удобные методы
|
||||||
|
указать его принудительную подгрузку~--- например, создав
|
||||||
|
соответствующий файл в каталоге
|
||||||
|
\hreftt{http://0pointer.de/public/systemd-man/modules-load.d.html}{/etc/modules-load.d/}
|
||||||
|
(стандартный метод настройки принудительной подгрузки модулей).
|
||||||
|
\item И наконец, хотелось бы отметить, что каталог +/etc+ определен как
|
||||||
|
место для хранения системных настроек (<<Host-specific system
|
||||||
|
configuration>>, согласно FHS). Наличие внутри него подкаталога
|
||||||
|
+sysconfig+, который тоже содержит системную конфигурацию,
|
||||||
|
является очевидно избыточным.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Что же можно предложить в качестве современной, совместимой с systemd
|
||||||
|
альтернативы настройке системы через файлы в этих каталогах? Ниже приведены
|
||||||
|
несколько рекомендаций, как лучше поступить с задаваемыми таким образом параметрами
|
||||||
|
конфигурации:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Попробуйте просто отказаться от них. Если они полностью избыточны (например,
|
||||||
|
настройка аппаратных часов на Гринвич/местное время), то убрать
|
||||||
|
их будет довольно легко (если не~рассматривать вопросы
|
||||||
|
обеспечения совместимости). Если аналогичные по смыслу опции
|
||||||
|
штатно поддерживаются systemd, нет никакого смысла дублировать
|
||||||
|
их где-то еще (перечень опций, которые можно задать для любой
|
||||||
|
службы, приведен на страницах справки
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{systemd.exec(5)}
|
||||||
|
и
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.service.html}{systemd.service(5)}.)
|
||||||
|
Если же ваша настройка просто добавляет еще один уровень
|
||||||
|
отключения запуска службы~--- не~плодите лишние сущности,
|
||||||
|
откажитесь от нее.
|
||||||
|
\item Найдите для них более подходящее место. Например, в случае с
|
||||||
|
некоторыми общесистемными настройками (такими, как локаль или
|
||||||
|
часовой пояс), мы надеемся аккуратно подтолкнуть дистрибутивы в
|
||||||
|
правильно направлении (см. предыдущий эпизод).
|
||||||
|
\item Добавьте их поддержку в штатную систему настройки демона через
|
||||||
|
собственные файлы конфигурации. К счастью, большинство служб,
|
||||||
|
работающих в Linux, являются свободным программным обеспечением,
|
||||||
|
так что сделать это довольно просто.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Существует лишь одна причина поддерживать эти файлы еще некоторое
|
||||||
|
время: необходимо обеспечить совместимость при обновлении. Тем не~менее, как
|
||||||
|
минимум в новых пакетах, от этих файлов лучше отказаться.
|
||||||
|
|
||||||
|
Если требование совместимости критично, вы можете задействовать эти
|
||||||
|
конфигурационные файлы даже в том случае, если настраиваете службы через
|
||||||
|
штатные unit-файлы systemd. Если ваш файл из +sysconfig+ содержит лишь
|
||||||
|
определения переменных, можно воспользоваться опцией
|
||||||
|
+EnvironmentFile=-/etc/sysconfig/foobar+ (подробнее об этой опции см.
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{systemd.exec(5)}),
|
||||||
|
позволяющей прочитать из файла набор переменных окружения, который будет
|
||||||
|
установлен при запуске службы. Если же для задания настроек вам необходим
|
||||||
|
полноценный язык программирования~--- ничто не~мешает им воспользоваться.
|
||||||
|
Например, вы можете создайть в +/usr/lib/<your package>/+ простой скрипт,
|
||||||
|
который включает соответствующие файлы, а затем запускает бинарник демона через
|
||||||
|
+exec+. После чего достаточно просто указать этот скрипт в опции +ExecStart=+
|
||||||
|
вместо бинарника демона.
|
||||||
|
|
||||||
|
\section{Экземпляры служб}
|
||||||
|
\label{sec:instances}
|
||||||
|
|
||||||
|
Большинство служб в Linux/Unix являются одиночными (singleton): в каждый момент
|
||||||
|
времени на данном хосте работает только один экземпляр службы. В качестве
|
||||||
|
примера таких одиночных служб можно привести Syslogd, Postfix, Apache. Однако,
|
||||||
|
существуют службы, запускающие по несколько экземпляров себя на одном хосте.
|
||||||
|
Например, службы наподобие Dovecot IMAP запускают по одному экземпляру на каждый
|
||||||
|
локальный порт и/или IP-адрес. Другой пример, который можно встретить
|
||||||
|
практически во всех системах~--- \emph{getty}, небольшая служба, запускающаяся на
|
||||||
|
каждом TTY (от +tty1+ до +tty6+). На некоторых серверах, в зависимости от
|
||||||
|
сделанных администратором настроек или параметров загрузки, могут запускаться
|
||||||
|
дополнительные экземпляры getty, для подключаемых к COM-портам терминалов или
|
||||||
|
для консоли системы виртуализации. Еще один пример службы, работающей в
|
||||||
|
нескольких экземплярах (по крайней мере, в мире systemd)~--- \emph{fsck},
|
||||||
|
программа проверки файловой системы, которая запускается по одному экземпляру
|
||||||
|
на каждое блочное устройство, требующее такой проверки. И наконец, стоит
|
||||||
|
упомянуть службы с активацией в стиле inetd~--- при обращении через сокет, по
|
||||||
|
одному экземпляру на каждое соединение. В этой статье я попытаюсь рассказать,
|
||||||
|
как в systemd реализовано управление <<многоэкземплярными>> службами, и какие
|
||||||
|
выгоды системный администратор может извлечь из этой возможности.
|
||||||
|
|
||||||
|
Если вы читали предыдущие статьи из этого цикла, вы, скорее всего, уже знаете,
|
||||||
|
что службы systemd именуются по схеме \emph{foobar}+.service+, где
|
||||||
|
\emph{foobar}~--- строка, идентифицирующая службу (проще говоря, ее имя), а
|
||||||
|
+.service+~--- суффикс, присутствующий в именах всех файлов конфигурации служб.
|
||||||
|
Сами эти файлы могут находиться в каталогах +/etc/systemd/systemd+ и
|
||||||
|
+/lib/systemd/system+ (а также, возможно, и в других). Для служб, работающих в
|
||||||
|
нескольких экземплярах, эта схема становится немного сложнее:
|
||||||
|
\emph{foobar}+@+\emph{quux}+.service+, где \emph{foobar}~--- имя службы,
|
||||||
|
общее для всех экземпляров, а \emph{quux}~--- идентификатор конкретного
|
||||||
|
экземпляра. Например, +serial-gett@ttyS2.service+~--- это служба getty для
|
||||||
|
COM-порта, запущенная на +ttyS2+.
|
||||||
|
|
||||||
|
При необходимости, экземпляры служб можно легко создать динамически. Скажем, вы
|
||||||
|
можете, безо всяких дополнительных настроек, запустить новый экземпляр getty на
|
||||||
|
последовательном порту, просто выполнив +systemctl start+ для нового экземпляра:
|
||||||
|
\begin{Verbatim}
|
||||||
|
# systemctl start serial-getty@ttyUSB0.service
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Получив такую команду, systemd сначала пытается найти файл конфигурации юнита с
|
||||||
|
именем, точно соответствующим запрошенному. Если такой файл найти не~удается
|
||||||
|
(при работе с экземплярами сервисов обычно так и происходит), из имени файла
|
||||||
|
удаляется идентификатор экземпляра, и полученное имя используется при поиске
|
||||||
|
\emph{шаблона} конфигурации. В нашем случае, если отсутствует файл с именем
|
||||||
|
+serial-getty@ttyUSB0.service+, используется файл-шаблон под названием
|
||||||
|
+serial-getty@.service+. Таким образом, для всех экземпляров данной службы,
|
||||||
|
используется один и тот же шаблон конфигурации. В случае с getty для COM-портов,
|
||||||
|
этот шаблон, поставляемый в комплекте с systemd
|
||||||
|
(файл +/lib/systemd/system/serial-getty@.service+) выглядит примерно так:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=Serial Getty on %I
|
||||||
|
BindTo=dev-%i.device
|
||||||
|
After=dev-%i.device systemd-user-sessions.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/sbin/agetty -s %I 115200,38400,9600
|
||||||
|
Restart=always
|
||||||
|
RestartSec=0
|
||||||
|
\end{Verbatim}
|
||||||
|
(Заметим, что приведенная здесь версия немного сокращена, по сравнению с реально
|
||||||
|
используемой в systemd. Удалены не~относящиеся к теме нашего обсуждения
|
||||||
|
параметры конфигурации, обеспечивающие совместимость с SysV, очистку экрана и
|
||||||
|
удаление предыдущих пользователей с текущего TTY. Если вам интересно, можете
|
||||||
|
посмотреть
|
||||||
|
\href{http://cgit.freedesktop.org/systemd/plain/units/serial-getty@.service.m4}{полную
|
||||||
|
версию}.)
|
||||||
|
|
||||||
|
Этот файл похож на обычный файл конфигурации юнита, с единственным отличием: в
|
||||||
|
нем используются спецификаторы \%I и \%i. В момент загрузки юнита, systemd
|
||||||
|
заменяет эти спецификаторы на идентификатор экземпляра службы. В нашем случае,
|
||||||
|
при обращении к экземпляру +serial-getty@ttyUSB0.service+, они заменяются на
|
||||||
|
<<+ttyUSB0+>>. Результат этой замены можно проверить, например, запросив
|
||||||
|
состояние для этой службы:
|
||||||
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
|
$ systemctl status serial-getty@ttyUSB0.service
|
||||||
|
serial-getty@ttyUSB0.service - Getty on ttyUSB0
|
||||||
|
Loaded: loaded (/lib/systemd/system/serial-getty@.service; static)
|
||||||
|
Active: active (running) since Mon, 26 Sep 2011 04:20:44 +0200; 2s ago
|
||||||
|
Main PID: 5443 (agetty)
|
||||||
|
CGroup: name=systemd:/system/getty@.service/ttyUSB0
|
||||||
|
\mytextSFii{} 5443 /sbin/agetty -s ttyUSB0 115200,38400,9600
|
||||||
|
\end{Verbatim}
|
||||||
|
Собственно, это и есть ключевая идея организации экземпляров служб. Как видите,
|
||||||
|
systemd предоставляет простой в использовании механизм шаблонов, позволяющих
|
||||||
|
динамически создавать экземпляры служб. Добавим несколько дополнительных
|
||||||
|
замечаний, позволяющих эффективно использовать этот механизм:
|
||||||
|
|
||||||
|
Вы можете создавать дополнительные экземпляры таких служб, просто добавляя
|
||||||
|
символьные ссылки в каталоги +*.wants/+. Например, чтобы обеспечить запуск getty
|
||||||
|
на ttyUSB0 при каждой загрузке, достаточно создать такую ссылку:
|
||||||
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
|
# ln -s /lib/systemd/system/serial-getty@.service \tbs{}
|
||||||
|
/etc/systemd/system/getty.target.wants/serial-getty@ttyUSB0.service
|
||||||
|
\end{Verbatim}
|
||||||
|
При этом файл конфигурации, на который указывает ссылка (в нашем случае
|
||||||
|
+serial-getty@.service+), будет вызван с тем именем экземпляра, которое указанно
|
||||||
|
в названии этой ссылки (в нашем случае~--- +ttyUSB0+).
|
||||||
|
|
||||||
|
Вы не~сможете обратиться к юниту-шаблону без указания идентификатора экземпляра.
|
||||||
|
В частности, команда +systemctl start serial-getty@.service+ завершится ошибкой.
|
||||||
|
|
||||||
|
Иногда возникает необходимость отказаться от использования общего шаблона
|
||||||
|
для конкретного экземпляра (т.е. конфигурация данного экземпляра настолько
|
||||||
|
сильно отличается от конфигурации остальных экземпляров данной службы, что
|
||||||
|
механизм шаблонов оказывается неэффективен). Специально для таких случаев, в
|
||||||
|
systemd и заложен предварительный поиск файла с именем, точно соответствующим
|
||||||
|
указанному (прежде чем использовать общий шаблон). Таким образом, вы можете
|
||||||
|
поместить файл с именем, точно соответствующим полному титулу экземпляра, в
|
||||||
|
каталог +/etc/systemd/system/+~--- и содержимое этого файла, при обращении
|
||||||
|
к выбранному экземпляру, полностью перекроет все настройки, сделанные в общем
|
||||||
|
шаблоне.
|
||||||
|
|
||||||
|
В приведенном выше файле, в некоторых местах используется спецификатор +%I+, а
|
||||||
|
в других~--- +%i+. У вас может возникнуть закономерный вопрос~--- чем они
|
||||||
|
отличаются? +%i+ всегда точно соответствует идентификатору экземпляра, в то
|
||||||
|
время, как +%I+ соответствует экранированной (escaped) версии этого
|
||||||
|
идентификатора. Когда идентификатор не~содержит спецсимволов (например,
|
||||||
|
+ttyUSB0+). Но имена устройств, например, содержат слеши (<</>>), которые
|
||||||
|
не~могут присутствовать в имени юнита (и в имени файла на Unix). Поэтому, перед
|
||||||
|
использованием такого имени в качестве идентификатора устройства, оно должно
|
||||||
|
быть экранировано~--- <</>> заменяются на <<->>, а большинство других
|
||||||
|
специальных символов (включая <<->>) заменяются последовательностями вида
|
||||||
|
+\xAB+, где AB~--- ASCII-код символа, записанный в шестнадцатеричной системе
|
||||||
|
счисления\footnote{Согласен, этот алгоритм дает на выходе не~очень читабельный
|
||||||
|
результат. Но этим грешат практически все алгоритмы экранирования. В данном
|
||||||
|
случае, были использован механизм экранирования из udev, с одним изменением. В
|
||||||
|
конце концов, нам нужно было выбрать что-то. Если вы собираетесь комментировать
|
||||||
|
наш алгоритм экранирования~--- пожалуйста, оставьте свой адрес, чтобы я
|
||||||
|
мог приехать к вам и раскрасить ваш сарай для велосипедов в синий с желтыми
|
||||||
|
полосами. Спасибо!}. Например, чтобы обратиться
|
||||||
|
последовательному USB-порту по его адресу на шине, нам нужно использовать имя
|
||||||
|
наподобие +serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0+. Экранированная
|
||||||
|
версия этого имени~---
|
||||||
|
+serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0+. +%I+ будет
|
||||||
|
ссылаться на первую из этих строк, +%i+~--- на вторую. С практической точки
|
||||||
|
зрения, это означает, что спецификатор +%i+ можно использовать в том случае,
|
||||||
|
когда надо сослаться на имена других юнитов, например, чтобы описать
|
||||||
|
дополнительные зависимости (в случае с +serial-getty@.service+, этот
|
||||||
|
спецификатор используется для ссылки на юнит +dev-%i.device+, соответствующий
|
||||||
|
одноименному устройству). В то время как +%I+ удобно использовать в командной
|
||||||
|
строке (+ExecStart+) и для формирования читабельных строк описания. Рассмотрим
|
||||||
|
работу этих принципов на примере нашего юнит-файла:
|
||||||
|
\begin{landscape}
|
||||||
|
\begin{Verbatim}[fontsize=\small,commandchars=|\{\}]
|
||||||
|
# systemctl start 'serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.service'
|
||||||
|
# systemctl status 'serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.service'
|
||||||
|
serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.service - Serial Getty on serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0
|
||||||
|
Loaded: loaded (/lib/systemd/system/serial-getty@.service; static)
|
||||||
|
Active: active (running) since Mon, 26 Sep 2011 05:08:52 +0200; 1s ago
|
||||||
|
Main PID: 5788 (agetty)
|
||||||
|
CGroup: name=systemd:/system/serial-getty@.service/serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0
|
||||||
|
|mytextSFii{} 5788 /sbin/agetty -s serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0 115200 38400 9600
|
||||||
|
\end{Verbatim}
|
||||||
|
\end{landscape}
|
||||||
|
Как видите, в качестве идентификатора экземпляра используется экранированная
|
||||||
|
версия, в то время как в строке описания и в командной строке +getty+
|
||||||
|
используется неэкранированная версия. Как и предполагалось.
|
||||||
|
|
||||||
|
(Небольшое замечание: помимо +%i+ и +%I+, существует еще несколько
|
||||||
|
спецификаторов, и большинство из них доступно и в обычных файлах конфигурации
|
||||||
|
юнитов, а не~только в шаблонах. Подробности можно посмотреть на
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.unit.html}{странице
|
||||||
|
руководства}, содержащей полный перечень этих спецификаторов с краткими
|
||||||
|
пояснениями.)
|
||||||
|
|
||||||
|
\section{Службы с активацией в стиле inetd}
|
||||||
|
|
||||||
|
В одной из предыдущих глав (гл.~\ref{sec:convert}) я рассказывал, как можно
|
||||||
|
преобразовать SysV init-скрипт в юнит-файл systemd. В этой главе мы рассмотрим,
|
||||||
|
как провести аналогичное преобразование для служб inetd.
|
||||||
|
|
||||||
|
Начнем с небольшого экскурса в историю вопроса. По давно устоявшейся традиции,
|
||||||
|
inetd считается одной из базовых служб Unix-систем. Работая как суперсервер, он
|
||||||
|
слушает сетевые сокеты от имени различных служб, и активирует соответствующие
|
||||||
|
службы при поступлении на эти сокеты входящих соединений. Таким образом, он
|
||||||
|
обеспечивает механизм активации по запросу (on-demand activation). Подобный
|
||||||
|
подход избавляет от необходимости держать постоянно работающими все серверные
|
||||||
|
процессы, что позволяет поддерживать множество служб даже на системах с очень
|
||||||
|
ограниченными ресурсами. На протяжении многих лет, дистрибутивы Linux
|
||||||
|
поставляются с различными реализациями inetd. Наиболее популярные из них~--- BSD
|
||||||
|
inetd и xinetd. Хотя inetd во многих дистрибутивах до сих пор устанавливается по
|
||||||
|
умолчанию, сейчас уже он редко используется для запуска сетевых служб~--- теперь
|
||||||
|
большинство из них запускаются автономно при загрузке системы (основной
|
||||||
|
аргумент в пользу такой схемы~--- она позволяет обеспечить более высокую
|
||||||
|
производительность служб).
|
||||||
|
|
||||||
|
Одной из ключевых возможностей systemd (а также launchd от Apple) является
|
||||||
|
сокет-активация~--- тот самый механизм, давным-давно реализованный inetd,
|
||||||
|
однако в данном случае ключевые цели немного другие. Сокет-активация в стиле
|
||||||
|
systemd прежде всего ориентирована на локальные сокеты (+AF_UNIX+), хотя
|
||||||
|
поддерживаются также и сетевые сокеты (+AF_INET+). И более важное отличие~---
|
||||||
|
сокет-активация в systemd обеспечивает не~только экономию системных ресурсов,
|
||||||
|
но также и эффективную параллелизацию работы (так как она
|
||||||
|
позволяет запускать клиентов и серверы одновременно, непосредственно после
|
||||||
|
создания сокета), упрощение процесса конфигурации (отпадает необходимость явно
|
||||||
|
указывать зависимости между службами) и увеличение надежности (служебный или
|
||||||
|
экстренный, в случае падения, перезапуск службы не~приводит к недоступности
|
||||||
|
сокета). Тем не~менее, systemd ничуть не~хуже inetd может запускать службы в
|
||||||
|
ответ на входящие сетевые соединения.
|
||||||
|
|
||||||
|
Любая сокет-активация требует соответствующей поддержки со стороны самой
|
||||||
|
запускаемой службы. systemd предоставляет очень простой интерфейс, который может
|
||||||
|
быть использован службами для обеспечения сокет-активации. В основе этого
|
||||||
|
\href{http://0pointer.de/blog/projects/socket-activation.html}{простого и
|
||||||
|
минималистичного} механизма лежит функция
|
||||||
|
\hreftt{http://0pointer.de/public/systemd-man/sd_listen_fds.html}{sd\_listen\_fds()}.
|
||||||
|
Однако, интерфейс, традиционно используемый в inetd, еще проще. Он позволяет
|
||||||
|
передавать запускаемой службе только один сокет, который формируется из потоков
|
||||||
|
STDIN и STDOUT запущенного процесса. Поддержка этого механизма также
|
||||||
|
присутствует в systemd~--- для обеспечения совместимости с множеством служб
|
||||||
|
поддерживающих сокет-активацию только в стиле inetd.
|
||||||
|
|
||||||
|
Прежде, чем мы перейдем к примерам, рассмотрим три различных схемы, использующих
|
||||||
|
сокет-активацию:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item \textbf{Сокет-активация, ориентированная на параллелизацию,
|
||||||
|
упрощение и надежность:} сокеты создаются на ранних стадиях
|
||||||
|
загрузки, и единственный экземпляр службы тут же начинает
|
||||||
|
обслуживать все поступающие запросы. Такая схема подходит для
|
||||||
|
часто используемых системных служб~--- очевидно, что такие
|
||||||
|
службы лучше запускать как можно раньше, и по вомзожности
|
||||||
|
параллельно. В качестве примера можно привести D-Bus и Syslog.
|
||||||
|
\item \textbf{Сокет-активация для одиночных служб:} сокеты создаются на
|
||||||
|
ранних стадиях загрузки, и единственный экземпляр службы
|
||||||
|
запускается при получении входящих запросов. Такая схема больше
|
||||||
|
подходит для редко используемых служб, позволяя обеспечить
|
||||||
|
экономию системных ресурсов и уменьшить время загрузки, просто
|
||||||
|
отложив активацию службы до того момента, когда она
|
||||||
|
действительно понадобится. Пример~--- CUPS.
|
||||||
|
\item \textbf{Сокет-активация для служб, запускающих по экземпляру на
|
||||||
|
каждое соединение:} сокеты создаются на ранней стадии загрузки,
|
||||||
|
и при каждом входящем соединении создается экземпляр службы,
|
||||||
|
которому передается сокет соединения (слушающий сокет при этом
|
||||||
|
остается у суперсервера, inetd или systemd). Эта схема подходит
|
||||||
|
для редко используемых служб, не~критичных по производительности
|
||||||
|
(каждый новый процесс занимает сравнительно немного ресурсов).
|
||||||
|
Пример: SSH.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
Описанные схемы отнюдь не~эквивалентны с точки зрения производительности. Первая
|
||||||
|
и вторая схема, после завершения запуска службы, обеспечивают точно такую же
|
||||||
|
производительность, как и в случае с независимой (stand-alone) службой (т.е.
|
||||||
|
службой, запущенной без использования суперсервера и сокет-активации), так как
|
||||||
|
слушающий сокет передается непосредственно процессу службы, и дальнейшая
|
||||||
|
обработка входящих соединений происходит точно так же, как и в независимой
|
||||||
|
службе. В то же время, производительность третьей из предложенных схем порою
|
||||||
|
оставляет желать лучшего: каждое входящее соединение порождает еще один процесс
|
||||||
|
службы, что, при большом количестве соединений, может привести к значительному
|
||||||
|
потреблению системных ресурсов. Впрочем, эта схема имеет и свои достоинства.
|
||||||
|
В частности, обеспечивается эффективная изоляция обработки клиентских запросов
|
||||||
|
и, кроме того, выбор такой схемы активации значительно упрощает процесс
|
||||||
|
разработки службы.
|
||||||
|
|
||||||
|
В systemd наибольшее внимание уделяется первой из этих схем, однако остальные
|
||||||
|
две тоже прекрасно поддерживаются. В свое время, я
|
||||||
|
\href{http://0pointer.de/blog/projects/socket-activation2.html}{рассказывал},
|
||||||
|
какие изменения в коде службы нужно сделать для обеспечения работы по второй
|
||||||
|
схеме, на примере сервера CUPS. Что же касается inetd, то он предназначен прежде
|
||||||
|
всего для работы по третьей схеме, хотя поддерживает и вторую (но не~первую).
|
||||||
|
Именно из-за специфики этой схемы inetd получил репутации <<медленного>> (что,
|
||||||
|
на самом деле, немного несправедливо).
|
||||||
|
|
||||||
|
Итак, изучив теоретическую сторону вопроса, перейдем к практике и рассмотрим,
|
||||||
|
как inetd-служба может быть интегрирована с механизмами сокет-активации systemd.
|
||||||
|
В качестве примера возьмем SSH, известную и широко распространенную службу. На
|
||||||
|
большинстве систем, где она используется, частота обращений к ней не~превышает
|
||||||
|
одного раза в час (как правило, она \emph{значительно} меньше этой величины).
|
||||||
|
SSH уже очень давно поддерживает сокет-активацию в стиле inetd, согласно третьей
|
||||||
|
схеме. Так как необходимость в этой службе возникает сравнительно редко, и
|
||||||
|
число одновременно работающих процессов обычно невелико, она хорошо подходит для
|
||||||
|
использования по этой схеме. Перерасход системных ресурсов должен быть
|
||||||
|
незначителен: большую часть времени такая служба фактически не~выполняется и
|
||||||
|
не~тратит ресурсы. Когда кто-либо начинает сеанс удаленной работы, она
|
||||||
|
запускается, и останавливается немедленно по завершению сеанса, освобождая
|
||||||
|
ресурсы. Что ж, посмотрим, как в systemd можно воспользоваться режимом
|
||||||
|
совместимости с inetd и обеспечить сокет-активацию SSH.
|
||||||
|
|
||||||
|
Так выглядит строка с конфигурацией службы SSH для классического inetd:
|
||||||
|
\begin{Verbatim}
|
||||||
|
ssh stream tcp nowait root /usr/sbin/sshd sshd -i
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Аналогичный фрагмент конфигурации для xinetd:
|
||||||
|
\begin{Verbatim}
|
||||||
|
service ssh {
|
||||||
|
socket_type = stream
|
||||||
|
protocol = tcp
|
||||||
|
wait = no
|
||||||
|
user = root
|
||||||
|
server = /usr/sbin/sshd
|
||||||
|
server_args = -i
|
||||||
|
}
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Б\'{о}льшая часть опций интуитивно понятна, кроме того, нетрудно заметить, что оба
|
||||||
|
этих текста повествуют об одном и том же. Однако, некоторые моменты не~вполне
|
||||||
|
очевидны. Например, номер прослушиваемого порта (22) не~указывается в явном
|
||||||
|
виде. Он определяется путем поиска имени службы в базе данных +/etc/services+.
|
||||||
|
Подобный подход был некогда весьма популярен в Unix, но сейчас он уже постепенно
|
||||||
|
выходит из моды, и поэтому в современных версиях xinetd поддерживается возможность
|
||||||
|
явного указания номера порта. Одна из наиболее интересных настроек названа
|
||||||
|
не~очень очевидно~--- +nowait+ (+wait=no+). Она определяет, будет ли служба
|
||||||
|
работать по второй (+wait+) или третьей (+nowait+) схеме. И наконец, ключ +-i+
|
||||||
|
активирует inetd-режим в SSH-сервере (без этого ключа он работает в независимом
|
||||||
|
режиме).
|
||||||
|
|
||||||
|
На языке systemd эти фрагменты конфигурации превращаются в два файла. Первый из
|
||||||
|
них, +sshd.socket+, содержит информацию о прослушиваемом сокете:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=SSH Socket for Per-Connection Servers
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=22
|
||||||
|
Accept=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Смысл большинства опций вполне очевиден. Сделаю лишь пару замечаний.
|
||||||
|
+Accept=yes+ соответствует режиму +nowait+. Надеюсь, предложенное мною название
|
||||||
|
более точно отражает смысл опции~--- в режиме +nowait+ суперсвервер сам вызывает
|
||||||
|
+accept()+ для слушающего сокета, в то время как в режиме +wait+ эта работа
|
||||||
|
ложится на процесс службы. Опция +WantedBy=sockets.target+ обеспечивает
|
||||||
|
активацию данного юнита в нужный момент при загрузке системы.
|
||||||
|
|
||||||
|
Второй из этих файлов~--- +sshd@.service+:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=SSH Per-Connection Server
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/usr/sbin/sshd -i
|
||||||
|
StandardInput=socket
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Большинство представленных здесь опции, как и раньше, понятны интуитивно. Особое
|
||||||
|
внимание стоит обратить лишь на +StandardInput=socket+, которая, собственно, и
|
||||||
|
включает для данной службы режим совместимости с inetd-активацией. Опция
|
||||||
|
+StandardInput=+ позволяет указать, куда будет подключен поток STDIN процесса
|
||||||
|
данной службы (подробности см.
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{на странице
|
||||||
|
руководства}). Задав для нее значение +socket+, мы обеспечиваем подключение
|
||||||
|
этого потока к сокету соединения, как того и требует механизм inetd-активации.
|
||||||
|
Заметим, что явно указывать опцию +StandardInput=+ в данном случае
|
||||||
|
необязательно~--- она автоматически устанавливается в то же значение, что и
|
||||||
|
+StandardInput+, если явно не~указано что-то другое. Кроме того, можно отметить
|
||||||
|
наличие <<+-+>> перед именем бинарного файла sshd. Таким образом мы указываем
|
||||||
|
systemd игнорировать код выхода процесса sshd. По умолчанию, systemd сохраняет
|
||||||
|
коды выхода для всех экземпляров службы, завершившихся с ошибкой (сбросить эту
|
||||||
|
информацию можно командой +systemctl reset-failed+). SSH
|
||||||
|
периодически откалывает подобные номера, и мы разрешаем systemd
|
||||||
|
не~регистрировать подобные <<ошибки>>.
|
||||||
|
|
||||||
|
Служба +sshd@.service+ предназначена для работы в виде независимых экземпляров
|
||||||
|
(такие службы мы рассматривали в предыдущей главе~\ref{sec:instances}). Для
|
||||||
|
каждого входящего соединения systemd будет создавать свой экземпляр этой службы,
|
||||||
|
и идентификатор экземпляра формируется на основе реквизитов соединения.
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
||||||
vim:ft=tex:tw=80:spell:spelllang=ru
|
vim:ft=tex:tw=80:spell:spelllang=ru
|
||||||
|
|||||||
Reference in New Issue
Block a user