Compare commits

...

8 Commits
v9.2 ... v13.0

Author SHA1 Message Date
nnz1024
0d4aa4ac00 Version v13.0 (2012-07-17 18:57) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
6c4fa8f89f Version v12.1 (2012-07-13 20:45) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
720969dee5 Version v12.0 (2012-07-13 17:52) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
f54a9fa59c Version v11.2 (2012-07-12 17:06) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
a59846be38 Version v11.1 (2012-07-09 00:59) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
4539170bae Version v11.0 (2012-06-29 22:28) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
6a698b3e9a Version v10.0 (2012-06-03 02:30) [AUTO] 2017-08-17 23:05:39 +03:00
nnz1024
e71d20b589 Version v9.3 (2012-02-02 02:43) [AUTO] 2017-08-17 23:05:39 +03:00

504
s4a.tex
View File

@@ -2,7 +2,7 @@
\usepackage{cmap} % Copy-paste из PDF без проблем с кодировкой
\usepackage[utf8]{inputenc}
\usepackage[english,russian]{babel} % Русские переносы и проч.
\usepackage{graphicx,color}
\usepackage{graphicx,color,pmboxdraw}
\usepackage[T1,T2A]{fontenc}
\usepackage{indentfirst} % Отступ в первом абзаце главы
\usepackage{fancyvrb} % Продвинутые листинги и in-line commands
@@ -18,13 +18,8 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
% Несколько сокращений
\newcommand{\sectiona}[1]{\section*{#1}\addcontentsline{toc}{section}{#1}}
\newcommand{\hreftt}[2]{\href{#1}{\texttt{#2}}}
\newcommand{\tbs}{\textbackslash}
\newenvironment{caveat}[1][]{\smallskip\par\textbf{Предупреждение#1: }}%
{\smallskip\par}
% Примерный аналог символа \testSFii (присутствует в листингах),
% но без использования пакета pmboxdraw, средствами graphicx
\newcommand{\mytextSFii}{\raisebox{0pt}[0pt][\depth]{%
\reflectbox{\rotatebox[origin=t]{270}{$\neg$}}}}
% Настройка макета страницы
\setlength{\hoffset}{-1.5cm}
\addtolength{\textwidth}{2cm}
@@ -44,7 +39,7 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
\begin{document}
\sloppy
\title{systemd для администраторов}
\author{Lennart P\"{o}ttering (автор)\thanks{Первоисточник (на английском
\author{Lennart Poettering (автор)\thanks{Первоисточник (на английском
языке) опубликован на сайте автора: \url{http://0pointer.de/blog/projects}}\\%
Сергей Пташник (русский перевод)\thanks{Актуальная версия перевода
доступна на личной странице переводчика:
@@ -74,7 +69,7 @@ Unported}}
будем рассматривать ключевые новшества systemd, что может потребовать несколько
более подробного изложения.
\begin{flushright}
Lennart P\"{o}ttering, 23 августа 2010~г.
Lennart Poettering, 23 августа 2010~г.
\end{flushright}
\section{Контроль процесса загрузки}
@@ -202,7 +197,11 @@ JOB = Pending job for the unit.
внимательно посмотрев на листинг выше, вы можете заметить, что служба ntpd
(сервер точного времени) находится в состоянии, обозначенном как maintenance.
Чтобы узнать, что же произошло с ntpd, воспользуемся командой
+systemctl status+:
+systemctl status+\footnote{Прим. перев.: Стоит заметить, что формат вывода
данной команды менялся по мере развития systemd~--- появлялись дополнительные
поля с информацией, был добавлен вывод журнала службы
(см.~главу~\ref{sec:journal}) и т.д. Здесь приведен пример вывода этой команды
на момент написания исходной статьи (лето 2010 года).}:
\begin{Verbatim}[commandchars=\\\{\}]
[root@lambda] ~# systemctl status ntpd.service
ntpd.service - Network Time Service
@@ -1494,23 +1493,25 @@ $ systemd-analyze blame
значительно меньше, чем сумма времен инициализации каждой из них.
Рассмотрим повнимательнее первого осквернителя нашей загрузки: службу
+udev-settle.service+. Почему ей требуется так много времени для запуска, и что
мы можем с этим сделать? Данная служба выполняет очень простую функцию: она
ожидает, пока udev завершит опрос устройств, после чего завершается. Опрос же
устройств может занимать довольно много времени. Например, в нашем случае опрос
устройств длится более 6~секунд из-за подключенного к компьютеру 3G-модема, в
котором отсутствует SIM-карта. Этот модем очень долго отвечает на запросы udev.
Опрос устройств является частью схемы, обеспечивающей работу ModemManager'а и
позволяющей NetworkManager'у упростить для вас настройку 3G. Казалось бы,
очевидно, что виновником задержки является именно ModemManager, так как опрос
устройств для него занимает слишком много времени. Но такое обвинение будет
заведомо ошибочным. Дело в том, что опрос устройств очень часто оказывается
довольно длительной процедурой. Медленный опрос 3G-устройств для ModemManager
является частным случаем, отражающим это общее правило. Хорошая система опроса
устройств обязательно должна учитывать тот факт, что операция опроса любого из
устройств может затянуться надолго. Истинной причиной наших проблем является
необходимость ожидать завершения опроса, т.е., наличие службы
+udev-settle.service+ как обязательной части нашего процесса загрузки.
+udev-settle.service+\footnote{Прим. перев.: После объединения проектов systemd
и udev, эта служба называется +systemd-udev-settle.service+.} Почему ей
требуется так много времени для запуска, и что мы можем с этим сделать? Данная
служба выполняет очень простую функцию: она ожидает, пока udev завершит опрос
устройств, после чего завершается. Опрос же устройств может занимать довольно
много времени. Например, в нашем случае опрос устройств длится более 6~секунд
из-за подключенного к компьютеру 3G-модема, в котором отсутствует SIM-карта.
Этот модем очень долго отвечает на запросы udev. Опрос устройств является
частью схемы, обеспечивающей работу ModemManager'а и позволяющей
NetworkManager'у упростить для вас настройку 3G. Казалось бы, очевидно, что
виновником задержки является именно ModemManager, так как опрос устройств для
него занимает слишком много времени. Но такое обвинение будет заведомо
ошибочным. Дело в том, что опрос устройств очень часто оказывается довольно
длительной процедурой. Медленный опрос 3G-устройств для ModemManager является
частным случаем, отражающим это общее правило. Хорошая система опроса устройств
обязательно должна учитывать тот факт, что операция опроса любого из устройств
может затянуться надолго. Истинной причиной наших проблем является необходимость
ожидать завершения опроса, т.е., наличие службы +udev-settle.service+ как
обязательной части нашего процесса загрузки.
Но почему эта служба вообще присутствует в нашем процессе загрузки? На самом
деле, мы можем прекрасно обойтись и без нее. Она нужна лишь как часть
@@ -2105,7 +2106,7 @@ systemd?
\item Найдите для них более подходящее место. Например, в случае с
некоторыми общесистемными настройками (такими, как локаль или
часовой пояс), мы надеемся аккуратно подтолкнуть дистрибутивы в
правильно направлении (см. предыдущую главу).
правильном направлении (см. предыдущую главу).
\item Добавьте их поддержку в штатную систему настройки демона через
собственные файлы конфигурации. К счастью, большинство служб,
работающих в Linux, являются свободным программным обеспечением,
@@ -2116,8 +2117,8 @@ systemd?
время: необходимо обеспечить совместимость при обновлении. Тем не~менее, как
минимум в новых пакетах, от таких файлов лучше отказаться.
Если требование совместимости критично, вы можете задействовать эти
конфигурационные файлы даже в том случае, если настраиваете службы через
В том случае, если требование совместимости критично, вы можете задействовать
эти конфигурационные файлы даже в том случае, если настраиваете службы через
штатные unit-файлы systemd. Если ваш файл из +sysconfig+ содержит лишь
определения переменных, можно воспользоваться опцией
+EnvironmentFile=-/etc/sysconfig/foobar+ (подробнее об этой опции см.
@@ -2213,14 +2214,14 @@ RestartSec=0
при обращении к экземпляру +serial-getty@ttyUSB0.service+, они заменяются на
<<+ttyUSB0+>>. Результат такой замены можно проверить, например, запросив
состояние для нашей службы:
\begin{Verbatim}[commandchars=\\\{\}]
\begin{Verbatim}
$ 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
5443 /sbin/agetty -s ttyUSB0 115200,38400,9600
\end{Verbatim}
Собственно, это и есть ключевая идея организации экземпляров служб. Как видите,
systemd предоставляет простой в использовании механизм шаблонов, позволяющих
@@ -2230,8 +2231,8 @@ systemd предоставляет простой в использовании
Вы можете создавать дополнительные экземпляры таких служб, просто добавляя
символьные ссылки в каталоги +*.wants/+. Например, чтобы обеспечить запуск getty
на ttyUSB0 при каждой загрузке, достаточно создать такую ссылку:
\begin{Verbatim}[commandchars=\\\{\}]
# ln -s /lib/systemd/system/serial-getty@.service \tbs{}
\begin{Verbatim}
# ln -s /lib/systemd/system/serial-getty@.service \
/etc/systemd/system/getty.target.wants/serial-getty@ttyUSB0.service
\end{Verbatim}
При этом файл конфигурации, на который указывает ссылка (в нашем случае
@@ -2282,13 +2283,12 @@ systemd и заложен предварительный поиск файла
одноименному устройству). В то время как +%I+ удобно использовать в командной
строке (+ExecStart+) и для формирования читабельных строк описания. Рассмотрим
работу этих принципов на примере нашего юнит-файла\footnote{Прим. перев.: как
видно из нижеприведенного примера, в командной строке +systemctl+ необходимо
указывать экранированное имя юнита, что создает определенные трудности даже при
наличии в оболочке <<умного>> автодополнения. Однако, на момент написания этих
строк, в TODO проекта содержится пункт о добавлении в systemctl поддержки
неэкранированных имен юнитов.}:
видно из нижеприведенного примера, в командной строке +systemctl+ используется
экранированное имя юнита, что создает определенные трудности даже при
наличии в оболочке <<умного>> автодополнения. Однако, начиная с systemd v186,
при работе с +systemctl+ можно указывать неэкранированные имена юнитов.}:
\begin{landscape}
\begin{Verbatim}[fontsize=\small,commandchars=|\{\}]
\begin{Verbatim}[fontsize=\small]
# 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
@@ -2296,7 +2296,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
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
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}
Как видите, в качестве идентификатора экземпляра используется экранированная
@@ -2446,7 +2446,7 @@ service ssh {
Подобный подход был некогда весьма популярен в Unix, но сейчас он уже постепенно
выходит из моды, и поэтому в современных версиях xinetd поддерживается возможность
явного указания номера порта. Одна из наиболее интересных настроек названа
не~очень очевидно~--- +nowait+ (+wait=no+). Она определяет, будет ли служба
не~вполне очевидно~--- +nowait+ (+wait=no+). Она определяет, будет ли служба
работать по второй (+wait+) или третьей (+nowait+) схеме. И наконец, ключ +-i+
активирует inetd-режим в SSH-сервере (без этого ключа он работает в независимом
режиме).
@@ -2568,7 +2568,7 @@ sshd.socket loaded active listening SSH So
В завершение нашей дискуссии, сравним возможности xinetd и systemd, и выясним,
может ли systemd полностью заменить xinetd, или нет. Вкратце: systemd
поддерживает далеко не~все возможности xinetd и поэтому отнюдь не~является его
полноценной заменой на все случаи жизни. В частности, если вы загляните в
полноценной заменой на все случаи жизни. В частности, если вы заглянете в
\href{http://linux.die.net/man/5/xinetd.conf}{список параметров конфигурации}
xinetd, вы заметите, что далеко не~все эти опции доступны в systemd. Например, в
systemd нет и никогда не~будет встроенных служб +echo+, +time+, +daytime+,
@@ -2596,8 +2596,8 @@ Linux подсистема ipset гораздо лучше подходит дл
ценителей устаревших технологий systemd предлагает поддержку tcpwrap. С другой
стороны, systemd тоже предоставляет ряд возможностей, отсутствующих в xinetd, в
частности, индивидуальный контроль над каждым экземпляром службы (см. выше), и
куда более полный
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{список настроек}
внушительный
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{набор настроек}
для контроля окружения, в котором запускаются экземпляры. Я надеюсь, что
возможностей systemd должно быть достаточно для решения большинства задач, а в
тех редких случаях, когда вам потребуются специфические опции xinetd~--- ничто
@@ -2640,7 +2640,10 @@ MAC, от Mandatory Access Control), например, SELinux. Если вам
Linux уже очень давно, но при этом практически неизвестных для большинства
разработчиков. Мы постарались сделать соответствующие опции systemd максимально
простыми в использовании, чтобы заинтересовать администраторов и апстримных
разработчиков. Вот краткий перечень наиболее интересных возможностей:
разработчиков. Вот краткий перечень наиболее интересных
возможностей\footnote{Прим. перев.: В приведенном здесь списке не~упомянута
встроенная в systemd поддержка фильтров seccomp, так как она была добавлена уже
после написания исходной статьи.}:
\begin{itemize}
\item Изолирование служб от сети
\item Предоставление службам независимых каталогов +/tmp+
@@ -2744,7 +2747,7 @@ PrivateTmp=yes
сокеты (впрочем, в данном конкретном случае некоторые меры безопасности все же
присутствуют: сокеты размещаются в защищенном подкаталоге, который создается на
ранних стадиях загрузки). Разумеется, для служб, использующих +/tmp+ в целях
коммуникации, включение опции +PrivateTmp=yes+ недопустимо. К счастью, таких
коммуникации, включение опции +PrivateTmp=yes+ недопустимо. К счастью, подобных
служб сейчас уже не~так уж и много.
\end{caveat}
@@ -2766,15 +2769,15 @@ InaccessibleDirectories=/home
ReadOnlyDirectories=/var
...
\end{Verbatim}
Добавление этих двух строчек в файл конфигурации, приводит к тому, что служба
Добавление этих двух строчек в файл конфигурации приводит к тому, что служба
полностью утрачивает доступ к содержимому каталога +/home+ (она видит лишь
пустой каталог с правами доступа 000), а также не~может писать внутрь каталога
+/var+.
\begin{caveat}
К сожалений, в настоящее время опция +ReadOnlyDirectories=+ не~применяется
К сожалению, в настоящее время опция +ReadOnlyDirectories=+ не~применяется
рекурсивно к точкам монтирования, расположенным в поддереве указанного каталога
(т.е. файловые систем, смонтированные в подкаталогах +/var+, по-прежнему
(т.е. файловые системы, смонтированные в подкаталогах +/var+, по-прежнему
останутся доступными на запись, если, конечно, не~перечислить их все поименно).
Мы собираемся исправить это в ближайшее время.
\end{caveat}
@@ -2862,7 +2865,7 @@ LimitFSIZE=0
...
\end{Verbatim}
Обратите внимание, что эти ограничения будут эффективно работать только в том
случае, если служба будет работать от имени простого пользователя (не~root) и
случае, если служба запускается от имени простого пользователя (не~root) и
без привилегии +CAP_SYS_RESOURCE+ (блокирование этой привилегии можно
обеспечить, например, описанной выше опцией +CapabilityBoundingSet=+). В
противном случае, ничто не~мешает процессу поменять соответствующие ограничения.
@@ -2881,7 +2884,7 @@ LimitFSIZE=0
\subsection{Контроль доступа служб к файлам устройств}
Файлы устройств предоставляют приложениям интерфейс для доступа к ядру и
драйверам. Причем драйверы, как правило менее тщательно тестируются и не~так
драйверам. Причем драйверы, как правило, менее тщательно тестируются и не~так
аккуратно проверяются на предмет наличия уязвимостей, по сравнению с основными
компонентами ядра. Именно поэтому драйверы часто становятся объектами атаки
злоумышленников. systemd позволяет контролировать доступ к устройствам
@@ -2926,6 +2929,405 @@ systemd.
выиграют не~только ваши пользователи, но и все мы, потому что Интернет станет
чуть более безопасным.
\section{Отчет о состоянии службы и ее журнал}
\label{sec:journal}
При работе с системами, использующими systemd, одной из наиболее важных и часто
используемых команд является +systemctl status+. Она выводит отчет о состоянии
службы (или другого юнита). В таком отчете приводится статус службы (работает
она или нет), список ее процессов и другая полезная информация.
В Fedora~17 мы ввели
\href{http://0pointer.de/blog/projects/the-journal.html}{Journal}, новую
реализацию системного журнала, обеспечивающую структурированное, индексированное
и надежное журналирование, при сохранении совместимости с классическими
реализациями syslog. Собственно, мы начали работу над~Journal только потому, что
хотели добавить одну, казалось бы, простую, возможность: включить в вывод
+systemctl status+ последние 10 сообщений, поступивших от службы в системный
журнал. Но на практике оказалось, что в рамках классических механизмов syslog,
реализация этой возможности чрезвычайно сложна и малоэффективна. С другой
стороны, сообщения службы в системный журнал несут очень важную информацию о ее
состоянии, и такая возможность действительно была бы очень полезной, особенно
при диагностике нештатных ситуаций.
Итак, мы интегрировали Journal в systemd, и научили +systemctl+ работать с ним.
Результат выглядит примерно так:
\begin{Verbatim}[fontsize=\small]
$ systemctl status avahi-daemon.service
avahi-daemon.service - Avahi mDNS/DNS-SD Stack
Loaded: loaded (/usr/lib/systemd/system/avahi-daemon.service; enabled)
Active: active (running) since Fri, 18 May 2012 12:27:37 +0200; 14s ago
Main PID: 8216 (avahi-daemon)
Status: "avahi-daemon 0.6.30 starting up."
CGroup: name=systemd:/system/avahi-daemon.service
8216 avahi-daemon: running [omega.local]
8217 avahi-daemon: chroot helper
May 18 12:27:37 omega avahi-daemon[8216]: Joining mDNS multicast group on interface eth1.IPv4 with address 172.31.0.52.
May 18 12:27:37 omega avahi-daemon[8216]: New relevant interface eth1.IPv4 for mDNS.
May 18 12:27:37 omega avahi-daemon[8216]: Network interface enumeration completed.
May 18 12:27:37 omega avahi-daemon[8216]: Registering new address record for 192.168.122.1 on virbr0.IPv4.
May 18 12:27:37 omega avahi-daemon[8216]: Registering new address record for fd00::e269:95ff:fe87:e282 on eth1.*.
May 18 12:27:37 omega avahi-daemon[8216]: Registering new address record for 172.31.0.52 on eth1.IPv4.
May 18 12:27:37 omega avahi-daemon[8216]: Registering HINFO record with values 'X86_64'/'LINUX'.
May 18 12:27:38 omega avahi-daemon[8216]: Server startup complete. Host name is omega.local. Local service cookie is 3555095952.
May 18 12:27:38 omega avahi-daemon[8216]: Service "omega" (/services/ssh.service) successfully established.
May 18 12:27:38 omega avahi-daemon[8216]: Service "omega" (/services/sftp-ssh.service) successfully established.
\end{Verbatim}
Очевидно, это отчет о состоянии всеми любимого демона mDNS/DNS-SD, причем после
списка процессов, как мы и обещали, приведены сообщения этого демона в системный
журнал. Миссия выполнена!
Команда +systemctl status+ поддерживает ряд опций, позволяющих настроить вывод
информации в соответствии с вашими пожеланиями. Отметим две наиболее интересные
из них: ключ +-f+ позволяет в реальном времени отслеживать обновление сведений
(по аналогии с +tail -f+), а ключ +-n+ задает количество выводимых журнальных
записей (как нетрудно догадаться, по аналогии с +tail -n+).
Журнальные записи собираются из трех различных источников. Во-первых, это
сообщения службы в системный журнал, отправленные через функцию libc
+syslog()+. Во-вторых, это сообщения, отправленные через штатный API системы
Journal. И наконец, это весь текст, выводимый демоном в STDOUT и STDERR. Проще
говоря, все, что демон считает нужным сказать администратору, собирается,
упорядочивается и отображается в одинаковом формате.
Добавленная нами возможность, при всей своей простоте, может оказаться
чрезвычайно полезной практически любому администратору. По-хорошему, ее стоило
реализовать еще 15 лет назад.
\section{Самодокументированный процесс загрузки}
Нам часто приходится слышать жалобы, что процесс загрузки при использовании
systemd очень сложен для понимания. Не~могу с этим согласиться. Более того, я
берусь даже утверждать обратное: по сравнению с тем, что мы имели раньше (когда
для того, чтобы разобраться в загрузке, нужно было иметь хорошие навыки
программирования на языке Bourne Shell\footnote{Чья привлекательность очень
коварна и обманчива.}), процесс загрузки стал более простым и прозрачным. Но
определенная доля истины в этом критическом замечании все же есть: даже опытному
Unix-администратору при переходе на systemd нужно изучить некоторые новые для
себя вещи. Мы, разработчики systemd, обязаны максимально упростить такое
обучение. Решая поставленную задачу, мы подготовили для вас кое-какие приятные
сюрпризы, и предоставили хорошую документацию даже там, где это казалось
невозможным.
Уже сейчас systemd располагает довольно обширной документацией, включая
\href{http://www.freedesktop.org/software/systemd/man/}{страницы руководства}
(на данный момент, их около сотни),
\href{http://www.freedesktop.org/wiki/Software/systemd}{wiki-сайт проекта}, а
также ряд статей в моем блоге. Тем не~менее, большое количество документации еще
не~гарантирует простоты понимания. Огромные груды руководств выглядят пугающе, и
неподготовленный читатель не~может разобраться, с какого места ему начинать
чтение, если его интересует просто общая концепция.
Чтобы решить данную проблему, мы добавили в systemd небольшую, но очень изящную
возможность: самодокументированный\footnote{Прим. перев.: В оригинале
использован термин <<self-explanatory>>, который также можно перевести как
<<само-объясняющий>>, <<самоочевидный>>.} процесс загрузки. Что мы под этим
подразумеваем? То, что для каждого элемента процесса загрузки теперь имеется
документация, прозрачно привязанная к этому элементу, так что ее поиск
не~представляет трудности.
Иными словами, все штатные юниты systemd (которые, собственно, и формируют
процесс загрузки, вызывая соответствующие программы) включают ссылки на страницы
документации, описывающие назначение юнита/программы, используемые ими
конфигурационные файлы и т.д. Если пользователь хочет узнать, для чего
предназначен какой-либо юнит, какова его роль в процессе загрузки и как его
можно настроить, может получить ссылки на соответствующую документацию, просто
воспользовавшись давно известной командой +systemctl status+. Возьмем для
примера +systemd-logind.service+:
\begin{Verbatim}[fontsize=\small,commandchars=\\\{\},%
% В окружении Verbatim ссылки, содержащие знак дефиса/минуса "-",
% повреждаются. Обходим это при помощи черной магии в стиле sysvinit:
codes={\catcode`+=\active},defineactive=\def+{-}]
$ systemctl status systemd-logind.service
systemd-logind.service - Login Service
Loaded: loaded (/usr/lib/systemd/system/systemd-logind.service; static)
Active: active (running) since Mon, 25 Jun 2012 22:39:24 +0200; 1 day and 18h ago
Docs: \href{http://www.freedesktop.org/software/systemd/man/systemd+logind.service.html}{man:systemd-logind.service(7)}
\href{http://www.freedesktop.org/software/systemd/man/logind.conf.html}{man:logind.conf(5)}
\url{http://www.freedesktop.org/wiki/Software/systemd/multiseat}
Main PID: 562 (systemd-logind)
CGroup: name=systemd:/system/systemd-logind.service
└ 562 /usr/lib/systemd/systemd-logind
Jun 25 22:39:24 epsilon systemd-logind[562]: Watching system buttons on /dev/input/event2 (Power Button)
Jun 25 22:39:24 epsilon systemd-logind[562]: Watching system buttons on /dev/input/event6 (Video Bus)
Jun 25 22:39:24 epsilon systemd-logind[562]: Watching system buttons on /dev/input/event0 (Lid Switch)
Jun 25 22:39:24 epsilon systemd-logind[562]: Watching system buttons on /dev/input/event1 (Sleep Button)
Jun 25 22:39:24 epsilon systemd-logind[562]: Watching system buttons on /dev/input/event7 (ThinkPad Extra Buttons)
Jun 25 22:39:25 epsilon systemd-logind[562]: New session 1 of user gdm.
Jun 25 22:39:25 epsilon systemd-logind[562]: Linked /tmp/.X11-unix/X0 to /run/user/42/X11-display.
Jun 25 22:39:32 epsilon systemd-logind[562]: New session 2 of user lennart.
Jun 25 22:39:32 epsilon systemd-logind[562]: Linked /tmp/.X11-unix/X0 to /run/user/500/X11-display.
Jun 25 22:39:54 epsilon systemd-logind[562]: Removed session 1.
\end{Verbatim}
На первый взгляд, в выводе этой команды почти ничего не~изменилось. Но если вы
вглядитесь повнимательнее, то заметите новое поле +Docs+, в котором приведены
ссылки на документацию по данной службе. В нашем случае случае это два URI,
ссылающихся на man-страницы, и один URL, указывающий на веб-страницу.
man-страницы описывают соответственно предназначение службы и ее настройки, а
веб-страница~--- базовые концепции, которые реализуются этой службой.
Тем, кто использует современные графические эмуляторы терминала, чтобы открыть
соответствующую страницу документации, достаточно щелкнуть мышью по
URI\footnote{Для нормальной работы данной функции, в эмуляторе терминала должен
быть исправлена \href{https://bugzilla.gnome.org/show_bug.cgi?id=676452}{эта
ошибка}, а в программе просмотра страниц помощи~---
\href{https://bugzilla.gnome.org/show_bug.cgi?id=676482}{вот эта}.}. Иными
словами, доступ к документации компонентов загрузки становится предельно
простым: достаточно вызвать +systemctl status+, после чего щелкнуть по
полученным ссылкам.
Если же вы используете не~графический эмулятор терминала (где можно просто
щелкнуть по URI), а настоящий терминал, наличие URI где-то в середине вывода
+systemctl status+ вряд ли покажется вам удобным. Чтобы упростить обращение к
соответствующим страницам документации без использования мыши и
копирования/вставки, мы ввели новую команду
\begin{Verbatim}
systemctl help systemd-logind.service
\end{Verbatim}
которая просто откроет в вашем терминале соответствующие man-страницы.
URI, ссылающиеся на документацию, формируются в соответствии со страницей
руководства
\href{https://www.kernel.org/doc/man-pages/online/pages/man7/url.7.html}{uri(7)}.
Поддерживаются схемы +http+/+https+ (URL для веб-страниц) и +man+/+info+
(локальные страницы руководства).
Разумеется, добавленная нами возможность не~обеспечивает полной очевидности
абсолютно всего, хотя бы потому, что пользователь должен как минимум знать про
команду +systemctl status+ (а также вообще про программу +systemctl+ и про то,
что такое юнит). Но при наличии этих базовых знаний, пользователю уже
не~составит труда получить информацию по интересующим его вопросам.
Мы надеемся, что добавленный нами механизм для связи работающего кода и
соответствующей документации станет значительным шагом к полностью прозрачному и
предельно простому для понимания процессу загрузки.
Описанная функциональность частично присутствует в Fedora~17, а в полном
объеме она будет представлена в Fedora~18.
В завершение, стоит отметить, что использованная нами идея не~является такой уж
новой: в SMF, системе инициализации Solaris, уже используется практика
указания ссылок на документацию в описании службы. Однако, в Linux такой
подход является принципиально новым, и systemd сейчас является наиболее
документированной и прозрачной системой загрузки для данной платформы.
Если вы занимаетесь разработкой или сопровождением пакетов и создаете файл
конфигурации юнита, пожалуйста, включите в него ссылки на документацию. Это
очень просто: достаточно добавить в секции +[Unit]+ поле +Documentation=+ и
перечислить в нем соответствующие URI. Подробнее об этом поле см. на странице
руководства
\href{http://www.freedesktop.org/software/systemd/man/systemd.unit.html}{systemd.unit(5)}.
Чем больше будет документированных юнитов, тем проще станет работа системного
администратора. (В частности, я уже направил в FPC
\href{https://fedorahosted.org/fpc/ticket/192}{предложение} внести
соответствующие пожелания в нормативные документы, регулирующие подготовку
пакетов для Fedora.)
Да, кстати: если вас интересует общий обзор процесса загрузки systemd, то вам
стоит обратить внимание на
\href{http://www.freedesktop.org/software/systemd/man/bootup.html}{новую
страницу руководства}, где представлена псевгдорафическая потоковая диаграмма,
описывающая процесс загрузки и роль ключевых юнитов.
\section{Сторожевые таймеры}
Разрабатывая systemd, мы ориентируемся на три основных области его применения:
мобильные/встраиваемые устройства, настольные системы и промышленные серверы.
Мобильные и встраиваемые системы, как правило, располагают очень скромными
ресурсами и вынуждены очень экономно расходовать энергию. Настольные системы
уже не~так сильно ограничены по мощности, хотя все же проигрывают в
этом плане промышленным серверам. Но, как ни~странно, существуют
возможности, востребованные в обоих крайних случаях (встраиваемые системы и
серверы), но не~очень актуальные в промежуточной ситуации (десктопы). В
частности, к ним относится поддержка
\href{http://ru.wikipedia.org/wiki/Watchdog}{сторожевых таймеров} (watchdogs),
как аппаратных, так и программных.
Во встраиваемых системах часто используются аппаратные сторожевые таймеры,
выполняющие сброс системы, когда программа перестает отвечать (точнее, перестает
периодически посылать таймеру сигнал <<все в порядке>>). Таким образом,
обеспечивается повышение надежности системы: что бы ни~случилось, система
обязательно попытается привести себя в рабочее состояние. На десктопах такая
функциональность практически не~востребована\footnote{Тем не~менее, сейчас
аппаратные сторожевые таймеры все чаще появляются и в настольных системах, так
как стоят они относительно дешево и доступны практически во всех современных
чипсетах.}. С другой стороны, она весьма актуальна для высокодоступных серверных
систем.
Начиная с версии 183, systemd полностью поддерживает аппаратные сторожевые
таймеры (доступные через интерфейс +/dev/watchdog+), а также обеспечивает
программный сторожевой контроль системных служб. В целом эта схема (если она
задействована) работает так. systemd периодически посылает сигналы аппаратному
таймеру. В том случае, если systemd или ядро зависают, аппаратный таймер,
не~получив очередного сигнала, автоматически перезапустит систему. Таким
образом, ядро и systemd защищены от бесконечного зависания~--- на аппаратном
уровне. В то же время, сам systemd предоставляет интерфейс, реализующий логику
программных сторожевых таймеров для отдельных служб. Таким образом можно
обеспечить, например, принудительный перезапуск службы в случае ее зависания.
Для каждой службы можно независимо настроить частоту опроса и задать
соответствующее действие. Соединив оба звена (аппаратный сторожевой таймер,
контролирующий ядро и systemd, и программные сторожевые таймеры, посредством
которых systemd контролирует отдельные службы), мы получаем надежную схему
надзора за всеми системными компонентами.
Чтобы задействовать аппаратный таймер, достаточно задать ненулевое значение
параметра +RuntimeWatchdogSec=+ в файле +/etc/systemd/system.conf+. По умолчанию
этот параметр равен нулю (т.е. аппаратный таймер не~задействован). Установив его
равным, например, <<+20s+>>, мы включим аппаратный сторожевой таймер. Если в
течение 20 секунд таймер не~получит очередного сигнала <<все в порядке>>,
система автоматически перезагрузится. Отметим, что systemd отправляет такие
сигналы с периодом, равным половине заданного интервала~--- в нашем случае,
через каждые 10 секунд. Собственно, это все. Просто задав один параметр,
вы обеспечите аппаратный контроль работоспособности systemd и
ядра\footnote{Небольшой совет: если вы занимаетесь отладкой базовых системных
компонентов~--- не~забудьте отключить сторожевой таймер. Иначе ваша система
может неожиданно перезагрузиться, когда отладчик остановит процесс init и тот
не~может вовремя отправить сообщение таймеру.}.
Заметим, что с аппаратным сторожевым таймером (+/dev/watchdog+)
должна работать только одна программа. Этой программой может быть либо systemd,
либо отдельный демон сторожевого таймера (например,
\href{http://linux.die.net/man/8/watchdog}{watchdogd})~--- выбор остается за
вами.
Стоит упомянуть здесь еще одну опцию из файла +/etc/systemd/system.conf+~---
+ShutdownWatchdogSec=+. Она позволяет настроить аппаратный сторожевой таймер для
контроля процесса перезагрузки. По умолчанию она равна <<+10min+>>. Если в
процессе остановки системы перед перезагрузкой она зависнет, аппаратный таймер
принудительно перезагрузит ее по истечении данного интервала.
Это все, что я хотел сказать об аппаратных таймерах. Двух вышеописанных опций
должно быть вполне достаточно для полноценного использования их возможностей.
А сейчас мы рассмотрим логику программных сторожевых таймеров, обеспечивающих
контроль работоспособности отдельных служб.
Прежде всего отметим, что для полноценной поддержки сторожевого контроля,
программа должна содержать специальный код, периодически отправляющий таймеру
сигналы <<все в порядке>>. Добавить поддержку такой функциональности довольно
просто. Для начала, демон должен проверить переменную окружения +WATCHDOG_USEC=+.
Если она определена, то ее значение задает контрольный интервал в микросекундах,
сформатированный в виде текстовой (ASCII) строки. В этом случае демон должен
регулярно выполнять вызов
\hreftt{http://www.freedesktop.org/software/systemd/man/sd_notify.html}{sd\_notify}+("WATCHDOG=1")+
с периодом, равным половине указанного интервала. Таким образом, поддержка
программного сторожевого контроля со стороны демона сводится к проверке значения
переменной окружения, и выполнении определенных действий в соответствии с этим
значением.
Если интересующая вас служба обеспечивает поддержку такой
функциональности, вы можете включить для нее сторожевой контроль, задав опцию
+WatchdogSec=+ в ее юнит-файле. Эта опция задает период работы таймера
(подробнее см.
\href{http://www.freedesktop.org/software/systemd/man/systemd.service.html}{systemd.service(5)}).
Если вы зададите ее, то systemd при запуске службы передаст ей соответствующее
значение +WATCHDOG_USEC=+ и, если служба перестанет своевременно отправлять
сигналы <<все в порядке>>, присвоит ей статус сбойной (failure state).
Очевидно, что одного только присвоения статуса недостаточно для обеспечения
надежной работы системы. Поэтому нам также пригодятся настройки, определяющие,
нужно ли перезапускать зависшую службу, количество попыток перезапуска, и
дальнейшие действия, если она все равно продолжает сбоить. Чтобы включить
автоматический перезапуск службы при сбое, нужно задать опцию
+Restart=on-failure+ в ее юнит-файле. Чтобы настроить, сколько раз systemd будет
пытаться перезапустить службу, воспользуйтесь настройками +StartLimitBurst=+
+StartLimitInterval=+ (первая из них определяет предельное количество попыток,
вторая~--- интервал времени, в течение которого они подсчитываются). В том
случае, если достигнут предел количества попыток за указанное время, выполняется
действие, заданное параметром +StartLimitAction=+. По умолчанию он установлен в
+none+ (никаких дополнительных действий не~будет, службу просто оставят в покое со
статусом сбойной). В качестве альтернативы можно указать одно из трех
специальных действий: +reboot+, +reboot-force+ и +reboot-immediate+.
+reboot+ соответствует обычной перезагрузке системы, с выполнением всех
сопутствующих процедур (корректное завершение всех служб, отмонтирование
файловых систем и т.д.). +reboot-force+ действует более грубо~--- даже
не~пытаясь корректно остановить службы, оно просто убивает все их процессы,
отмонтирует файловые системы и выполняет принудительную перезагрузку (в
результате, перезагрузка происходит быстрее, чем обычно, но файловые системы
остаются неповрежденными). И наконец, +reboot-immediate+ даже не~пытается отдать
дань вежливости (убить процессы и отмонтировать файловый системы)~--- оно
немедленно выполняет жесткую перезагрузку системы (это поведение практически
аналогично срабатыванию аппаратного сторожевого таймера). Все перечисленный
настройки подробно описаны на странице руководства
\href{http://www.freedesktop.org/software/systemd/man/systemd.service.html}{systemd.service(5)})%
\footnote{Прим. перев.: Автор упускает из виду одну полезную опцию,
непосредственно относящуюся к обсуждаемому вопросу~--- +OnFailure=+, задающую
юнит, который будет активирован в случае сбоя исходного юнита. Таким образом
можно обеспечить, например, запуск скриптов, отправляющих администратору
уведомление о сбое в сочетании с дополнительной информацией (для сбора которой
целесообразно задействовать команды +systemctl status+ и +journalctl+). Кроме
того, комбинирование данной настройки с опцией +OnFailureIsolate=+ позволяет
при сбое юнита перевести систему в определенное состояние (например, остановить
некоторые службы, перейти в режим восстановления, выполнить перезагрузку).}.
Таким образом, мы мы получаем гибкий механизм для настройки сторожевого контроля
служб, их перезапуска при зависании, и реагирования в ситуации, когда перезапуск
не~помогает.
Рассмотрим применение этих настроек на простом примере:
\begin{Verbatim}
[Unit]
Description=My Little Daemon
Documentation=man:mylittled(8)
[Service]
ExecStart=/usr/bin/mylittled
WatchdogSec=30s
Restart=on-failure
StartLimitInterval=5min
StartLimitBurst=4
StartLimitAction=reboot-force
\end{Verbatim}
Данная служба будет автоматически перезапущена, если она не~передаст системному
менеджеру очередной сигнал <<все в порядке>> в течение 30 секунд после
предыдущего (кроме того, перезапуск будет произведен и в случае любого другого
сбоя, например, завершения основного процесса службы с ненулевым кодом выхода).
Если потребуется более 4 перезапусков службы за 5 минут~--- будет предпринято
специальное действие, в данном случае, быстрая перезагрузка системы с корректным
отмонтированием файловых систем.
Это все, что я хотел рассказать о сторожевых таймерах в systemd. Мы надеемся,
что поддержки аппаратного отслеживания работоспособности процесса init, в
сочетании с контролем функционирования отдельных служб, должно быть достаточно
для решения большинства задач, связанных со сторожевыми таймерами.
Разрабатываете ли вы встраиваемую либо мобильную систему, или работаете с
высокодоступными серверами~--- вам определенно стоит попробовать наши решения!
(И да, если у вас возникнет вопрос, почему с аппаратным таймером должен работать
именно init, и что мешает вынести эту логику в отдельный демон~--- пожалуйста,
перечитайте эту главу еще раз, и попытайтесь увидеть всю цепочку сторожевого
контроля как единое целое: аппаратный таймер надзирает за работой systemd, а
тот, в свою очередь, следит за отдельными службами. Кроме того, мы полагаем, что
отсутствие своевременного ответа от службы нужно рассматривать и обрабатывать
так же, как и любые другие ее сбои. И наконец, взаимодействие с
+/dev/watchdog+~--- одна из самых тривиальных задач в работе ОС (обычно, она
сводится к простому вызову +ioctl()+), и для ее решения достаточно нескольких
строк кода. С другой стороны, вынос данной функции в отдельный демон потребует
организации сложного межпроцессного взаимодействия между этим демоном и
процессом init~--- очевидно, реализация такой схемы предоставит значительно
б\'{о}льший простор для ошибок, не~говоря уже о повышенном потреблении
ресурсов.)
Отметим, что встроенная в systemd поддержка аппаратного сторожевого таймера
в~конфигурации по умолчанию отключена, и поэтому никак не~мешает работе с этим
таймером из других программ. Вы без лишних проблем можете выбрать внешний
сторожевой демон, если он лучше подходит для вашей задачи.
Да, и еще: если у вас возникнет вопрос, имеется ли в вашей системе аппаратный
таймер~--- скорее всего да, если ваш компьютер не~очень старый. Чтобы получить
точный ответ, вы можете воспользоваться утилитой
\href{http://karelzak.blogspot.de/2012/05/eject1-sulogin1-wdctl1.html}{wdctl},
включенной в последний релиз util-linux\footnote{Прим. перев.: Утилита wdctl
присутствует в util-linux, начиная с версии~2.22, которая, на~момент написания
этих строк, еще не~вышла.}. Эта программа выведет всю необходимую
информацию о вашем аппаратном сторожевом таймере.
И в завершение, я хотел бы поблагодарить ребят из
\href{http://www.pengutronix.de/}{Pengutronix}, которым приндалежит основная
заслуга реализации сторожевого контроля в systemd.
\end{document}
vim:ft=tex:tw=80:spell:spelllang=ru