From f1fbbf08cf35aff48592780c42d1e4b9bae51af9 Mon Sep 17 00:00:00 2001 From: nnz1024 <0comffdiz@inbox.ru> Date: Thu, 15 Dec 2011 03:23:00 +0400 Subject: [PATCH] Version v8.3 (2011-12-15 03:23) [AUTO] --- s4a.tex | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/s4a.tex b/s4a.tex index 44a6241..dc20f7d 100644 --- a/s4a.tex +++ b/s4a.tex @@ -2117,6 +2117,7 @@ systemd? вместо бинарника демона. \section{Экземпляры служб} +\label{sec:instances} Большинство служб в Linux/Unix являются одиночными (singleton): в каждый момент времени на данном хосте работает только один экземпляр службы. В качестве @@ -2245,8 +2246,8 @@ systemd и заложен предварительный поиск файла результат. Но этим грешат практически все алгоритмы экранирования. В данном случае, были использован механизм экранирования из udev, с одним изменением. В конце концов, нам нужно было выбрать что-то. Если вы собираетесь комментировать -наш алгоритм экранирования~--- пожалуйста, также укажите, где вы живете, чтобы я -мог приехать к вам и раскрасить ваш велосипедный гараж в синий с желтыми +наш алгоритм экранирования~--- пожалуйста, оставьте свой адрес, чтобы я +мог приехать к вам и раскрасить ваш сарай для велосипедов в синий с желтыми полосами. Спасибо!}. Например, чтобы обратиться последовательному USB-порту по его адресу на шине, нам нужно использовать имя наподобие +serial/by-path/pci-0000:00:1d.0-usb-0:1.4:1.1-port0+. Экранированная @@ -2286,7 +2287,7 @@ 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. В этой главе мы рассмотрим +преобразовать SysV init-скрипт в юнит-файл systemd. В этой главе мы рассмотрим, как провести аналогичное преобразование для служб inetd. Начнем с небольшого экскурса в историю вопроса. По давно устоявшейся традиции, @@ -2354,10 +2355,129 @@ STDIN и STDOUT запущенного процесса. Поддержка эт остается у суперсервера, inetd или systemd). Эта схема подходит для редко используемых служб, не~критичных по производительности (каждый новый процесс занимает сравнительно немного ресурсов). - Пример:SSH. + Пример: 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}