Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ffca4f1be | ||
|
|
751d5d1bae | ||
|
|
237904f0df | ||
|
|
20db2f8715 | ||
|
|
93782fa4ec | ||
|
|
57b51c4e30 |
802
s4a.tex
802
s4a.tex
@@ -14,7 +14,7 @@
|
|||||||
\hypersetup{pdftitle={systemd для администраторов},%
|
\hypersetup{pdftitle={systemd для администраторов},%
|
||||||
pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||||||
% Не засоряем оглавление подразделами
|
% Не засоряем оглавление подразделами
|
||||||
\setcounter{tocdepth}{1}
|
%\setcounter{tocdepth}{1} % А почему бы и нет?
|
||||||
% Несколько сокращений
|
% Несколько сокращений
|
||||||
\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}}}
|
||||||
@@ -48,7 +48,8 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
|||||||
\href{http://creativecommons.org/licenses/by-sa/3.0/legalcode}{CC-BY-SA 3.0
|
\href{http://creativecommons.org/licenses/by-sa/3.0/legalcode}{CC-BY-SA 3.0
|
||||||
Unported}}
|
Unported}}
|
||||||
\maketitle
|
\maketitle
|
||||||
\tableofcontents%\newpage
|
\tableofcontents
|
||||||
|
\newpage
|
||||||
\sectiona{Предисловие автора}
|
\sectiona{Предисловие автора}
|
||||||
Многие из вас, наверное, уже знают, что
|
Многие из вас, наверное, уже знают, что
|
||||||
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd}~--- это новая
|
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd}~--- это новая
|
||||||
@@ -67,7 +68,7 @@ Unported}}
|
|||||||
Большинство этих возможностей можно описать легко и просто, и подобные статьи
|
Большинство этих возможностей можно описать легко и просто, и подобные статьи
|
||||||
должны быть интересны довольно широкой аудитории. Однако, время от времени мы
|
должны быть интересны довольно широкой аудитории. Однако, время от времени мы
|
||||||
будем рассматривать ключевые новшества systemd, что может потребовать несколько
|
будем рассматривать ключевые новшества systemd, что может потребовать несколько
|
||||||
более подробного изложения.
|
более подробного изложения.
|
||||||
\begin{flushright}
|
\begin{flushright}
|
||||||
Lennart Poettering, 23 августа 2010~г.
|
Lennart Poettering, 23 августа 2010~г.
|
||||||
\end{flushright}
|
\end{flushright}
|
||||||
@@ -419,7 +420,12 @@ alias psc='ps xawf -eo pid,user,cgroup,args'
|
|||||||
|
|
||||||
Альтернативный способ получить ту же информацию~--- воспользоваться утилитой
|
Альтернативный способ получить ту же информацию~--- воспользоваться утилитой
|
||||||
+systemd-cgls+, входящей в комплект поставки systemd. Она отображает иерархию
|
+systemd-cgls+, входящей в комплект поставки systemd. Она отображает иерархию
|
||||||
контрольных групп в виде псевдографической диаграммы-дерева:
|
контрольных групп в виде псевдографической диаграммы-дерева\footnote{Прим.
|
||||||
|
перев.: Стоит заметить, что в нижеприведенном листинге используется
|
||||||
|
ASCII-псевдографика. Между тем, уже довольно давно отображение иерархии
|
||||||
|
процессов в +systemd-cgls+ и +systemctl status+ производится в более
|
||||||
|
выразительной ├юникодной └псевдографике. ASCII-вариант выводится только в том
|
||||||
|
случае, если консоль не~поддерживает Unicode.}:
|
||||||
|
|
||||||
\begin{landscape}
|
\begin{landscape}
|
||||||
\begin{Verbatim}[fontsize=\small]
|
\begin{Verbatim}[fontsize=\small]
|
||||||
@@ -1117,6 +1123,7 @@ Apache, crond, atd, которые по роду служебной деятел
|
|||||||
+ln+.
|
+ln+.
|
||||||
|
|
||||||
\section{Смена корня}
|
\section{Смена корня}
|
||||||
|
\label{sec:chroots}
|
||||||
|
|
||||||
Практически все администраторы и разработчики рано или поздно встречаются с
|
Практически все администраторы и разработчики рано или поздно встречаются с
|
||||||
\href{http://linux.die.net/man/1/chroot}{chroot-окружениями}. Системный вызов
|
\href{http://linux.die.net/man/1/chroot}{chroot-окружениями}. Системный вызов
|
||||||
@@ -2126,7 +2133,7 @@ systemd?
|
|||||||
позволяющей прочитать из файла набор переменных окружения, который будет
|
позволяющей прочитать из файла набор переменных окружения, который будет
|
||||||
установлен при запуске службы. Если же для задания настроек вам необходим
|
установлен при запуске службы. Если же для задания настроек вам необходим
|
||||||
полноценный язык программирования~--- ничто не~мешает им воспользоваться.
|
полноценный язык программирования~--- ничто не~мешает им воспользоваться.
|
||||||
Например, вы можете создайть в +/usr/lib/<your package>/+ простой скрипт,
|
Например, вы можете создать в +/usr/lib/<your package>/+ простой скрипт,
|
||||||
который включает соответствующие файлы, а затем запускает бинарник демона через
|
который включает соответствующие файлы, а затем запускает бинарник демона через
|
||||||
+exec+. После чего достаточно просто указать этот скрипт в опции +ExecStart=+
|
+exec+. После чего достаточно просто указать этот скрипт в опции +ExecStart=+
|
||||||
вместо бинарника демона.
|
вместо бинарника демона.
|
||||||
@@ -2311,6 +2318,7 @@ serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.
|
|||||||
пояснениями.)
|
пояснениями.)
|
||||||
|
|
||||||
\section{Службы с активацией в стиле inetd}
|
\section{Службы с активацией в стиле inetd}
|
||||||
|
\label{sec:inetd}
|
||||||
|
|
||||||
В одной из предыдущих глав (гл.~\ref{sec:convert}) я рассказывал, как можно
|
В одной из предыдущих глав (гл.~\ref{sec:convert}) я рассказывал, как можно
|
||||||
преобразовать SysV init-скрипт в юнит-файл systemd. В этой главе мы рассмотрим,
|
преобразовать SysV init-скрипт в юнит-файл systemd. В этой главе мы рассмотрим,
|
||||||
@@ -2612,6 +2620,7 @@ systemd. Но, конечно, будет лучше, если этим займ
|
|||||||
приложения, или сопровождающие вашего дистрибутива.
|
приложения, или сопровождающие вашего дистрибутива.
|
||||||
|
|
||||||
\section{К вопросу о безопасности}
|
\section{К вопросу о безопасности}
|
||||||
|
\label{sec:security}
|
||||||
|
|
||||||
Одно из важнейших достоинств Unix-систем~--- концепция разделения привилегий
|
Одно из важнейших достоинств Unix-систем~--- концепция разделения привилегий
|
||||||
между различными компонентами ОС. В частности, службы обычно работают от имени
|
между различными компонентами ОС. В частности, службы обычно работают от имени
|
||||||
@@ -3129,7 +3138,7 @@ URI, ссылающиеся на документацию, формируютс
|
|||||||
Да, кстати: если вас интересует общий обзор процесса загрузки systemd, то вам
|
Да, кстати: если вас интересует общий обзор процесса загрузки systemd, то вам
|
||||||
стоит обратить внимание на
|
стоит обратить внимание на
|
||||||
\href{http://www.freedesktop.org/software/systemd/man/bootup.html}{новую
|
\href{http://www.freedesktop.org/software/systemd/man/bootup.html}{новую
|
||||||
страницу руководства}, где представлена псевгдорафическая потоковая диаграмма,
|
страницу руководства}, где представлена псевдографическая потоковая диаграмма,
|
||||||
описывающая процесс загрузки и роль ключевых юнитов.
|
описывающая процесс загрузки и роль ключевых юнитов.
|
||||||
|
|
||||||
\section{Сторожевые таймеры}
|
\section{Сторожевые таймеры}
|
||||||
@@ -3453,7 +3462,7 @@ getty. Таким образом, вам достаточно лишь прав
|
|||||||
консоль, то по завершении загрузки он увидит на этой консоли приглашение для
|
консоль, то по завершении загрузки он увидит на этой консоли приглашение для
|
||||||
логина\footnote{Отметим, что getty, а точнее, +agetty+ на такой консоли
|
логина\footnote{Отметим, что getty, а точнее, +agetty+ на такой консоли
|
||||||
вызывается с параметром +-s+, и поэтому не~изменяет настроек символьной
|
вызывается с параметром +-s+, и поэтому не~изменяет настроек символьной
|
||||||
скорость (baud rate)~--- сохраняется то значение, которое было указано в строке
|
скорости (baud rate)~--- сохраняется то значение, которое было указано в строке
|
||||||
параметров ядра.}. Кроме того, systemd выполняет поиск консолей, предоставляемых
|
параметров ядра.}. Кроме того, systemd выполняет поиск консолей, предоставляемых
|
||||||
системами виртуализации, и запускает +serial-getty@.service+ на первой из этих
|
системами виртуализации, и запускает +serial-getty@.service+ на первой из этих
|
||||||
консолей (+/dev/hvc0+, +/dev/xvc0+ или +/dev/hvsi0+). Такое поведение
|
консолей (+/dev/hvc0+, +/dev/xvc0+ или +/dev/hvsi0+). Такое поведение
|
||||||
@@ -3625,7 +3634,10 @@ Journal был включен в Fedora начиная с F17. В Fedora~18 jour
|
|||||||
большинства лог-файлов. При этом авторы четко разделяют полномочия групп +adm+ и
|
большинства лог-файлов. При этом авторы четко разделяют полномочия групп +adm+ и
|
||||||
+wheel+: если последняя используется для предоставления прав \emph{изменять}
|
+wheel+: если последняя используется для предоставления прав \emph{изменять}
|
||||||
что-либо в системе, то первая дает возможность лишь \emph{просматривать}
|
что-либо в системе, то первая дает возможность лишь \emph{просматривать}
|
||||||
системную информацию.}:
|
системную информацию. Начиная с версии systemd 198, группа-владелец файлов
|
||||||
|
журнала изменена с +adm+ на +systemd-journal+, однако штатный алгоритм установки
|
||||||
|
systemd все равно выдает права на их чтение группам +adm+ и +wheel+ (через
|
||||||
|
ACL).}:
|
||||||
\begin{Verbatim}
|
\begin{Verbatim}
|
||||||
$ journalctl
|
$ journalctl
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
@@ -3801,7 +3813,7 @@ $ journalctl -F _SYSTEMD_UNIT
|
|||||||
однако, начиная с релиза systemd 196, аналогичная функциональность доступна и
|
однако, начиная с релиза systemd 196, аналогичная функциональность доступна и
|
||||||
для zsh.}! Это же просто прекрасно~--- вы можете просмотреть перечень значений
|
для zsh.}! Это же просто прекрасно~--- вы можете просмотреть перечень значений
|
||||||
поля и выбрать из него нужно прямо при вводе выражения. Возьмем для примера
|
поля и выбрать из него нужно прямо при вводе выражения. Возьмем для примера
|
||||||
метки SELinux. Помнится, имя поле начиналось с букв SE\ldots{}
|
метки SELinux. Помнится, имя поля начиналось с букв SE\ldots{}
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
$ journalctl _SE\textbf{<TAB>}
|
$ journalctl _SE\textbf{<TAB>}
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
@@ -3953,16 +3965,32 @@ CPUShares=1500
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Первая строка обеспечивает включение в нашу конфигурацию файла с настройками по
|
Первая строка обеспечивает включение в нашу конфигурацию файла с настройками по
|
||||||
умолчанию, сделанными разработчиками Apache или его сопровождающими в вашем
|
умолчанию, сделанными разработчиками Apache или его сопровождающими в вашем
|
||||||
дистрибутиве (если это включение не~указать явно, данный файл будет проигнорирован).
|
дистрибутиве (если это включение не~указать явно, данный файл будет
|
||||||
Далее, мы указываем тот параметр, который хотим изменить. Сохраняем файл,
|
проигнорирован). Далее, мы указываем тот параметр, который хотим
|
||||||
приказываем systemd перечитать конфигурацию, и перезапускаем Apache, чтобы
|
изменить\footnote{Прим. перев.: В новых версиях systemd, начиная со 198, можно
|
||||||
настройки вступили в силу\footnote{Прим. перев.: К сожалению, в настоящее время
|
поступить проще: вместо того, чтобы создавать свой юнит-файл в каталоге +/etc+ и
|
||||||
systemd не~поддерживает изменение параметров контрольных групп без перезапуска
|
включать в него содержимое штатного (из +/usr+), достаточно просто создать
|
||||||
службы. Но вы можете узнать контрольную группу службы командой наподобие
|
каталог +/etc/systemd/system/httpd.service.d/+ и поместить в него файл
|
||||||
+systemctl show -p ControlGroup avahi-daemon.service+, и выполнить настройки
|
+my_resource_limit.conf+ (суффикс +.conf+ обязателен), в котором указываются
|
||||||
любым удобным для вас способом, например, через запись значений в псевдофайлы
|
только те настройки, которые необходимо изменить (последние две строки
|
||||||
cgroupfs. Разумеется, при следующем запуске службы к ней будут применены
|
вышеприведенного листинга). Это никак не~отменяет основного конфигурационного
|
||||||
параметры, указанные в конфигурационном файле.}:
|
файла юнита (который может находиться в +/usr+ или +/etc+), однако настройки из
|
||||||
|
+.d+-каталогов имеют более высокий приоритет и могут перекрывать настройки
|
||||||
|
основного файла. Все вышесказанное относится и к другим примерам из этого
|
||||||
|
раздела.}. Сохраняем файл, приказываем systemd перечитать конфигурацию, и
|
||||||
|
перезапускаем Apache, чтобы настройки вступили в силу\footnote{Прим. перев.:
|
||||||
|
systemd версий до 197 включительно, не~поддерживает изменение параметров
|
||||||
|
контрольных групп без перезапуска службы. Но вы можете узнать контрольную группу
|
||||||
|
службы командой наподобие +systemctl show -p ControlGroup avahi-daemon.service+,
|
||||||
|
и выполнить настройки любым удобным для вас способом, например, через запись
|
||||||
|
значений в псевдофайлы cgroupfs (разумеется, при следующем запуске службы к ней
|
||||||
|
будут применены параметры, указанные в конфигурационном файле). Начиная с
|
||||||
|
systemd 198, в программу +systemctl+ добавлена поддержка команд
|
||||||
|
+set-cgroup-attr+, +unset-cgroup-attr+ и +get-cgroup-attr+, позволяющих
|
||||||
|
манипулировать практически всеми параметрами контрольных групп. При этом
|
||||||
|
поддерживается сохранение установленных таким образом параметров в виде
|
||||||
|
вспомогательных конфигурационных файлов в +.d+-каталогах (см. примечание
|
||||||
|
выше).}:
|
||||||
\begin{Verbatim}
|
\begin{Verbatim}
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl restart httpd.service
|
systemctl restart httpd.service
|
||||||
@@ -4139,6 +4167,742 @@ ControlGroupAttribute=memory.swappiness 70
|
|||||||
и они не~так сильно ухудшают производительность. Возможно, мы рассмотрим их в
|
и они не~так сильно ухудшают производительность. Возможно, мы рассмотрим их в
|
||||||
последующих статьях.
|
последующих статьях.
|
||||||
|
|
||||||
|
\section{Проверка на виртуальность}
|
||||||
|
|
||||||
|
Еще в начале разработки systemd, мы внимательно изучали существовавшие на тот
|
||||||
|
момент init-скрипты, выделяя наиболее типичные для них операции. Среди прочих, в
|
||||||
|
составленный нами список попала и такая функция, как определение виртуализации:
|
||||||
|
некоторые скрипты проверяли, запускаются они в виртуальном окружении (например,
|
||||||
|
KVM, VMWare, LXC и т.д.) или на полноценной, физической системе. Часть этих
|
||||||
|
скриптов отказывалась работать на виртуальных системах (например, службы
|
||||||
|
управления устройствами совершенно излишни в виртуальных контейнерах, не~имеющих
|
||||||
|
доступа к устройствам), другие же, наоборот, запускались только в определенных
|
||||||
|
виртуальных окружениях (например, всевозможные <<guest additions>>,
|
||||||
|
рекомендуемые к запуску на гостевых системах VMWare и VirtualBox). По-хорошему,
|
||||||
|
в некоторых ситуациях было бы более правильно проверять некоторые другие
|
||||||
|
условия, а не~пытаться явно определить наличие виртуализации. Тем не~менее,
|
||||||
|
всесторонне изучив вопрос, мы пришли к выводу, что во многих случаях
|
||||||
|
возможность явной проверки такого условия при запуске служб была бы очень
|
||||||
|
кстати. В результате, мы добавили поддержку соответствующей опции настройки
|
||||||
|
юнитов~---
|
||||||
|
\hreftt{http://www.freedesktop.org/software/systemd/man/systemd.unit.html}{ConditionVirtualization};
|
||||||
|
кроме того, мы создали небольшую утилиту, которую можно вызывать из
|
||||||
|
скриптов~---
|
||||||
|
\hreftt{http://www.freedesktop.org/software/systemd/man/systemd-detect-virt.html}{systemd-detect-virt(1)};
|
||||||
|
и наконец, мы предоставили простой интерфейс для шины D-Bus, позволяющий
|
||||||
|
получить информацию о виртуализации даже непривилегированным программам.
|
||||||
|
|
||||||
|
Определить, запущен код на виртуальной системе, или на физической, на самом деле
|
||||||
|
\href{http://cgit.freedesktop.org/systemd/systemd/tree/src/shared/virt.c#n30}{не~так
|
||||||
|
уж и сложно}. В зависимости от того, какие именно механизмы виртуализации вы
|
||||||
|
хотите определить, основная работа сводится к выполнению инструкции CPUID и,
|
||||||
|
возможно, проверке некоторых файлов в +/sys+ и +/proc+. Основная трудность
|
||||||
|
здесь~--- точно знать строки, которые нужно искать. Список таких строк
|
||||||
|
необходимо поддерживать в актуальном состоянии. В настоящий момент, systemd
|
||||||
|
определяет следующие механизмы виртуализации:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Полная виртуализация (т.е. виртуальные машины):
|
||||||
|
\begin{itemize}
|
||||||
|
\item qemu
|
||||||
|
\item kvm
|
||||||
|
\item vmware
|
||||||
|
\item microsoft
|
||||||
|
\item oracle
|
||||||
|
\item xen
|
||||||
|
\item bochs
|
||||||
|
\end{itemize}
|
||||||
|
\item Виртуализация на уровне ОС (т.е. контейнеры):
|
||||||
|
\begin{itemize}
|
||||||
|
\item chroot
|
||||||
|
\item openvz
|
||||||
|
\item lxc
|
||||||
|
\item lxc-libvirt
|
||||||
|
\item \hyperref[sec:chroots]{systemd-nspawn}
|
||||||
|
\end{itemize}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Рассмотрим, как можно использовать эту функциональность.
|
||||||
|
|
||||||
|
\subsection{Условия на запуск юнитов}
|
||||||
|
|
||||||
|
При помощи опции
|
||||||
|
\hreftt{http://www.freedesktop.org/software/systemd/man/systemd.unit.html}{ConditionVirtualization},
|
||||||
|
добавленной в секцию +[Unit]+ файла конфигурации юнита, вы можете обеспечить
|
||||||
|
запуск (или наоборот, отмену запуска) данного юнита в зависимости от того,
|
||||||
|
работает ли он на виртуальной системе, или нет. В случае утвердительного ответа,
|
||||||
|
также можно уточнить, какая система виртуализации при этом используется.
|
||||||
|
Например:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Name=My Foobar Service (runs only only on guests)
|
||||||
|
ConditionVirtualization=yes
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/foobard
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Помимо <<+yes+>> или <<+no+>>, вы также можете указать идентификатор конкретной
|
||||||
|
системы виртуализации (согласно списку выше, например, <<+kvm+>>, <<+vmware+>> и
|
||||||
|
т.д.), либо <<+container+>> или <<+vm+>> (что позволит отличить виртуализацию на
|
||||||
|
уровне ОС от полной виртуализации). Кроме того, вы можете добавить перед
|
||||||
|
значением восклицательный знак, и результат проверки будет инвертирован (юнит
|
||||||
|
запустится только в том случае, если указанная технология
|
||||||
|
\emph{не}~используется). Подробности вы можете узнать на
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/systemd.unit.html}{странице
|
||||||
|
руководства}.
|
||||||
|
|
||||||
|
\subsection{В скриптах}
|
||||||
|
|
||||||
|
В скриптах оболочки вы можете выполнить аналогичные проверки при помощи утилиты
|
||||||
|
\hreftt{http://www.freedesktop.org/software/systemd/man/systemd-detect-virt.html}{systemd-detect-virt(1)}.
|
||||||
|
Например:
|
||||||
|
\begin{Verbatim}
|
||||||
|
if systemd-detect-virt -q ; then
|
||||||
|
echo "Virtualization is used:" `systemd-detect-virt`
|
||||||
|
else
|
||||||
|
echo "No virtualization is used."
|
||||||
|
fi
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Эта утилита возвращает код 0 (успех), обнаружив виртуализацию, или ненулевое
|
||||||
|
значение, если виртуализация не~выявлена. Также она выводит идентификатор
|
||||||
|
обнаруженной системы виртуализации (согласно списку выше), если это не~было
|
||||||
|
запрещено опцией +-q+. Кроме того, опции +-c+ и +-v+ позволяют ограничить
|
||||||
|
проверки только механизмами виртуализации на уровне ОС, либо полной
|
||||||
|
виртуализации, соответственно. Подробности см. на
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/systemd-detect-virt.html}{странице
|
||||||
|
руководства}.
|
||||||
|
|
||||||
|
\subsection{В программах}
|
||||||
|
|
||||||
|
Информация о виртуализации также представлена на системной шине:
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ gdbus call --system --dest org.freedesktop.systemd1 --object-path /org/freedesktop/systemd1 \
|
||||||
|
> --method org.freedesktop.DBus.Properties.Get org.freedesktop.systemd1.Manager Virtualization
|
||||||
|
(<'systemd-nspawn'>,)
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Если виртуализация не~выявлена, это свойство содержит пустую строку. Обратите
|
||||||
|
внимание, что некоторые контейнерные системы не~могут быть обнаружены напрямую
|
||||||
|
из непривилегированного кода. Именно поэтому мы не~стали создавать библиотеку, а
|
||||||
|
воспользовались шиной D-Bus, которая позволяет корректно решить проблему
|
||||||
|
привилегий.
|
||||||
|
|
||||||
|
Стоит отметить, что все эти инструменты определяют только <<самый внутренний>>
|
||||||
|
из задействованных механизмов виртуализации. Если вы используете несколько
|
||||||
|
систем, вложенных друг в друга, вышеописанные инструменты обнаружат только ту, в
|
||||||
|
которой они непосредственно запущены. В частности, если они работают в
|
||||||
|
контейнере, находящемся внутри виртуальной машины, они увидят только контейнер.
|
||||||
|
|
||||||
|
\section{Сокет-активация служб и контейнеров}
|
||||||
|
|
||||||
|
\href{http://0pointer.de/blog/projects/socket-activation.html}{Сокет}-%
|
||||||
|
\href{http://0pointer.de/blog/projects/socket-activation2.html}{активация}~---
|
||||||
|
это одна из наиболее интересных возможностей systemd. Еще в
|
||||||
|
\href{http://0pointer.de/blog/projects/systemd.html}{первом анонсе} нашего
|
||||||
|
проекта мы рассказывали о том, как этот механизм улучшает
|
||||||
|
параллелизацию и отказоустойчивость использующих сокеты служб, а также упрощает
|
||||||
|
формирование зависимостей между службами при загрузке. В данной статье я
|
||||||
|
продолжу рассказ о его возможностях~--- на этот раз речь пойдет об увеличении
|
||||||
|
числа служб и контейнеров, работающих на одной и той же системе, без повышения
|
||||||
|
потребления ресурсов. Другими словами: как можно увеличить количество клиентских
|
||||||
|
сайтов на хостинговых серверах без затрат на новое оборудование.
|
||||||
|
|
||||||
|
\subsection{Сокет-активация сетевых служб}
|
||||||
|
|
||||||
|
Начнем с небольшого отступления. Итак, что же такое сокет-активация, и как она
|
||||||
|
работает? На самом деле все довольно просто. systemd создает <<слушающие>>
|
||||||
|
сокеты (не~обязательно IP) от имени вашей службы (которая пока не~запущена) и
|
||||||
|
ожидает входящие соединения. Как только в сокет поступает первый запрос, systemd
|
||||||
|
запускает службу и передает ей полученные данные. После обработки запроса, в
|
||||||
|
зависимости от реализации службы, она может продолжать работу, ожидая новых
|
||||||
|
соединений, или завершиться, переложив эту задачу обратно на systemd (который
|
||||||
|
вновь запустит ее при поступлении очередного запроса). При этом, со стороны
|
||||||
|
клиента невозможно отличить, когда служба запущена, а когда~--- нет. Сокет
|
||||||
|
постоянно остается открытым для входящих соединений, и все они обрабатываются
|
||||||
|
быстро и корректно.
|
||||||
|
|
||||||
|
Такая конфигурация позволяет снизить потребление системных ресурсов: службы
|
||||||
|
работают и потребляют ресурсы только тогда, когда это действительно необходимо.
|
||||||
|
Многие интернет-сайты и службы могут использовать это с выгодой для себя.
|
||||||
|
Например, хостеры веб-сайтов знают, что из огромного количества существующих в
|
||||||
|
Интернете сайтов лишь малая часть получает непрерывный поток запросов.
|
||||||
|
Большинство же сайтов, хотя и должны постоянно оставаться доступными, получают
|
||||||
|
запросы очень редко. Используя сокет-активацию, вы можете воспользоваться этим:
|
||||||
|
разместив множество таких сайтов на одной системе и активируя их службы только
|
||||||
|
при необходимости, вы получаете возможность <<оверкоммита>>: ваша система будет
|
||||||
|
обслуживать сайтов больше, чем формально позволяют ее ресурсы\footnote{Прим.
|
||||||
|
перев.: Стоит отметить, что подобная схема работает только при условии, что для
|
||||||
|
каждого клиентского сайта запускаются отдельные процессы служб, хотя это и
|
||||||
|
происходит в рамках одного хоста. Не~очень распространенный в отчественном
|
||||||
|
хостинге вариант: обычно следующей опцией после shared-хостинга (одна служба на
|
||||||
|
всех клиентов) идет VPS (каждому клиенту по виртуальному хосту).}. Разумеется,
|
||||||
|
увлекаться оверкоммитом не~стоит, иначе в моменты пиковой нагрузки ресурсов
|
||||||
|
может действительно не~хватить.
|
||||||
|
|
||||||
|
С помощью systemd вы без труда можете организовать такую схему. Множество
|
||||||
|
современных сетевых служб уже поддерживают сокет-активацию <<из коробки>> (а в
|
||||||
|
те, которые пока не~поддерживают, ее
|
||||||
|
\href{http://0pointer.de/blog/projects/socket-activation.html}{не~так уж} и
|
||||||
|
\href{http://0pointer.de/blog/projects/socket-activation2.html}{сложно}
|
||||||
|
добавить). Реализованный в systemd механизм управления
|
||||||
|
\hyperref[sec:instances]{экземплярами служб} позволяет подготовить
|
||||||
|
универсальные шаблоны конфигурации служб, и в соответствии с ними для каждого
|
||||||
|
сайта будет запускаться свой экземпляр службы. Кроме того, не~стоит забывать,
|
||||||
|
что systemd предоставляет \hyperref[sec:security]{внушительный арсенал}
|
||||||
|
механизмов обеспечения безопасности и разграничения доступа, который позволит
|
||||||
|
изолировать клиентские сайты друг от друга (например, службы каждого клиента
|
||||||
|
будут видеть только его собственный домашний каталог, в то время как каталоги
|
||||||
|
всех остальных пользователей будут им недоступны). Итак, в конечном итоге вы
|
||||||
|
получаете надежную и масштабируемую серверную систему, на сравнительно небольших
|
||||||
|
ресурсах которой функционирует множество безопасно изолированных друг от друга
|
||||||
|
служб~--- и все это реализовано штатными возможностями вашей ОС\footnote{Прим.
|
||||||
|
перев.: В качестве практического примера использования сокет-активации служб
|
||||||
|
systemd в промышленных серверных платформах, можно предложить
|
||||||
|
\href{http://savanne.be/articles/deploying-node-js-with-systemd/}{вот эту
|
||||||
|
статью}, наглядно описывающую применение этой и других технологий (мониторинг,
|
||||||
|
использование Journal, ограничение ресурсов и доступа) на примере Node.js.}.
|
||||||
|
|
||||||
|
Подобные конфигурации уже используются на рабочих серверах ряда компаний. В
|
||||||
|
частности, специалисты из \href{https://www.getpantheon.com/}{Pantheon}
|
||||||
|
используют такую схему для обслуживания масштабируемой инфраструктуры множества
|
||||||
|
сайтов на базе Drupal. (Стоит упомянуть, что заслуга ее внедрения в компании
|
||||||
|
Pantheon принадлежит Дэвиду Штрауссу. Дэвид, ты крут!)
|
||||||
|
|
||||||
|
\subsection{Сокет-активация контейнеров}
|
||||||
|
|
||||||
|
Все вышеописанные технологии уже реализованы в ранее вышедших версиях systemd.
|
||||||
|
Если ваш дистрибутив поддерживает systemd, вы можете воспользоваться этими
|
||||||
|
механизмами прямо сейчас. А теперь сделаем шаг вперед: начиная с
|
||||||
|
systemd 197 (и, соответственно, с Fedora~19), мы добавили поддержку
|
||||||
|
сокет-активации \emph{виртуальных контейнеров} с полноценными ОС внутри. И
|
||||||
|
я считаю это действительно важным достижением.
|
||||||
|
|
||||||
|
Сокет-активация контейнеров работает следующим образом. Изначально, systemd
|
||||||
|
хост-системы слушает порты от имени контейнера (например, порт SSH, порт
|
||||||
|
веб-сервера и порт сервера СУБД). При поступлении на любой из этих портов
|
||||||
|
входящего запроса, systemd запускает контейнер и передает ему все его сокеты.
|
||||||
|
Внутри контейнера, еще один systemd (init гостевой системы) принимает эти
|
||||||
|
сокеты, после чего вступает в работу вышеописанная схема обычной сокет-активации
|
||||||
|
служб. При этом, SSH-сервер, веб-сервер и СУБД-сервер <<видят>> только ОС
|
||||||
|
контейнера~--- хотя они были активированы сокетами, созданными на хосте! Для
|
||||||
|
клиента все эти тонкости скрыты. Таким образом, мы получаем виртуальный
|
||||||
|
контейнер с собственной ОС, активируемый при поступлении входящего сетевого
|
||||||
|
соединения, причем совершенно прозрачно для клиента\footnote{Кстати говоря,
|
||||||
|
\href{https://plus.google.com/115547683951727699051/posts/cVrLAJ8HYaP}{это еще
|
||||||
|
один аргумент} в пользу важности быстрой загрузки для серверных систем.}.
|
||||||
|
|
||||||
|
Внутри контейнера функционирует полноценная ОС, причем ее дистрибутив
|
||||||
|
не~обязательно совпадает с дистрибутивом хост-системы. Например, вы можете
|
||||||
|
установить на хосте Fedora, и запускать на нем несколько контейнеров с Debian.
|
||||||
|
Контейнеры имеют собственные init-системы, собственные SSH-серверы, собственные
|
||||||
|
списки процессов и т.д., но при этом пользуются некоторыми механизмами ОС хоста
|
||||||
|
(например, управлением памятью).
|
||||||
|
|
||||||
|
К настоящему моменту сокет-активация контейнеров поддерживается лишь встроенным
|
||||||
|
в systemd простейшим контейнерным менеджером~---
|
||||||
|
\hyperref[sec:chroots]{systemd-nspawn}. Мы надеемся, что соответствующая
|
||||||
|
возможность вскоре появится и в
|
||||||
|
\href{http://libvirt.org/drvlxc.html}{libvirt-lxc}. А пока, за отсутствие
|
||||||
|
альтернатив, рассмотрим использование этого механизма на примере systemd-nspawn.
|
||||||
|
|
||||||
|
Начнем с установки файлов ОС контейнера в выбранный каталог. Детальное
|
||||||
|
рассмотрение этого вопроса выходит далеко за рамки нашего обсуждения, и
|
||||||
|
при том детально рассмотрено во многих статьях и руководствах. Поэтому
|
||||||
|
ограничусь лишь несколькими наиболее важными замечаниями. В частности, команда
|
||||||
|
для установки Fedora будет выглядеть следующим образом:
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ yum --releasever=19 --nogpg --installroot=/srv/mycontainer/ --disablerepo='*' \
|
||||||
|
> --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal
|
||||||
|
\end{Verbatim}
|
||||||
|
а для Debian~---
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ debootstrap --arch=amd64 unstable /srv/mycontainer/
|
||||||
|
\end{Verbatim}
|
||||||
|
Также см. последние абзацы страницы руководства
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html}{systemd-nspawn(1)}.
|
||||||
|
Стоит отметить, что в настоящее время реализация системного аудита в Linux
|
||||||
|
не~поддерживает виртуальные контейнеры, и ее включение в ядре хоста вызовет
|
||||||
|
множество ошибок при попытке запустить контейнер. Отключить ее можно добавлением
|
||||||
|
+audit=0+ в строку параметров загрузки ядра хоста.
|
||||||
|
|
||||||
|
Разумеется, внутри контейнера должен должен быть установлен systemd версии
|
||||||
|
не~ниже 197. Установить его и произвести другие необходимые настройки можно при
|
||||||
|
помощи того же \hyperref[sec:chroots]{systemd-nspawn} (пока что в режиме аналога
|
||||||
|
+chroot+, т.е. без параметра +-b+). После этого можно попробовать загрузить ОС
|
||||||
|
контейнера, используя systemd-nspawn уже с параметром +-b+.
|
||||||
|
|
||||||
|
Итак, ваш контейнер нормально загружается и работает. Подготовим для него
|
||||||
|
service-файл, при помощи которого systemd сможет запускать и останавливать
|
||||||
|
виртуальное окружение. Для этого, создадим на хост-системе файл
|
||||||
|
+/etc/systemd/system/mycontainer.service+ со следующим содержанием:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=My little container
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/systemd-nspawn -jbD /srv/mycontainer 3
|
||||||
|
KillMode=process
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Теперь мы можем запускать и останавливать эту службу командами +systemctl start+
|
||||||
|
и +stop+. Однако, пока что мы не~можем войти в эту систему\footnote{Прим.
|
||||||
|
перев.: Ручной запуск на хосте соответствующей команды +systemd-nspawn -b+ во
|
||||||
|
время работы такой службы просто создаст \emph{еще один контейнер}. Хотя
|
||||||
|
корневой каталог у них один и тот же, пространства имен (например, списки
|
||||||
|
процессов) у каждого будут свои. Впрочем, данная задача может быть решена
|
||||||
|
утилитой +nsenter+, которая должна войти в следующий релиз util-linux
|
||||||
|
(предположительно, 2.23).}. Чтобы исправить это упущение, настроим на контейнере
|
||||||
|
SSH-сервер, причем таким образом, что подключение к его порту активировало весь
|
||||||
|
контейнер, а затем активировало сервер, работающий внутри. Начнем с того, что
|
||||||
|
прикажем хосту слушать порт SSH для контейнера. Для этого создадим на хосте файл
|
||||||
|
+/etc/systemd/system/mycontainer.socket+:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=The SSH socket of my little container
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=23
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
После того, как мы запустим этот юнит командой +systemctl start+, systemd будет
|
||||||
|
слушать 23-й TCP-порт хоста. В примере выбран именной 23-й, потому что 22-й
|
||||||
|
скорее всего окажется занят SSH-сервером самого хоста. nspawn виртуализует
|
||||||
|
списки процессов и точек монтирования, но не~сетевые стеки, поэтому порты хоста
|
||||||
|
и гостей не~должны конфликтовать\footnote{Прим. перев.: Ограниченные возможности
|
||||||
|
виртуализации сети в +systemd-nspawn+ значительно затрудняют использование
|
||||||
|
описываемой технологии. Ее практическое применение будет иметь смысл после
|
||||||
|
реализации соответствующей поддержки в lxc-libvirt, либо расширения возможностей
|
||||||
|
nspawn. Впрочем, опытные администраторы легко могут найти обходные пути,
|
||||||
|
например: присваивание хосту дополнительного IP-адреса (безо всякой
|
||||||
|
виртуализации, командой +ip addr add+) и привязка слушающих сокетов к конкретным
|
||||||
|
адресам (в параметре +ListenStream=+ сокет-файлов и/или в директиве
|
||||||
|
+ListenAddress+ файла +sshd_config+ хоста).}.
|
||||||
|
|
||||||
|
Пока что systemd, работающий внутри контейнера, не~знает, что делать с тем
|
||||||
|
сокетами, которые ему передает systemd хоста. Если вы попробуете подключиться к
|
||||||
|
порту 23, контейнер запустится, но сетевое соединение немедленно будет закрыто,
|
||||||
|
так как данному сокету не~соответствует пока никакой сервер. Давайте это
|
||||||
|
исправим!
|
||||||
|
|
||||||
|
Настройка сокет-активации службы SSH была детально рассмотрена
|
||||||
|
\hyperref[sec:inetd]{в одной из предыдущих статей}, поэтому ограничусь
|
||||||
|
приведением содержимого необходимых для этого конфигурационных файлов. Файл
|
||||||
|
настроек для сокета
|
||||||
|
(+/srv/mycontainer/etc/systemd/system/sshd.socket+)\footnote{Прим. перев.:
|
||||||
|
Обратите внимание на разницу между файлами конфигурации сокетов на хосте и
|
||||||
|
в контейнере. Внутри контейнера используются параметры +Accept=yes+ и
|
||||||
|
+StandardInput=socket+, которые не~задействованы на хосте. Это обусловлено тем
|
||||||
|
фактом, что внутри контейнера сокет-активация производится в стиле inetd (служба
|
||||||
|
получает только один сокет, причем замкнутый на ее потоки STDIN и STDOUT), в то
|
||||||
|
время как на стороне хоста используется родной стиль активации systemd, при
|
||||||
|
котором запущенному процессу (в данном случае +systemd-nspawn+) просто
|
||||||
|
передаются открытые файловые дескрипторы (+fd+) всех сокетов. Одно из достоинств
|
||||||
|
такого подхода~--- возможность передавать сразу несколько сокетов, что позволяет
|
||||||
|
активировать внутри контейнера несколько серверов.}:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=SSH Socket for Per-Connection Servers
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=23
|
||||||
|
Accept=yes
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Соответствующий ему файл конфигурации службы \\
|
||||||
|
(+/srv/mycontainer/etc/systemd/system/sshd@.service+):
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=SSH Per-Connection Server for %I
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/usr/sbin/sshd -i
|
||||||
|
StandardInput=socket
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
После чего, добавим наш сокет в зависимости к цели +sockets.target+, чтобы
|
||||||
|
systemd создавал его автоматически при загрузке контейнера\footnote{Прим.
|
||||||
|
перев.: Возиться вручную с командой +ln+ здесь совершенно необязательно. Можно
|
||||||
|
просто добавить в файл +sshd.socket+ секцию +[Install]+, содержащую параметр
|
||||||
|
+WantedBy=sockets.target+, после чего добавление правильного симлинка будет
|
||||||
|
выполняться куда более очевидной командой
|
||||||
|
+systemctl --root=/srv/mycontainer enable sshd.socket+.}:
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ chroot /srv/mycontainer ln -s /etc/systemd/system/sshd.socket \
|
||||||
|
> /etc/systemd/system/sockets.target.wants/
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Собственно, все. После того, как мы запустим на хосте юнит +mycontainer.socket+,
|
||||||
|
systemd начнет прослушивать TCP-порт 23. При подключении к этому порту, systemd
|
||||||
|
запустит контейнер и передаст сокет ему. Внутри контейнера свой systemd, в
|
||||||
|
соответствии с файлом +sshd.socket+, примет этот сокет и запустит для нашего
|
||||||
|
соединения экземпляр +sshd@.service+, что позволит нам залогиниться в контейнер
|
||||||
|
по SSH.
|
||||||
|
|
||||||
|
Если нам нужно запуститьунтри контейнера другие службы с сокет-активацией, мы
|
||||||
|
можем добавить в +mycontainer.socket+ дополнительные сокеты. Все они будут
|
||||||
|
прослушиваться, обращение к любому из них приведет к активации контейнера, и все
|
||||||
|
эти сокеты будут переданы контейнеру при его активации. Внутри контейнера они
|
||||||
|
будут обработаны соответствии с настройками имеющихся там сокет-юнитов. Те
|
||||||
|
сокеты, для которых соответствующих юнитов не~найдется, будут
|
||||||
|
закрыты\footnote{Прим. перев.: Стоит особо отметить, что описанная технология
|
||||||
|
работает только для служб, поддерживающих сокет-активацию в режимах inetd (все
|
||||||
|
классические inetd-службы, кроме встроенных) или systemd (зависят от библиотеки
|
||||||
|
+libsystemd-daemon.so+, либо содержат в исходниках заголовочный файл
|
||||||
|
+sd-daemon.h+). Службы, которые сами открывают себе слушающий сокет и
|
||||||
|
не~содержат кода для приема уже открытого сокета, так активировать нельзя.}, а
|
||||||
|
те сокеты, которые будут настроены для прослушивания внутри контейнера, но
|
||||||
|
не~получены от хоста, будут активированы и доступны изнутри контейнера (а если
|
||||||
|
это сетевые или файловые unix-сокеты, то и извне).
|
||||||
|
|
||||||
|
Итак, давайте отступим чуть назад и полюбуемся на результаты наших трудов. Что
|
||||||
|
мы получили в итоге? Возможность настраивать на одном хосте множество
|
||||||
|
контейнеров с полноценными ОС внутри, причем контейнеры запускаются только по
|
||||||
|
запросу, что позволяет снизить потребление системных ресурсов и, соответственно,
|
||||||
|
увеличить количество контейнеров (по сравнению с принудительной их активацией
|
||||||
|
при загрузке хоста).
|
||||||
|
|
||||||
|
Разумеется, описанный подход работает только для контейнерной виртуализации, и
|
||||||
|
неприменим к полной, т.е. может быть использован только с технологиями наподобие
|
||||||
|
libvirt-lxc или nspawn, но не~c qemu/kvm или xen.
|
||||||
|
|
||||||
|
Если вы будете администрировать несколько таких контейнеров, вас наверняка
|
||||||
|
порадует одна из возможностей journal: при запуске на хосте утилиты +journalctl+
|
||||||
|
с ключом +-m+, она автоматически обнаружит журналы гостевых контейнеров и
|
||||||
|
объединит их вывод с выводом журнала хоста\footnote{Прим. перев.: Этот трюк
|
||||||
|
работает благодаря опции +-j+, которую мы передаем программе +systemd-nspawn+
|
||||||
|
при запуске контейнера (см. файл юнита выше). В соответствии с ней, в каталоге
|
||||||
|
+/var/log/journal+ хоста создается символьная ссылку на соответствующий каталог
|
||||||
|
гостя. При этом, так как сообщения от гостей имеют другие machine ID, journalctl
|
||||||
|
хоста не~выводит их, если явно не~указать +-m+. Подробности см. на страницах
|
||||||
|
руководства
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html}{systemd-nspawn(1)}
|
||||||
|
и
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/journalctl.html}{journalctl(1)}.}.
|
||||||
|
Ловко, не~правда ли?
|
||||||
|
|
||||||
|
Необходимый минимум технологий для сокет-активации контейнеров, присутствует в
|
||||||
|
systemd, начиная с версии 197. Тем не~менее, наша работа в этой области еще
|
||||||
|
не~закончена, и в ближайшее время мы планируем доработать некоторые моменты.
|
||||||
|
Например, сейчас, даже если все серверные службы внутри контейнера
|
||||||
|
закончили обработку запросов и завершились, контейнер все равно продолжает
|
||||||
|
функционировать и потреблять ресурсы хоста. Мы просто обязаны реализовать
|
||||||
|
возможность автоматического завершения работы гостевой системы в такой ситуации.
|
||||||
|
Причем у нас уже есть готовые наработки в этой области~--- мы можем
|
||||||
|
задействовать уже существующую инфраструктуру, обеспечивающую автоматическое
|
||||||
|
засыпание/выключение ноутбука при отсутствии активных задач и пользователей.
|
||||||
|
|
||||||
|
Впрочем, пора закругляться, а то статья получается чересчур длинной. Надеюсь,
|
||||||
|
что вы смогли продраться через все эти длинные и скучные рассуждения о
|
||||||
|
виртуализации, сокетах, службах, различных ОС и прочем колдунстве. Также
|
||||||
|
надеюсь, что эта статья станет хорошей отправной точкой при конфигурировании
|
||||||
|
мощных и хорошо масштабируемых серверных систем. За дополнительной информацией
|
||||||
|
обращайтесь к документации или приходите на наш IRC-канал. Спасибо за внимание!
|
||||||
|
|
||||||
|
\appendix
|
||||||
|
|
||||||
|
\section{Диагностика проблем при работе с systemd}
|
||||||
|
|
||||||
|
\subsection{Диагностика проблем с загрузкой}
|
||||||
|
|
||||||
|
Если система зависает во время загрузки, прежде всего нужно разобраться, на
|
||||||
|
каком этапе возникает проблема~--- до запуска systemd, или после.
|
||||||
|
|
||||||
|
Для этого надо удалить из командной стоки ядра параметры +quiet+ и +rhgb+. При
|
||||||
|
работе systemd на экран выводятся примерно такие сообщения:
|
||||||
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
|
Welcome to \textcolor{blue}{Fedora \emph{ВЕРСИЯ} (\emph{имя релиза})}!
|
||||||
|
Starting \emph{название}...
|
||||||
|
[ \textcolor{green}{OK} ] Stared \emph{название}...
|
||||||
|
\end{Verbatim}
|
||||||
|
(Пример можно посмотреть на
|
||||||
|
\href{http://freedesktop.org/wiki/Software/systemd/Debugging?action=AttachFile&do=view&target=f17boot.png}{скриншоте}.)
|
||||||
|
|
||||||
|
Если у вас есть доступ к оболочке, это значительно упрощает диагностику и
|
||||||
|
решение проблем. В том случае, когда до приглашения входа в систему дело так и
|
||||||
|
не~доходит, попробуйте переключиться на другую виртуальную консоль, нажав
|
||||||
|
CTRL--ALT--F<\emph{цифра}>. Дело в том, что при проблемах, связанных с запуском
|
||||||
|
X-сервера, может возникать ситуация, когда на первой консоли (+tty1+)
|
||||||
|
приглашение ко входу отсутствует, но все остальные консоли при этом работают
|
||||||
|
нормально.
|
||||||
|
|
||||||
|
Если ни~на одной из виртуальных консолей приглашение так и не~появилось~---
|
||||||
|
попробуйте выждать еще \emph{порядка 5 минут}. Только после этого можно
|
||||||
|
будет утверждать, что процесс загрузка завис окончательно. Если подвисание
|
||||||
|
обусловлено сбоем при запуске какой-то службы, то после истечения
|
||||||
|
тайм-аута проблемная служба будет убита, и загрузка может продолжиться. Другой
|
||||||
|
вариант~--- отсутствует устройство, которое должно быть смонтировано для
|
||||||
|
нормальной работы системы. В этом случае загрузка будет остановлена, и система
|
||||||
|
перейдет в \emph{аварийный режим (emergency mode)}.
|
||||||
|
|
||||||
|
\subsubsection{Если у вас нет~доступа к оболочке}
|
||||||
|
|
||||||
|
Если система не~предоставила вам ни~нормального приглашения, ни~аварийной
|
||||||
|
оболочки, то для диагностики проблемы нужно выполнить следующие действия:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Попытайтесь перезагрузить систему, нажав CTRL--ALT--DEL. Если после
|
||||||
|
этого перезагрузки не~произойдет~--- обязательно укажите данное
|
||||||
|
обстоятельство, когда будете писать отчет об ошибке (bugreport).
|
||||||
|
Чтобы перезагрузить систему, вы можете воспользоваться
|
||||||
|
\href{http://fedoraproject.org/wiki/QA/Sysrq}{SysRq} или
|
||||||
|
<<аппаратным>> методом.
|
||||||
|
\item При следующей загрузке попробуйте воспользоваться некоторыми
|
||||||
|
нижеописанными стратегиями.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\begin{description}
|
||||||
|
\item[Вывод диагностических сообщений на последовательную консоль]%
|
||||||
|
\hypertarget{it:serial}{} Если у вас под рукой есть терминал
|
||||||
|
последовательной консоли, либо дело происходит в виртуальной машине (в
|
||||||
|
частности, virt-manager позволяет просматривать вывод виртуальной машины
|
||||||
|
на последовательную консоль: меню Вид (View)~$\Rightarrow$ Текстовые
|
||||||
|
консоли (Text Consoles)), вы можете попросить systemd выводить на эту
|
||||||
|
консоль подробную отладочную информацию о ходе загрузки, добавив к
|
||||||
|
параметрам ядра следующие аргументы:
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemd.log_level=debug systemd.log_target=console console=ttyS0,38400
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
\item[Загрузка в восстановительном (rescue) или аварийном (emergency)
|
||||||
|
режимах] Чтобы загрузиться в восстановительном режиме, добавьте к
|
||||||
|
параметрам ядра +systemd.unit=rescue.target+, или просто +1+. Это режим
|
||||||
|
эффективен для решения проблем, возникающих на этапе запуска обычных
|
||||||
|
служб, когда ключевые компоненты системы уже инициализированы. В такой
|
||||||
|
ситуации, вы можете просто отключить проблемную службу. Если же загрузка
|
||||||
|
не~доходит даже до восстановительного режима~--- попробуйте менее
|
||||||
|
требовательный, аварийный режим.
|
||||||
|
|
||||||
|
Для загрузки напрямую в режим аварийной оболочки, добавьте к параметрам
|
||||||
|
ядра +systemd.unit=emergency.target+, или просто +emergency+. Обратите
|
||||||
|
внимание, что в аварийном режиме корневая система по умолчанию
|
||||||
|
монтируется в режиме <<только для чтения>>, поэтому перед
|
||||||
|
восстановительными работами, связанными с записью на диск, необходимо
|
||||||
|
перемонтировать ее в режиме <<для чтения и записи>>:
|
||||||
|
\begin{Verbatim}
|
||||||
|
mount -o remount,rw /
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Как правило, аварийная оболочка используется для исправления
|
||||||
|
некорректных записей в +/etc/fstab+. После внесения необходимых
|
||||||
|
изменений, скомандуйте +systemctl daemon-reload+, чтобы systemd увидел
|
||||||
|
ваши исправления.
|
||||||
|
|
||||||
|
Если не~работает даже аварийный режим, попробуйте загрузиться напрямую в
|
||||||
|
оболочку, добавив к параметрам ядра +init=/bin/sh+. Такая ситуация может
|
||||||
|
возникнуть вследствие повреждения бинарного файла systemd, либо
|
||||||
|
библиотек, которые он использует. В этом случае может помочь
|
||||||
|
переустановка соответствующих пакетов.
|
||||||
|
|
||||||
|
Если не~срабатывает даже +init=/bin/sh+, остается лишь попробовать
|
||||||
|
загрузиться с другого носителя.
|
||||||
|
|
||||||
|
\item[Отладочная оболочка]\hypertarget{it:dbgshell}{}
|
||||||
|
Вы можете включить специальную отладочную оболочку, которая запускается
|
||||||
|
в отдельной консоли на раннем этапе загрузки и позволяет собрать
|
||||||
|
необходимую диагностическую информацию, а также провести
|
||||||
|
восстановительные операции. Для включения отладочной оболочки
|
||||||
|
скомандуйте
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemctl enable debug-shell.service
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
\textbf{Совет:} Если вы используете старую версию systemd, в которой еще
|
||||||
|
не~реализована поддержка отладочной оболочки, вы можете загрузить
|
||||||
|
соответствующий файл конфигурации юнита из
|
||||||
|
\href{http://cgit.freedesktop.org/systemd/systemd/plain/units/debug-shell.service.in}{git-репозитария
|
||||||
|
systemd}. Перед использованием этого файла, замените в нем +@sushell@+
|
||||||
|
на +/bin/bash+.
|
||||||
|
|
||||||
|
\textbf{Совет:} Если вы не~можете воспользоваться командой +systemctl+
|
||||||
|
(например, загрузились с помощью другой операционной системы), вы можете
|
||||||
|
выполнить соответствующие действия и напрямую:
|
||||||
|
\begin{Verbatim}
|
||||||
|
cd $ПУТЬ_К_ВАШЕМУ_КОРНЮ/etc/systemd/system
|
||||||
|
mkdir -p sysinit.target.wants
|
||||||
|
ln -s /lib/systemd/system/debug-shell.service sysinit.target.wants/
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Отладочная оболочка будет запущена с правами +root+ на консоли +tty9+
|
||||||
|
при следующей загрузке системы. Чтобы переключиться на нее, нажмите
|
||||||
|
CTRL--ALT--F9. Оболочка запускается на самом раннем этапе загрузки и
|
||||||
|
позволяет вам проверять состояние служб, читать системные журналы,
|
||||||
|
выявлять зависшие задачи (командой +systemctl list-jobs+) и т.д.
|
||||||
|
|
||||||
|
\textbf{Предупреждение:} Используйте эту оболочку только для отладки!
|
||||||
|
Не~забудьте отключить ее после того, как разберетесь с проблемами.
|
||||||
|
Оставлять доступную всем и каждому оболочку с правами +root+, мягко
|
||||||
|
говоря, небезопасно.
|
||||||
|
|
||||||
|
\item[Проверка параметров ядра] Для корректной загрузки системы необходимо,
|
||||||
|
чтобы каталог +/dev+ был заполнен, хотя бы частично. Убедитесь, что ядро
|
||||||
|
Linux собрано с опциями +CONFIG_DEVTMPFS+ и +CONFIG_DEVTMPFS_MOUNT+.
|
||||||
|
Кроме того, для корректной работы systemd рекомендуется включить
|
||||||
|
поддержку контрольных групп и fanotify (опции +CONFIG_CGROUPS+ и
|
||||||
|
+CONFIG_FANOTIFY+ соответственно). Отключение этих опций может привести
|
||||||
|
к появлению сообщений об ошибках вида <<Failed to get D-Bus
|
||||||
|
connection: No connection to service manager.>> при попытке запуска
|
||||||
|
+systemctl+.
|
||||||
|
\end{description}
|
||||||
|
|
||||||
|
\subsubsection{Если у вас есть доступ к оболочке}
|
||||||
|
|
||||||
|
Если вам все-таки удалось получить доступ к оболочке системы, вы можете
|
||||||
|
воспользоваться ею для сбора диагностической информации. Загрузите систему со
|
||||||
|
следующими параметрами ядра:
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M
|
||||||
|
\end{Verbatim}
|
||||||
|
В соответствии с ними, systemd будет выводить максимально подробные сообщения о
|
||||||
|
процессе загрузки, и направлять их в кольцевой буфер ядра (последний параметр
|
||||||
|
обеспечивает соответствующее увеличение размера буфера). Дождавшись запуска
|
||||||
|
оболочки, сохраните полученный журнал:
|
||||||
|
\begin{Verbatim}
|
||||||
|
dmesg > dmesg.txt
|
||||||
|
\end{Verbatim}
|
||||||
|
Отправляя отчет об ошибке, присоедините к нему полученный файл +dmesg.txt+.
|
||||||
|
|
||||||
|
Также, вы можете просмотреть список операций, чтобы выявить зависшие задачи:
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemctl list-jobs
|
||||||
|
\end{Verbatim}
|
||||||
|
Операции, находящиеся в состоянии <<waiting>>, будут запущены на исполнение
|
||||||
|
только после того, как завершатся операции, выполняемые в данный момент
|
||||||
|
(состояние <<running>>).
|
||||||
|
|
||||||
|
\subsection{Диагностика проблем с выключением системы}
|
||||||
|
|
||||||
|
При зависании системы во время выключения, как и в случае с загрузкой,
|
||||||
|
рекомендуется подождать \emph{минимум 5 минут}, чтобы отличить полное зависание
|
||||||
|
системы от временного подвисания из-за проблем с отдельными службами. Также
|
||||||
|
стоит проверить, реагирует ли система на нажатие CTRL--ALT--DEL.
|
||||||
|
|
||||||
|
Если процесс остановки системы (при выключении или перезагрузке) зависает
|
||||||
|
полностью, прежде всего нужно убедиться, способно ли ядро Linux выключить или
|
||||||
|
перезагрузить систему. Для этого воспользуйтесь одной из команд:
|
||||||
|
\begin{Verbatim}
|
||||||
|
sync && reboot -f
|
||||||
|
sync && poweroff -f
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Если хотя бы одна из этих команд не~сработает~--- значит, проблема не~в systemd,
|
||||||
|
а в ядре.
|
||||||
|
|
||||||
|
\subsubsection{Система очень долго выключается}
|
||||||
|
|
||||||
|
Если ваша система все же может выключиться/перезагрузиться, но этот процесс
|
||||||
|
длится подозрительно долго, выполните нижеописанные операции:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Загрузите систему со следующими параметрами ядра:
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M enforcing=0
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
\item Создайте файл +/lib/systemd/system-shutdown/debug.sh+, добавьте
|
||||||
|
ему право на запуск и запишите в него следующие строки:
|
||||||
|
\begin{Verbatim}
|
||||||
|
#!/bin/sh
|
||||||
|
mount -o remount,rw /
|
||||||
|
dmesg > /shutdown-log.txt
|
||||||
|
mount -o remount,ro /
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
\item Перезагрузите систему.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
После этого вы можете самостоятельно проанализировать файл +/shutdown-log.txt+,
|
||||||
|
и/или присоединить его к вашему сообщению об ошибке.
|
||||||
|
|
||||||
|
\subsubsection{Система не~может выключиться самостоятельно}
|
||||||
|
|
||||||
|
Если процесс выключения или перезагрузки вашей системы не~завершается даже через
|
||||||
|
несколько минут, и вышеописанный метод с +shutdown-log+ не~сработал, вы можете
|
||||||
|
собрать диагностическую информацию другими методами (которые мы уже
|
||||||
|
рассматривали применительно к проблемам загрузки):
|
||||||
|
\begin{itemize}
|
||||||
|
\item Используйте \hyperlink{it:serial}{последовательную консоль}.
|
||||||
|
\item Воспользуйтесь \hyperlink{it:dbgshell}{отладочной оболочкой}~---
|
||||||
|
она полезна не~только на ранних стадиях загрузки, но и на
|
||||||
|
поздних стадиях остановки системы.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{Просмотр состояния службы и ее журнала}
|
||||||
|
|
||||||
|
Когда при запуске службы происходит сбой, systemd выводит весьма абстрактное
|
||||||
|
сообщение об ошибке:
|
||||||
|
\begin{Verbatim}
|
||||||
|
# systemctl start foo.service
|
||||||
|
Job failed. See system journal and 'systemctl status' for details.
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
При этом сама служба может выводить собственное сообщение, но вы (пока что) его
|
||||||
|
не~видите. Дело в том, что запуск служб происходит не~из вашей оболочки, а из
|
||||||
|
процесса systemd, и поэтому вывод программы не~привязан к вашей консоли. Тем
|
||||||
|
не~менее, это вовсе не~означает, что выводимые сообщения теряются. По умолчанию,
|
||||||
|
потоки STDOUT и STDERR, принадлежащие запускаемым службам, перенаправляются в
|
||||||
|
системный журнал (journal). Туда же попадают и сообщения, отправляемые с помощью
|
||||||
|
функции +syslog(3)+. Кроме того, systemd записывает код выхода сбойных
|
||||||
|
процессов. Посмотреть собранные данные можно, например, так:
|
||||||
|
\begin{Verbatim}
|
||||||
|
# systemctl status foo.service
|
||||||
|
foo.service - mmm service
|
||||||
|
Loaded: loaded (/etc/systemd/system/foo.service; static)
|
||||||
|
Active: failed (Result: exit-code) since Fri, 11 May 2012 20:26:23 +0200; 4s ago
|
||||||
|
Process: 1329 ExecStart=/usr/local/bin/foo (code=exited, status=1/FAILURE)
|
||||||
|
CGroup: name=systemd:/system/foo.service
|
||||||
|
|
||||||
|
May 11 20:26:23 scratch foo[1329]: Failed to parse config
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
В нашем примере, служба запустилась как процесс с идентификатором (PID) 1329,
|
||||||
|
после чего завершилась с кодом выхода 1. Если вы запустили команду
|
||||||
|
+systemctl status+ от имени пользователя +root+, либо от имени пользователя,
|
||||||
|
входящего в группу +adm+, вы также увидите последние несколько строчек,
|
||||||
|
записанные службой в журнал. В нашем примере служба выдала всего одно сообщение
|
||||||
|
(<<Failed to parse config>>).
|
||||||
|
|
||||||
|
Чтобы просмотреть весь журнал целиком, воспользуйтесь командой +journalctl+.
|
||||||
|
|
||||||
|
Если одновременно с journal вы используете и классический демон системного лога
|
||||||
|
(например, rsyslog), то все сообщения из журнала будут переданы также и этому
|
||||||
|
демону, который запишет их в традиционные лог-файлы (в какие именно~--- зависит
|
||||||
|
от его настроек, обычно +/var/log/messages+).
|
||||||
|
|
||||||
|
\subsection{Подготовка сообщений об ошибках}
|
||||||
|
|
||||||
|
Если вы собираетесь отправить сообщение об ошибке в systemd, пожалуйста,
|
||||||
|
включите в него диагностическую информацию, в частности, содержимое системных
|
||||||
|
журналов. Журналы должны быть полными (без вырезок), не~заархивированными, с
|
||||||
|
MIME-типом +text/plain+.
|
||||||
|
|
||||||
|
Прежде всего, отправьте сообщение в багтрекер своего дистрибутива. Если же вы
|
||||||
|
твердо уверены, что проблема именно в апстримном systemd, проверьте сначала
|
||||||
|
список
|
||||||
|
\href{https://bugs.freedesktop.org/buglist.cgi?query_format=advanced&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=systemd}{уже
|
||||||
|
известных ошибок}. Если вы не~найдете в нем своего случая~---
|
||||||
|
\href{https://bugs.freedesktop.org/enter_bug.cgi?product=systemd}{заводите новую
|
||||||
|
запись}.
|
||||||
|
|
||||||
|
\subsubsection{Что нужно включить в сообщение об ошибке}
|
||||||
|
|
||||||
|
По возможности, пожалуйста, укажите в самом сообщении, либо присоедините к нему,
|
||||||
|
следующую информацию:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Строку параметров ядра, если она отличается от значения по
|
||||||
|
умолчанию. Ее можно найти в файле конфигурации загрузчика
|
||||||
|
(например, +/boot/grub2/grub.cfg+) или в специальном файле
|
||||||
|
+/proc/cmdline+.
|
||||||
|
\item Копию файла +/var/log/messages+.
|
||||||
|
\item Файл +dmesg.txt+, полученный после выполнения команды
|
||||||
|
+dmesg > dmesg.txt+ (перед ее выполнением лучше загрузиться с
|
||||||
|
параметрами ядра
|
||||||
|
+systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M+.
|
||||||
|
\item Файл +systemd-dump.txt+, полученный в результате выполнения
|
||||||
|
команды +systemctl dump > systemd-dump.txt+.
|
||||||
|
\item Файл +systemd-test.txt+, полученный при помощи команды
|
||||||
|
+/usr/bin/systemd --test --system --log-level=debug > systemd-test.txt 2>&1+.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
\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