Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c9a949351 | ||
|
|
f1fbbf08cf | ||
|
|
0905f9aa1d |
318
s4a.tex
318
s4a.tex
@@ -16,7 +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{\llangl}{\reflectbox{\rotatebox[origin=c]{270}{$\neg$}}}
|
\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}
|
||||||
@@ -581,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+), располагаются в
|
||||||
@@ -2112,6 +2117,7 @@ systemd?
|
|||||||
вместо бинарника демона.
|
вместо бинарника демона.
|
||||||
|
|
||||||
\section{Экземпляры служб}
|
\section{Экземпляры служб}
|
||||||
|
\label{sec:instances}
|
||||||
|
|
||||||
Большинство служб в Linux/Unix являются одиночными (singleton): в каждый момент
|
Большинство служб в Linux/Unix являются одиночными (singleton): в каждый момент
|
||||||
времени на данном хосте работает только один экземпляр службы. В качестве
|
времени на данном хосте работает только один экземпляр службы. В качестве
|
||||||
@@ -2193,7 +2199,7 @@ serial-getty@ttyUSB0.service - Getty on ttyUSB0
|
|||||||
Active: active (running) since Mon, 26 Sep 2011 04:20:44 +0200; 2s ago
|
Active: active (running) since Mon, 26 Sep 2011 04:20:44 +0200; 2s ago
|
||||||
Main PID: 5443 (agetty)
|
Main PID: 5443 (agetty)
|
||||||
CGroup: name=systemd:/system/getty@.service/ttyUSB0
|
CGroup: name=systemd:/system/getty@.service/ttyUSB0
|
||||||
\llangl{} 5443 /sbin/agetty -s ttyUSB0 115200,38400,9600
|
\mytextSFii{} 5443 /sbin/agetty -s ttyUSB0 115200,38400,9600
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Собственно, это и есть ключевая идея организации экземпляров служб. Как видите,
|
Собственно, это и есть ключевая идея организации экземпляров служб. Как видите,
|
||||||
systemd предоставляет простой в использовании механизм шаблонов, позволяющих
|
systemd предоставляет простой в использовании механизм шаблонов, позволяющих
|
||||||
@@ -2203,8 +2209,8 @@ systemd предоставляет простой в использовании
|
|||||||
Вы можете создавать дополнительные экземпляры таких служб, просто добавляя
|
Вы можете создавать дополнительные экземпляры таких служб, просто добавляя
|
||||||
символьные ссылки в каталоги +*.wants/+. Например, чтобы обеспечить запуск getty
|
символьные ссылки в каталоги +*.wants/+. Например, чтобы обеспечить запуск getty
|
||||||
на ttyUSB0 при каждой загрузке, достаточно создать такую ссылку:
|
на ttyUSB0 при каждой загрузке, достаточно создать такую ссылку:
|
||||||
\begin{Verbatim}
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
# ln -s /lib/systemd/system/serial-getty@.service \
|
# ln -s /lib/systemd/system/serial-getty@.service \tbs{}
|
||||||
/etc/systemd/system/getty.target.wants/serial-getty@ttyUSB0.service
|
/etc/systemd/system/getty.target.wants/serial-getty@ttyUSB0.service
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
При этом файл конфигурации, на который указывает ссылка (в нашем случае
|
При этом файл конфигурации, на который указывает ссылка (в нашем случае
|
||||||
@@ -2240,15 +2246,9 @@ systemd и заложен предварительный поиск файла
|
|||||||
результат. Но этим грешат практически все алгоритмы экранирования. В данном
|
результат. Но этим грешат практически все алгоритмы экранирования. В данном
|
||||||
случае, были использован механизм экранирования из udev, с одним изменением. В
|
случае, были использован механизм экранирования из udev, с одним изменением. В
|
||||||
конце концов, нам нужно было выбрать что-то. Если вы собираетесь комментировать
|
конце концов, нам нужно было выбрать что-то. Если вы собираетесь комментировать
|
||||||
наш алгоритм экранирования~--- пожалуйста, также укажите, где вы живете, чтобы я
|
наш алгоритм экранирования~--- пожалуйста, оставьте свой адрес, чтобы я
|
||||||
мог приехать к вам и раскрасить ваш велосипедный гараж в синий с желтыми
|
мог приехать к вам и раскрасить ваш сарай для велосипедов в синий с желтыми
|
||||||
полосами. Спасибо!}\,\footnote{Прим. перев.: В предыдущем примечании автор снова
|
полосами. Спасибо!}. Например, чтобы обратиться
|
||||||
намекает на Паркинсовский Закон Тривиальности. Действительно, выбор алгоритма
|
|
||||||
экранирования практически не~влияет ни на работу systemd, ни на управлением им
|
|
||||||
(файлы/юниты с экранированными именами, как правило либо создаются специальными
|
|
||||||
программами-генераторами, либо формируются systemd на лету; при выводе состояния
|
|
||||||
показываются и неэкранированные имена; при вводе команд, как обычно, на
|
|
||||||
помощь приходит автодополнение оболочки).}. Например, чтобы обратиться
|
|
||||||
последовательному USB-порту по его адресу на шине, нам нужно использовать имя
|
последовательному USB-порту по его адресу на шине, нам нужно использовать имя
|
||||||
наподобие +serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0+. Экранированная
|
наподобие +serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0+. Экранированная
|
||||||
версия этого имени~---
|
версия этого имени~---
|
||||||
@@ -2262,7 +2262,7 @@ systemd и заложен предварительный поиск файла
|
|||||||
строке (+ExecStart+) и для формирования читабельных строк описания. Рассмотрим
|
строке (+ExecStart+) и для формирования читабельных строк описания. Рассмотрим
|
||||||
работу этих принципов на примере нашего юнит-файла:
|
работу этих принципов на примере нашего юнит-файла:
|
||||||
\begin{landscape}
|
\begin{landscape}
|
||||||
\begin{Verbatim}[fontsize=\small]
|
\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 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'
|
# 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
|
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
|
||||||
@@ -2270,7 +2270,7 @@ serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.
|
|||||||
Active: active (running) since Mon, 26 Sep 2011 05:08:52 +0200; 1s ago
|
Active: active (running) since Mon, 26 Sep 2011 05:08:52 +0200; 1s ago
|
||||||
Main PID: 5788 (agetty)
|
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
|
CGroup: name=systemd:/system/serial-getty@.service/serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0
|
||||||
5788 /sbin/agetty -s serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0 115200 38400 9600
|
|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{Verbatim}
|
||||||
\end{landscape}
|
\end{landscape}
|
||||||
Как видите, в качестве идентификатора экземпляра используется экранированная
|
Как видите, в качестве идентификатора экземпляра используется экранированная
|
||||||
@@ -2284,6 +2284,294 @@ serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.
|
|||||||
руководства}, содержащей полный перечень этих спецификаторов с краткими
|
руководства}, содержащей полный перечень этих спецификаторов с краткими
|
||||||
пояснениями.)
|
пояснениями.)
|
||||||
|
|
||||||
|
\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 будет создавать свой экземпляр этой службы,
|
||||||
|
причем идентификатор экземпляра формируется на основе реквизитов соединения.
|
||||||
|
|
||||||
|
Быть может, вы спросите: почему для настройки inetd-службы в systemd требуется
|
||||||
|
два файла конфигурации, а не~один? Отвечаем: чтобы избежать излишнего
|
||||||
|
усложнения, мы обеспечиваем максимально прозрачную связь между работающими
|
||||||
|
юнитами и соответствующими им юнит-файлами. Такой подход позволяет независимо
|
||||||
|
оперировать юнитом сокета и юнитами соответствующих служб при формировании графа
|
||||||
|
зависимостей и при управлении юнитами. В частности, вы можете остановить
|
||||||
|
(удалить) сокет, не~затрагивая уже работающие экземпляры соответствующей службы,
|
||||||
|
или остановить любой из этих экземпляров, не~трогая другие экземпляры и сам
|
||||||
|
сокет.
|
||||||
|
|
||||||
|
Посмотрим, как наш пример будет работать. После того, как мы поместим оба
|
||||||
|
предложенных выше файла в каталог +/etc/systemd/system+, мы сможем включить
|
||||||
|
сокет (то есть, обеспечить его активацию при каждой нормальной загрузке) и
|
||||||
|
запустить его (то есть активировать в текущем сеансе работы):
|
||||||
|
|
||||||
|
\begin{Verbatim}
|
||||||
|
# systemctl enable sshd.socket
|
||||||
|
ln -s '/etc/systemd/system/sshd.socket' '/etc/systemd/system/sockets.target.wants/sshd.socket'
|
||||||
|
# systemctl start sshd.socket
|
||||||
|
# systemctl status sshd.socket
|
||||||
|
sshd.socket - SSH Socket for Per-Connection Servers
|
||||||
|
Loaded: loaded (/etc/systemd/system/sshd.socket; enabled)
|
||||||
|
Active: active (listening) since Mon, 26 Sep 2011 20:24:31 +0200; 14s ago
|
||||||
|
Accepted: 0; Connected: 0
|
||||||
|
CGroup: name=systemd:/system/sshd.socket
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Итак, наш сокет уже прослушивается, но входящих соединений на него пока
|
||||||
|
не~поступало (счетчик +Accepted:+ показывает количество принятых соединений
|
||||||
|
с момента запуска сокета, счетчик +Connected:+~--- количество активных
|
||||||
|
соединений на текущий момент).
|
||||||
|
|
||||||
|
Подключимся к нашему серверу с двух разных хостов, и посмотрим на список служб:
|
||||||
|
\begin{Verbatim}[fontsize=\small]
|
||||||
|
$ systemctl --full | grep ssh
|
||||||
|
sshd@172.31.0.52:22-172.31.0.4:47779.service loaded active running SSH Per-Connection Server
|
||||||
|
sshd@172.31.0.52:22-172.31.0.54:52985.service loaded active running SSH Per-Connection Server
|
||||||
|
sshd.socket loaded active listening SSH Socket for Per-Connection Servers
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Как и следовало ожидать, работают два экземпляра нашей службы, по одному на
|
||||||
|
соединение, и их в названиях указаны IP-адреса и TCP-порты источника и
|
||||||
|
получателя. (Заметим, что в случае с локальными сокетами типа +AF_UNIX+ там были
|
||||||
|
бы указаны идентификаторы процесса и пользователя, соответствующие подключенному
|
||||||
|
клиенту.) Таким образом, мы можем независимо выслеживать и убивать отдельные
|
||||||
|
экземпляры sshd (например, если нам нужно прервать конкретный удаленный сеанс):
|
||||||
|
\begin{Verbatim}
|
||||||
|
# systemctl kill sshd@172.31.0.52:22-172.31.0.4:47779.service
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Вот и все, что вам нужно знать о портировании inetd-служб в systemd и дальнейшем
|
||||||
|
их использовании.
|
||||||
|
|
||||||
|
Приметительно к SSH, в большинстве случаев схема с inetd-активацией позволяет
|
||||||
|
сэкономить системные ресурсы и поэтому оказывается более эффективным решением,
|
||||||
|
чем использование обычного service-файла sshd, обеспечивающего запуск одиночной
|
||||||
|
службы без использования сокет-активации (поставляется в составе пакета и может
|
||||||
|
быть включен при необходимости). В ближайшее время я собираюсь направить
|
||||||
|
соответсвующий запрос относительно нашего пакета SSH в багтрекер Fedora.
|
||||||
|
|
||||||
|
В завершение нашей дискуссии, сравним возможности xinetd и systemd, и выясним,
|
||||||
|
может ли systemd полностью заменить xinetd, или нет. Вкратце: systemd
|
||||||
|
поддерживает далеко не~все возможности xinetd и поэтому отнюдь не~является его
|
||||||
|
полноценной заменой на все случаи жизни. В частности, если вы загляните
|
||||||
|
в \href{http://linux.die.net/man/5/xinetd.conf}{список параметров конфигурации}
|
||||||
|
xinetd, вы заметите, что далеко не~все эти опции доступны в systemd. Например, в
|
||||||
|
systemd нет и не~будет встроенных служб +echo+, +time+, +daytime+, +discard+ и
|
||||||
|
т.д. Кроме того, systemd не~поддерживает TCPMUX и RPC. Впрочем, большинство этих
|
||||||
|
опций уже не~актуальны в наше время. Подавляющее большинство inetd-служб
|
||||||
|
не~используют эти опции (в частности, все имеющиеся в Fedora xinetd-службы
|
||||||
|
принадлежат к этому большинству, и не~используют перечисленные опции). Стоит
|
||||||
|
отметить, что xinetd поддерживает некоторые интересные возможности,
|
||||||
|
отсутствующие в systemd, например, списки контроля доступа для IP-адресов (IP
|
||||||
|
ACL). Однако, большинство администраторов, скорее всего, согласятся, что
|
||||||
|
настройка барндмауэра является более эффективным решением подобных задач,
|
||||||
|
а для ценителей устаревших технологий systemd предлагает поддержку tcpwrap.
|
||||||
|
С другой стороны, systemd тоже предоставляет ряд возможностей, отсутствующих в
|
||||||
|
xinetd, в частности, индивидуальный контроль над каждым экземпляром службы (см.
|
||||||
|
выше), и куда более полный
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{список настроек}
|
||||||
|
для контроля окружения, в котором запускаются экземпляры. Я надеюсь, что
|
||||||
|
возможностей systemd должно быть достаточно для решения большинства задач, а в
|
||||||
|
тех редких случаях, когда вам потребуются специфические опции xinetd~--- ничто
|
||||||
|
не~мешает вам запустить его в дополнение к systemd. Таким образом, уже сейчас в
|
||||||
|
большинстве случаев xinetd можно выкинуть из числа обязательных системных
|
||||||
|
компонентов. В некотором смысле, systemd возвращает функциональность
|
||||||
|
классического юниксового inetd и вновь возвращает ей ключевую роль в
|
||||||
|
Linux-системах.
|
||||||
|
|
||||||
|
Теперь, вооруженные этими занниями, вы можете портировать свои службы с inetd на
|
||||||
|
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