Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78ebb26a64 | ||
|
|
df098ff4c1 |
617
s4a.tex
617
s4a.tex
@@ -20,6 +20,8 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||||
\newcommand{\hreftt}[2]{\href{#1}{\texttt{#2}}}
|
||||
\newenvironment{caveat}[1][]{\smallskip\par\textbf{Предупреждение#1: }}%
|
||||
{\smallskip\par}
|
||||
\newcommand{\sfnote}[1]{\texorpdfstring{\protect\footnote%
|
||||
{Прим. перев.: #1}}{}}
|
||||
% Настройка макета страницы
|
||||
\setlength{\hoffset}{-1.5cm}
|
||||
\addtolength{\textwidth}{2cm}
|
||||
@@ -972,6 +974,7 @@ Apache, crond, atd, которые по роду служебной деятел
|
||||
не~отдельному процессу.
|
||||
|
||||
\section{Три уровня выключения}
|
||||
\label{sec:off}
|
||||
|
||||
В \href{http://www.freedesktop.org/wiki/Software/systemd}{systemd} существует
|
||||
три уровня (разновидности) действий, направленных на прекращение работы службы
|
||||
@@ -3485,7 +3488,15 @@ getty\footnote{Отметим, что +systemctl enable+ \emph{для экзем
|
||||
более ранних версиях придется напрямую манипулировать символьными ссылками:
|
||||
\texttt{ln -s /usr/lib/systemd/system/serial-getty@.service
|
||||
/etc/systemd/system/getty.target.wants/serial-getty@ttyS2.service ; systemctl
|
||||
daemon-reload}.}:
|
||||
daemon-reload}.}\footnote{Прим. перев.: На самом деле, работать с символьными
|
||||
ссылками придется даже в современных версиях systemd (на момент написания этих
|
||||
строк, последней является версия 202), так как разработчики забыли включить в
|
||||
файл +serial-getty@.service+ секцию +[Install]+, в результате чего попытка
|
||||
выполнения +systemctl enable+ для экземпляра соответствующей службы ведет к
|
||||
закономерной ошибке. Впрочем, исправить это несложно: достаточно скопировать
|
||||
данный файл в +/etc/systemd/system/+, после чего дописать в него секцию
|
||||
+[Install]+ с параметром +WantedBy=getty.target+, а затем выполнить
|
||||
+systemctl daemon-reload+.}:
|
||||
\begin{Verbatim}
|
||||
# systemctl enable serial-getty@ttyS2.service
|
||||
# systemctl start serial-getty@ttyS2.service
|
||||
@@ -4601,7 +4612,10 @@ systemd, начиная с версии 197. Тем не~менее, наша р
|
||||
|
||||
\appendix
|
||||
|
||||
\section{Диагностика проблем при работе с systemd}
|
||||
\section{Диагностика неполадок\sfnote{Перевод статьи
|
||||
<<\href{http://freedesktop.org/wiki/Software/systemd/Debugging}{Debugging
|
||||
systemd Problems}>> с официального сайта проекта, по состоянию на 2013-01-08
|
||||
19:13:31 (ревизия \No26).}}
|
||||
|
||||
\subsection{Диагностика проблем с загрузкой}
|
||||
|
||||
@@ -4628,9 +4642,9 @@ X-сервера, может возникать ситуация, когда н
|
||||
|
||||
Если ни~на одной из виртуальных консолей приглашение так и не~появилось~---
|
||||
попробуйте выждать еще \emph{порядка 5 минут}. Только после этого можно
|
||||
будет утверждать, что процесс загрузка завис окончательно. Если подвисание
|
||||
обусловлено сбоем при запуске какой-то службы, то после истечения
|
||||
тайм-аута проблемная служба будет убита, и загрузка может продолжиться. Другой
|
||||
будет считать процесс загрузки окончательно зависшим. Если подвисание
|
||||
обусловлено всего лишь сбоем при запуске какой-то службы, то после истечения
|
||||
тайм-аута проблемная служба будет убита, и загрузка продолжится. Другой
|
||||
вариант~--- отсутствует устройство, которое должно быть смонтировано для
|
||||
нормальной работы системы. В этом случае загрузка будет остановлена, и система
|
||||
перейдет в \emph{аварийный режим (emergency mode)}.
|
||||
@@ -4893,15 +4907,598 @@ MIME-типом +text/plain+.
|
||||
+/proc/cmdline+.
|
||||
\item Копию файла +/var/log/messages+.
|
||||
\item Файл +dmesg.txt+, полученный после выполнения команды
|
||||
+dmesg > dmesg.txt+ (перед ее выполнением лучше загрузиться с
|
||||
параметрами ядра
|
||||
+systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M+.
|
||||
\begin{Verbatim}
|
||||
dmesg > dmesg.txt
|
||||
\end{Verbatim}
|
||||
Перед ее выполнением лучше загрузиться с параметрами ядра
|
||||
\begin{Verbatim}
|
||||
systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M
|
||||
\end{Verbatim}
|
||||
\item Файл +systemd-dump.txt+, полученный в результате выполнения
|
||||
команды +systemctl dump > systemd-dump.txt+.
|
||||
команды
|
||||
\begin{Verbatim}
|
||||
systemctl dump > systemd-dump.txt
|
||||
\end{Verbatim}
|
||||
\item Файл +systemd-test.txt+, полученный при помощи команды
|
||||
+/usr/bin/systemd --test --system --log-level=debug > systemd-test.txt 2>&1+.
|
||||
\begin{Verbatim}
|
||||
/usr/bin/systemd --test --system --log-level=debug > systemd-test.txt 2>&1
|
||||
\end{Verbatim}
|
||||
\end{itemize}
|
||||
|
||||
\section{Предсказуемые имена сетевых интерфейсов\sfnote{Перевод статьи
|
||||
<<\href{http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames}%
|
||||
{Predictable Network Interface Names}>> с официального сайта проекта, по
|
||||
состоянию на 2013-01-22 20:22:48 (ревизия \No27).}}
|
||||
|
||||
Начиная с версии 197, systemd/udev присваивает сетевым интерфейсам (Ethernet,
|
||||
WLAN, WWAN\footnote{Прим. перев.: WWAN (Wireless Wide Area Network)~---
|
||||
относительно новый термин, обозначающий технологии глобальных беспроводных
|
||||
компьютерных сетей, такие, как GPRS, 3G, WiMAX и т.д.}) стабильные,
|
||||
предсказуемые имена. Новая схема именования несколько отличается от классической
|
||||
(+eth0+, +eth1+, +wlan0+, \ldots{}), однако при этом лишена и многих ее
|
||||
недостатков.
|
||||
|
||||
\subsection{Зачем?}
|
||||
|
||||
Классическая схема именования сетевых интерфейсов, используемая ядром,
|
||||
предполагает последовательное присвоение интерфейсам имен +eth0+, +eth1+ и т.д.,
|
||||
по мере опроса оборудования соответствующими драйверами (device probing). На
|
||||
современных системах такой опрос не~обеспечивает гарантированного соблюдения
|
||||
одного и того же порядка поступления ответов. Вследствие этого, соответствие
|
||||
имен реальным интерфейсам не~является чем-то фиксированным, и очень может быть,
|
||||
что интерфейс, который сейчас называется +eth0+, при следующей загрузке
|
||||
превратится в +eth1+. Такая ситуация приводит к целому ряду проблем, в
|
||||
частности, к проблемам с безопасностью: в настройках брандмауэра интерфейсы
|
||||
идентифицируются как раз по именам.
|
||||
|
||||
Существует несколько подходов к решению этой проблемы. В течение многих лет udev
|
||||
поддерживал механизм постоянной привязки имен к интерфейсам, на основе
|
||||
MAC-адресов. Такой подход имел множество недостатков, в том числе: требование
|
||||
доступности корневого каталога на запись (что возможно далеко не~всегда);
|
||||
необходимость внесения изменений в образ системы после загрузки на новом
|
||||
оборудовании; привязка к MAC-адресам, которые далеко не~всегда являются
|
||||
фиксированными (в частности, это касается многих встраиваемых систем и
|
||||
механизмов виртуализации). Тем не~менее, основная проблема такого подхода
|
||||
состояла в том, что он использовал имена из того же адресного пространства
|
||||
(+ethX+), что и ядро. Вследствие этого, возникали ситуации <<гонки>> между udev
|
||||
и ядром, когда udev пытался присвоить интерфейсу имя, которое ядро уже выдало
|
||||
другому интерфейсу, что приводило к сбою операции переименования. Вследствие
|
||||
перечисленных недостатков, данный механизм был удален из
|
||||
systemd/udev\footnote{Прим. перев.: См. коммит
|
||||
\href{http://cgit.freedesktop.org/systemd/systemd/commit/?id=3e2147858f21943d5f4a781c60f33ac22c6096ed}%
|
||||
{3e214} от 3 апреля 2012 года, в котором, среди прочего, был удален каталог
|
||||
+src/udev/src/rule_generator+.}.
|
||||
|
||||
Другая попытка решения обсуждаемой проблемы~--- +biosdevname+, программа,
|
||||
формирующая имена интерфейсов на основании их физического расположении на
|
||||
материнской плате. Соответствующая информация запрашивается у BIOS. В чем-то
|
||||
такая схема похожа на ту, которую udev уже давно использует для формирования
|
||||
стабильных символьных ссылок на различные устройства (+/dev/*/by-path/*+), но,
|
||||
тем не~менее, в ее основе лежат несколько иные алгоритмы (udev, формируя свои
|
||||
символьные ссылки, опирается на идентификационные данные, предоставленные
|
||||
ядром, в то время как biosdevname использует свои собственные схемы).
|
||||
|
||||
И наконец, многие дистрибутивы в своих сетевых скриптах поддерживают механизмы,
|
||||
позволяющие присваивать интерфейсам имена, выбранные пользователем (например,
|
||||
+internet0+, +dmz0+, \ldots). Если бы не~необходимость явного вмешательства
|
||||
пользователя, это было бы замечательным решением.
|
||||
|
||||
Мы пришли к выводу, что наилучшим вариантом для настроек по умолчанию будет
|
||||
схема, являющаяся обобщением и развитием механизма biosdevname. Присвоение
|
||||
интерфейсам имен на основании информации об их физическом расположении имеет ряд
|
||||
существенных достоинств: такие имена формируются автоматически, всегда
|
||||
предсказуемы, а также остаются неизменными даже при добавлении и удалении
|
||||
оборудования, что позволяет без лишних проблем заменять сломанные сетевые
|
||||
устройства. Тем не~менее, такие выглядят немного сложнее, чем привычные +eth0+ и
|
||||
+wlan0+, например: +enp5s0+.
|
||||
|
||||
\subsection{Что именно было изменено в версии 197?}
|
||||
|
||||
В версии 197 мы добавили в systemd/udevd встроенную поддержку нескольких
|
||||
различных механизмов именования сетевых интерфейсов, получив в итоге схему,
|
||||
похожую на biosdevname, но отличающуюся большей гибкостью и максимально
|
||||
приближенную к алгоритмам идентификации устройств, используемым в ядре.
|
||||
В частности, udev теперь штатно поддерживает следующие механизмы именования
|
||||
сетевых интерфейсов:
|
||||
\begin{enumerate}
|
||||
\item Схема именования для устройств, встроенных в материнскую плату (на
|
||||
основании информации от EFI/BIOS), например: +eno1+.
|
||||
\item Схема именования для устройств, подключенных в слоты PCI Express
|
||||
(также на основании информации от EFI/BIOS), например: +ens1+.
|
||||
\item Схема именования, основанная на физическом расположении точки
|
||||
подключения оборудования, например, +enp2s0+.
|
||||
\item Схема именования на основании MAC-адреса, например,
|
||||
+enx78e7d1ea46da+.
|
||||
\item Классические, непредсказуемые имена, присвоенные ядром, например,
|
||||
+eth0+.
|
||||
\end{enumerate}
|
||||
|
||||
По умолчанию, systemd 197 при именовании сетевых интерфейсов последовательно
|
||||
пытается применить схемы 1--3 (для первых двух требуется информация от
|
||||
EFI/BIOS). Если ни одна из них не~подходит, используется схема 5. Что касается
|
||||
схемы 4~--- она не~задействована по умолчанию, однако ее можно включить вручную.
|
||||
|
||||
Вышеописанная комбинированная схема используется лишь \emph{в последнюю
|
||||
очередь}. Если у вас установлена программа biosdevname, для именования сетевых
|
||||
устройств будет использоваться именно она. Кроме того, приоритет предоставляется
|
||||
любым правилам, добавленным пользователем или разработчиками дистрибутива.
|
||||
|
||||
\subsection{Еще раз, что здесь хорошего?}
|
||||
|
||||
С нашей новой схемой вы получаете:
|
||||
\begin{itemize}
|
||||
\item Имена интерфейсов остаются неизменными после перезагрузок.
|
||||
\item Имена интерфейсов остаются неизменными при добавлении или
|
||||
удалении устройств.
|
||||
\item Имена интерфейсов остаются неизменными при обновлении/изменении
|
||||
ядра и драйверов.
|
||||
\item Имена интерфейсов остаются неизменными при замене сломанных
|
||||
сетевых карт новыми.
|
||||
\item Имена формируются автоматически, безо всякого вмешательства
|
||||
пользователя.
|
||||
\item Имена являются предсказуемыми: достаточно просто взглянуть на
|
||||
вывод +lspci+, чтобы узнать, как будет называться конкретное
|
||||
устройство.
|
||||
\item Изменения в аппаратной конфигурации не~приводят к необходимости
|
||||
записи в каталог +/etc+.
|
||||
\item Полная поддержка системам, корень которых доступен только
|
||||
для чтения.
|
||||
\item Схема именования аналогичная той, которая используется
|
||||
udev для формирования стабильных символьных ссылок в каталоге
|
||||
+/dev+ (+by-path+).
|
||||
\item Работает как на x86, так и на~других архитектурах.
|
||||
\item Работает одинаково во всех дистрибутивах, использующих на
|
||||
systemd/udev.
|
||||
\item От этой схемы очень легко отказаться (см. ниже).
|
||||
\end{itemize}
|
||||
|
||||
Есть ли у нее недостатки? Да. Раньше, если на компьютере имелся всего один
|
||||
сетевой интерфейс, можно было с высокой долей вероятности утверждать, что он
|
||||
называется +eth0+. Теперь же, прежде чем администратор начнет настраивать сеть,
|
||||
он должен как минимум просмотреть список сетевых интерфейсов.
|
||||
|
||||
\subsection{Мне не~нравится ваша схема. Как ее отключить?}
|
||||
|
||||
У вас есть три варианта:
|
||||
\begin{enumerate}
|
||||
\item Вы можете полностью отключить новую схему, вернувшись к
|
||||
классическим непредсказуемым именам. Для этого достаточно
|
||||
заблокировать (замаскировать) соответствующий файл правил udev:
|
||||
\begin{Verbatim}
|
||||
ln -s /dev/null /etc/udev/rules.d/80-net-name-slot.rules
|
||||
\end{Verbatim}
|
||||
\item Вы можете вручную назначить интерфейсам наиболее понятные для вас
|
||||
имена (например, +internet0+, +dmz0+, +lan0+). Для этого,
|
||||
подготовьте свои собственные правила, указав в них нужные имена
|
||||
при помощи параметра +NAME+, после чего сохраните их в файл с
|
||||
более высоким приоритетом, чем правила по умолчанию, например,
|
||||
+/etc/udev/rules.d/70-my-net-names.rules+. (Приоритет файлов
|
||||
определяется на основании алфавитной сортировки их имен.)
|
||||
\item Вы можете скорректировать правила, используемые по умолчанию,
|
||||
например, задействовав схему именования интерфейсов по
|
||||
MAC-адресам. Для, этого скопируйте файл правил в каталог +/etc+
|
||||
\begin{Verbatim}
|
||||
cp /usr/lib/udev/rules.d/80-net-name-slot.rules /etc/udev/rules.d/80-net-name-slot.rules
|
||||
\end{Verbatim}
|
||||
после чего измените его так, как считаете нужным.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Как именно работает новая схема?}
|
||||
|
||||
Подробности технической реализации описаны в блоке комментариев в
|
||||
\href{http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n20}%
|
||||
{исходном коде net-id built-in}. Ознакомьтесь с ним, если у вас возникают
|
||||
вопросы, касающиеся расшифровки новых имен\footnote{Прим. перев.: Далее
|
||||
приводится перевод упомянутого блока комментариев. Последним коммитом,
|
||||
затронувшим данный файл, на момент перевода является b92be от 24 марта
|
||||
2013 г.}.
|
||||
|
||||
\begin{Verbatim}
|
||||
Предсказуемые имена сетевых интерфейсов формируются на основании:
|
||||
- индексов встроенных в материнскую плату устройств (по информации EFI/BIOS)
|
||||
- индексов hotplug-слотов PCI-E (по информации EFI/BIOS)
|
||||
- физического расположения точки подключения оборудования
|
||||
- MAC-адресов
|
||||
|
||||
Первые два символа в имени определяют тип интерфейса:
|
||||
en -- ethernet
|
||||
wl -- wlan
|
||||
ww -- wwan
|
||||
|
||||
Последующие символы определяеются используемой схемой:
|
||||
o<index> -- для устройств, встроенных в материнскую плату
|
||||
s<slot>[f<function>][d<dev_id>] -- для hotplug-слотов
|
||||
x<MAC> -- при именовании по MAC-адресу
|
||||
p<bus>s<slot>[f<function>][d<dev_id>] -- на основании физического
|
||||
расположения PCI-устройства
|
||||
p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
|
||||
-- идентификационная цепочка для USB-устройств
|
||||
|
||||
Все многофункциональные (multi-function) PCI-устройства содержат в своем имени
|
||||
номер функции [f<function>] (отсчитываются от нуля).
|
||||
|
||||
Для USB-устройства формируется полная цепочка номеров портов хабов, через
|
||||
которые оно подключено. Если итоговая строка будет длиннее 15 символов, она
|
||||
не экспортируется.
|
||||
Стандартные значения config == 1 и interface == 0 опускаются.
|
||||
|
||||
Примеры:
|
||||
|
||||
Подключенная к PCI сетевая карта, которая идентифцироуется прошивкой
|
||||
по индексу "1":
|
||||
ID_NET_NAME_ONBOARD=eno1
|
||||
ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
|
||||
|
||||
Сетевая карта, включенная в hotplug PCI-слот, который идентифицируется
|
||||
прошивкой:
|
||||
/sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
|
||||
ID_NET_NAME_MAC=enx000000000466
|
||||
ID_NET_NAME_PATH=enp5s0
|
||||
ID_NET_NAME_SLOT=ens1
|
||||
|
||||
Multi-function PCI устройство с двумя портами:
|
||||
/sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
|
||||
ID_NET_NAME_MAC=enx78e7d1ea46da
|
||||
ID_NET_NAME_PATH=enp2s0f0
|
||||
/sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
|
||||
ID_NET_NAME_MAC=enx78e7d1ea46dc
|
||||
ID_NET_NAME_PATH=enp2s0f1
|
||||
|
||||
Подключенная к PCI wlan-карта:
|
||||
/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
|
||||
ID_NET_NAME_MAC=wlx0024d7e31130
|
||||
ID_NET_NAME_PATH=wlp3s0
|
||||
|
||||
Встроенный USB 3G модем:
|
||||
/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
|
||||
ID_NET_NAME_MAC=wwx028037ec0200
|
||||
ID_NET_NAME_PATH=wwp0s29u1u4i6
|
||||
|
||||
Подключенный по USB Android-смартфон:
|
||||
/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
|
||||
ID_NET_NAME_MAC=enxd626b3450fb5
|
||||
ID_NET_NAME_PATH=enp0s29u1u2
|
||||
\end{Verbatim}
|
||||
|
||||
\section{Специальные файловые системы\sfnote{Перевод статьи
|
||||
<<\href{http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems}{API
|
||||
File Systems}>> с официального сайта проекта, по состоянию на 2013-01-17
|
||||
11:06:59 (ревизия \No14).}}
|
||||
|
||||
\emph{Итак, вы запустили программу mount(8), и увидели в ее выводе множество
|
||||
странных файловых систем, не~указанных в /etc/fstab. У вас могут возникнуть
|
||||
вопросы: <<Как их убрать?>> или <<Как задать для них параметры монтирования?>>.}
|
||||
|
||||
В Linux предусмотрено несколько способов взаимодействия программ из пространства
|
||||
пользователя с ядром. Наиболее популярными механизмами являются системные вызовы
|
||||
(syscall), интерфейсы Netlink, а также виртуальные файловые системы (ФС), такие,
|
||||
как +/proc+ и +/sys+. Подобные ФС являются лишь программными интерфейсами, и
|
||||
не~предоставляют возможности для долговременного хранения данных (в частности,
|
||||
между перезагрузками системы). Они просто используют классические механизмы
|
||||
работы с файлами для предоставления доступа к различным данным и настройкам.
|
||||
Кроме того, существуют специальные ФС, используемые программами для собственных
|
||||
нужд, в частности, для хранения сегментов разделяемой памяти (shared memory),
|
||||
временных файлов и сокетов. В данной статье мы обсудим все эти разновидности
|
||||
\emph{специальных файловых систем}. Ниже представлен список таких ФС,
|
||||
поддерживаемых в типовых Linux-системах:
|
||||
\begin{itemize}
|
||||
\item +/sys+ предоставляет доступ к драйверам и устройствам, а также
|
||||
некоторым другим параметрам ядра
|
||||
\item +/proc+ дает доступ к информации о выполняемых процессах,
|
||||
настройкам ядра, а также другим параметрам
|
||||
\item +/dev+ отображает файлы устройств (device nodes)
|
||||
\item +/run+ содержит файлы и сокеты, используемые программами
|
||||
\item +/tmp+ хранит временные и часто изменяемые объекты (X)
|
||||
\item +/sys/fs/cgroup+ (и другие файловые системы, смонтированные в
|
||||
подкаталогах этого каталога) позволяют работать с иерархией
|
||||
контрольных групп
|
||||
\item +/sys/kernel/security+, +/sys/kernel/debug+ (X),
|
||||
+/sys/kernel/config+ (X) предоставляют доступ к
|
||||
специализированным механизмам ядра
|
||||
\item +/sys/fs/selinux+ используется для взаимодействия с SELinux
|
||||
\item +/dev/shm+ содержит объекты разделяемой памяти
|
||||
\item +/dev/pts+ обеспечивает доступ к псевдо-TTY устройствам
|
||||
\item +/proc/sys/fs/binfmt_misc+ используется для регистрации в ядре
|
||||
дополнительных бинарных форматов (X)
|
||||
\item +/dev/mqueue+ содержит объекты IPC-механизма mqueue (X)
|
||||
\item +/dev/hugepages+ позволяет программам запрашивать выделение
|
||||
<<гигантских>> страниц памяти (X)
|
||||
\item +/sys/fs/fuse/connections+ обеспечивает доступ к
|
||||
FUSE-соединениям (X)
|
||||
\item +/sys/firmware/efi/efivars+ предоставляет доступ к переменным EFI
|
||||
\end{itemize}
|
||||
|
||||
systemd монтирует все эти файловые системы на ранних стадиях загрузки, даже если
|
||||
они не~указаны явно в +/etc/fstab+. В зависимости от настроек вашего ядра,
|
||||
некоторые из перечисленных выше ФС могут быть недоступны, и наоборот, могут
|
||||
присутствовать другие специальные ФС, не~приведенные в этом списке. Все эти
|
||||
механизмы играют важную роль во взаимодействии ядра с программами и программ
|
||||
между собой. Именно поэтому они подключаются автоматически, безо всякого участия
|
||||
пользователя. Необдуманное вмешательство в их работу (отключение или изменение
|
||||
параметров) может нарушить нормальную работу ваших программ, так как они утратят
|
||||
доступ к необходимым для них интерфейсам.
|
||||
|
||||
В абсолютном большинстве случаев достаточно настроек, используемых по умолчанию.
|
||||
Однако, могут возникнуть ситуации, когда необходимо изменить параметры
|
||||
монтирования специальных ФС, либо полностью отключить монтирование некоторых из
|
||||
них.
|
||||
|
||||
Несмотря на то, что эти ФС по умолчанию отсутствуют в +/etc/fstab+, ничто
|
||||
не~мешает вам их туда добавить. Параметры монтирования, которые вы при этом
|
||||
укажете, будут автоматически применяться к соответствующим ФС. Проще говоря:
|
||||
если вам нужно изменить параметры монтирования для специальных ФС, просто
|
||||
добавьте их в +/etc/fstab+ с указанием соответствующих опций. Кроме параметров
|
||||
монтирования, так можно изменить и сам тип файловой системы. В частности, этот
|
||||
способ позволяет переключить +/tmp+ с +tmpfs+ на физический дисковый раздел.
|
||||
|
||||
Также вы можете полностью отключить монтирование некоторых (но не~всех)
|
||||
специальных систем, если это действительно необходимо. Отключаемые ФС в списке
|
||||
выше отмечены (X). Для их отключения, достаточно замаскировать соответствующий
|
||||
юнит:
|
||||
\begin{Verbatim}
|
||||
systemctl mask dev-hugepages.mount
|
||||
\end{Verbatim}
|
||||
|
||||
В результате выполнения такой операции, соответствующая ФС больше не~будет
|
||||
монтироваться по умолчанию, начиная со следующей загрузки системы. О том, что
|
||||
такое маскировка юнита, вы можете прочитать в~главе~\ref{sec:off}.
|
||||
|
||||
На всякий случай отметим, что применение к специальным ФС параметров монтирования,
|
||||
указанных в +/etc/fstab+, обеспечивается службой
|
||||
\hreftt{http://www.freedesktop.org/software/systemd/man/systemd-remount-fs.service.html}%
|
||||
{systemd-remount-fs.service}.
|
||||
|
||||
\subsection*{Зачем вы мне все это рассказываете? Я просто хочу убрать tmpfs из
|
||||
/tmp!}
|
||||
|
||||
У вас есть три варианта:
|
||||
\begin{enumerate}
|
||||
\item Вы можете отключить любое монтирование в +/tmp+, в результате чего
|
||||
содержимое данного каталога будет храниться на том же разделе, что
|
||||
и корень. Для этого достаточно выполнить команду
|
||||
\begin{Verbatim}
|
||||
systemctl mask tmp.mount
|
||||
\end{Verbatim}
|
||||
\item Вы можете смонтировать в +/tmp+ обычную файловую систему,
|
||||
размещенную на диске. Для этого достаточно создать
|
||||
соответствующую запись в +/etc/fstab+.
|
||||
\item Если вы хотите оставить в +/tmp+ +tmpfs+, но при этом задать для
|
||||
нее другой размер~--- это тоже делается через внесение в
|
||||
+/etc/fstab+ соответствующей записи, предписывающей монтирование
|
||||
+tmpfs+ в +/tmp+ с нужным вам значением параметра +size=+.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Запуск служб после появления сети\sfnote{Перевод статьи
|
||||
<<\href{http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget}{Running
|
||||
Services After the Network is up}>> с официального сайта проекта, по состоянию
|
||||
на 2013-01-17 23:22:58 (ревизия \No17).}}
|
||||
|
||||
\emph{Итак, ваша служба настроена на запуск только после достижения цели
|
||||
network.target, однако, несмотря на это, она все равно запускается до появления
|
||||
сети. У вас возникают вопросы: <<Почему так происходит?>> и <<Как это
|
||||
исправить?>>.}
|
||||
|
||||
Цель +network.target+ является systemd-шным аналогом LSB-сущности (facility)
|
||||
\verb+$network+. Определение этой сущности в стандарте
|
||||
\href{http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/facilname.html}%
|
||||
{довольно расплывчато} и оставляет широкий простор для трактовок. Вот примеры
|
||||
некоторых из них:
|
||||
\begin{itemize}
|
||||
\item Все заданные в настройках сетевые интерфейсы переведены в состояние
|
||||
UP и получили IP-адреса.
|
||||
\item Все имеющиеся физические сетевые интерфейсы, на которых
|
||||
зарегистрирована несущая (link beat), получили IP-адреса.
|
||||
Наличие или отсутствие явных настроек роли не~играет.
|
||||
\item Доступен DNS-сервер.
|
||||
\item Доступен некоторый выбранный сервер.
|
||||
\item Доступен некий абстрактный <<интернет>>.
|
||||
\item Все заданные в настройках ethernet-интерфейсы переведены в
|
||||
состояние UP, однако процесс настройки PPP-интерфейсов еще
|
||||
не~начался.
|
||||
\item Активирован некий профиль сетевых настроек, задающий одно из
|
||||
условий выше. В разных профилях могут использоваться разные
|
||||
условия.
|
||||
\item Выполняется некоторое условие (выбор условия определяется
|
||||
физическим расположением системы).
|
||||
\item Настроен как минимум один глобальный адрес IPv4.
|
||||
\item Настроен как минимум один глобальный адрес IPv6.
|
||||
\item Настроен как минимум один глобальный адрес IPv4 или IPv6.
|
||||
\end{itemize}
|
||||
|
||||
Этот список можно продолжать и дальше. Каждый предложенный в нем вариант можно
|
||||
использовать в качестве критерия появления сети, однако ни~один из них
|
||||
не~подходит в качестве варианта по умолчанию, пригодного для абсолютного
|
||||
большинства задач.
|
||||
|
||||
Современные компьютерные сети живут в очень динамичном ритме: компьютеры
|
||||
перемещаются между сетями, сетевые настройки меняются, устройства подключаются и
|
||||
отключаются, виртуальные сети настраиваются, перенастраиваются и выключаются.
|
||||
Наличие сетевого соединения не~является чем-то постоянным и безусловным. В
|
||||
разные моменты времени компьютер может быть подключен к разным сетям. И это
|
||||
справедливо не~только для мобильных устройств (смартфонов, планшетов и
|
||||
ноутбуков), но и, в определенной мере, для встраиваемых и серверных систем.
|
||||
Программы, которые считают, что сеть является чем-то неизменным и непрерывно
|
||||
доступным, не~могут нормально функционировать в таких условиях. Хорошо
|
||||
написанная программа должна корректно реагировать на изменение состояния сети, и
|
||||
не~унывать в беде. Если нужный ей сервер не~доступен в настоящий момент, она
|
||||
должна не~зависать по тайм-ауту, а пытаться достучаться к нему снова и снова.
|
||||
Если сетевое соединение утрачено, она должна отреагировать на это. Реализовать
|
||||
такое реагирование в коде демона, на самом деле, не~так уж и сложно. Существует
|
||||
множество хорошо известных сетевых служб, которые уже давно поддерживают такую
|
||||
возможность. Подобные службы можно запускать в любой момент, они устойчивы к
|
||||
сбоям, и в любой ситуации работают корректно.
|
||||
|
||||
+network.target+ предназначена для поддержки программ, созданных в
|
||||
предположении, что сеть доступна постоянно (т.е. написанных не~очень аккуратно).
|
||||
Конкретные требования таких программ могут сильно отличаться. Например,
|
||||
IMAP-серверу будет достаточно наличия IP-адреса, на котором можно слушать. В то
|
||||
время как для клиентов сетевых файловых систем требуется требуется доступность и
|
||||
работоспособность сервера, а также, опционально, наличие работоспособного DNS.
|
||||
Таким образом, конкретные требования к +network.target+ сильно зависят от
|
||||
решаемой задачи.
|
||||
|
||||
По соображениям надежности, загрузка системы не~должна зависеть от второстепенных
|
||||
служб. В частности, отсутствие ответа от DHCP-сервера не~должно завешивать
|
||||
процесс загрузки системы (за исключением ситуаций, когда сетевое соединение
|
||||
действительно необходимо для работы системы, например, при загрузке по сети).
|
||||
|
||||
По умолчанию, +network.target+ не~несет какой-либо сакральной смысловой
|
||||
нагрузки. Сама по себе настройка службы на запуск после достижения этой цели
|
||||
не~дает видимого эффекта. Наполнить +network.target+ смыслом должен сам
|
||||
администратор, в зависимости от задачи которую он решает, и от конкретных
|
||||
потребностей тех программ, с которыми ему приходится работать (а эти
|
||||
потребности, в свою очередь, могут зависеть от их настроек). По умолчанию, мы
|
||||
оставили +network.target+ <<пустышкой>>, что позволяет обеспечить максимальную
|
||||
скорость загрузки, и предоставили администратору возможность самостоятельно
|
||||
определить список проверок, который он считает наиболее целесообразным для
|
||||
данной системы.
|
||||
|
||||
\subsection*{Короче, как заставить network.target работать?}
|
||||
|
||||
Конкретный рецепт зависит от решаемой вами задачи и потребностей ваших служб
|
||||
(см. выше). Если вы используете NetworkManager, вы можете задействовать
|
||||
специальную службу +NetworkManager-wait-online.service+:
|
||||
\begin{Verbatim}
|
||||
systemctl enable NetworkManager-wait-online.service
|
||||
\end{Verbatim}
|
||||
|
||||
Включение этой службы позволит гарантировать, что загрузка продолжится только
|
||||
после того, как все заданные в настройках NM сетевые интерфейсы будут переведены
|
||||
в состояние UP и получат IP-адреса. Максимальное время ожидания~--- 90
|
||||
секунд\footnote{Прим. перев.: В апстримной конфигурации по умолчанию сейчас
|
||||
используется значение 30 секунд. См. параметр +--timeout+ программы +nm-online+
|
||||
в файле настроек службы
|
||||
+/usr/lib/systemd/system/NetworkManager-wait-online.service+.}.
|
||||
Обратите внимание, что включение данной службы может сильно замедлить загрузку.
|
||||
|
||||
Если же такое вариант вас не~устраивает, вы можете подготовить собственный
|
||||
service-файл, запускающий любую заданную вами программу или скрипт. Не~забудьте
|
||||
указать, что он должен быть запущен до достижения цели +network.target+ (при
|
||||
помощи параметра +Before=+). Кроме того, стоит указать зависимость от
|
||||
+network.target+ при помощи директивы +Wants=+\footnote{Прим. перев.: Также
|
||||
не~стоит забывать, что ваша служба сама должна быть кем-то активирована. Это
|
||||
определяется параметром +WantedBy=+ или +RequiredBy=+ секции +[Install]+. Проще
|
||||
всего указать здесь ту же самую +network.target+: в результате, ваша служба и
|
||||
+network.target+ будут взаимно зависеть друг от друга, но при этом
|
||||
+network.target+ будет активирована только после того, как отработает ваша
|
||||
служба. Разница между +WantedBy=+ и +RequiredBy=+ состоит в том, что при
|
||||
использовании Require требуется \emph{успешное} завершение запуска вашей службы.
|
||||
Если он завершится с ненулевым кодом выхода или по сигналу, +network.target+
|
||||
не~будет активирована. В то время как для Want достаточно просто завершения
|
||||
запуска, вне зависимости от успешности. В качестве основы вы можете взять
|
||||
\href{http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/data/NetworkManager-wait-online.service.in}%
|
||||
{апстримный файл} +NetworkManager-wait-online.service+. В завершение,
|
||||
не~забудьте выполнить для своей службы +systemctl enable+.}.
|
||||
|
||||
\subsection*{А что делать нам, разработчикам?}
|
||||
|
||||
Если вы~--- не~администратор, а разработчик сетевой службы, то вам стоит
|
||||
задуматься не~о том, что делать с +network.target+, а о том, как можно исправить
|
||||
вашу службу, чтобы она нормально реагировала на изменение состояния сети. Это
|
||||
позволит порадовать ваших пользователей (когда программа работает без
|
||||
дополнительной возни~--- это не~может не~радовать), а также уменьшит количество
|
||||
сообщений об ошибках (так как ваша программа уже не~будет паниковать по
|
||||
пустякам). Кроме того, системы ваших пользователей будут грузиться быстрее,
|
||||
потому что их уже не~будет задерживать необходимость ожидать появления сети (в
|
||||
случае с медленным DHCP-сервером, прогресс может быть весьма ощутимым).
|
||||
|
||||
Можно предложить несколько подходов к решению этой задачи:
|
||||
\begin{itemize}
|
||||
\item Отслеживайте изменений конфигурации сети при помощи
|
||||
\href{https://www.kernel.org/doc/man-pages/online/pages/man7/rtnetlink.7.html}%
|
||||
{rtnetlink} и реагируйте соответствующим образом. Это наиболее
|
||||
правильный, но далеко не~всегда простой способ.
|
||||
\item Если вы разрабатываете серверное приложение: слушайте только
|
||||
адреса 0.0.0.0 и 127.0.0.1. Оба этих псевдо-адреса должны быть
|
||||
доступны постоянно. Если ваша программа будет слушать только их,
|
||||
ей будут глубоко безразличны изменения конфигурации сети.
|
||||
\item Если вы разрабатываете серверное приложение и вам нужно слушать
|
||||
некий заданный адрес: воспользуйтесь опцией
|
||||
\href{https://www.kernel.org/doc/man-pages/online/pages/man7/ip.7.html}%
|
||||
{IP\_FREEBIND}, доступной на Linux-системах. Она позволит вашей
|
||||
программе слушать даже те адреса, которые не~присвоены локальным
|
||||
сетевым интерфейсам (в данный момент или вообще), что также
|
||||
сделает ваш код устойчивым к изменению сетевой конфигурации.
|
||||
\end{itemize}
|
||||
|
||||
\section{Моя служба не~может получить приоритет realtime\sfnote{Перевод статьи
|
||||
<<\href{http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime}%
|
||||
{My Service Can't Get Realtime!}>> с официального сайта проекта, по состоянию на
|
||||
2013-01-15 16:54:09 (ревизия \No1).}}
|
||||
|
||||
\emph{Итак, у вас есть служба, которая требует приоритет реального времени
|
||||
(realtime). Однако, когда вы пытаетесь запустить ее на системе, работающей под
|
||||
управлением systemd, ваша служба не~может получить этот приоритет, хотя обладает
|
||||
всеми необходимыми для этого привилегиями. Вы хотите понять, почему это
|
||||
происходит, и как это можно исправить.}
|
||||
|
||||
\subsection*{В чем же дело?}
|
||||
|
||||
По умолчанию, systemd помещает каждую системную службу в свою контрольную группу
|
||||
в иерархии контроллера +cpu+. Такое поведение дает очень полезный эффект: службы
|
||||
с множеством рабочих потоков (например, Apache с сотнями CGI-процессов),
|
||||
получают примерно такую же долю процессорного времени, как и службы с небольшим
|
||||
количеством рабочих потоков (например, MySQL). Проще говоря, процессорное время
|
||||
распределяется уже не~\emph{между процессами}, а \emph{между службами}.
|
||||
|
||||
К сожалению, в настоящее время реализация cpu-контроллера в Linux имеет один
|
||||
существенный недостаток: она требует явного задания realtime-бюджета времени (RT
|
||||
budget) для своих контрольных групп. Если же бюджет группы не~задан, то ее
|
||||
процессы не~смогут получить приоритет реального времени (соответствующая
|
||||
операция будет завершаться с ошибкой +EPERM+~--- <<недостаточные полномочия>>).
|
||||
systemd не~может присваивать такой бюджет \emph{каждой} группе, просто потому,
|
||||
что не~знает, как его правильно делить между ними. Бюджет выдается в абсолютных
|
||||
единицах времени, и их общее количество ограничено. Мы не~можем предложить
|
||||
механизм распределения бюджета, который бы подходил по умолчанию для большинства
|
||||
случаев. Поэтому, в конфигурации по умолчанию, приоритет реального времени
|
||||
недоступен для системных служб.
|
||||
|
||||
\subsection*{Как это исправить?}
|
||||
|
||||
Обойти это ограничение несложно. Существует несколько различных путей:
|
||||
\begin{itemize}
|
||||
\item Можно просто отключить использование cpu-контроллера по умолчанию
|
||||
для системных служб. Для этого, задайте в файле
|
||||
+/etc/systemd/system.conf+ параметр +DefaultControllers=+ равным
|
||||
пустой строке, после чего перезагрузите систему. (Также вы
|
||||
можете отключить контроллер +cpu+ на этапе сборки ядра. systemd
|
||||
не~пытается использовать контроллеры, которые не~поддерживаются
|
||||
ядром.)
|
||||
\item Также вы можете отключить группировку по +cpu+ только для
|
||||
конкретных служб. Для этого отредактируйте конфигурацию службы,
|
||||
добавив параметр +ControlGroup=cpu:/+ в секцию +[Service]+. В
|
||||
результате, процессы данной службы будут помещены не~в
|
||||
собственную контрольную группу (как это делалось по умолчанию),
|
||||
а в корневую контрольную группу иерархии +cpu+. Процессы из
|
||||
корневой группы располагают полным realtime-бюджетом.
|
||||
\item И наконец, вы можете явно выделить своей службе некоторый бюджет.
|
||||
Для этого добавьте в секцию +[Service]+ строку наподобие
|
||||
+ControlGroupAttribute=cpu.rt_runtime_us 500000+. Подробнее о
|
||||
правильном распределении бюджета читайте в
|
||||
\href{http://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt}%
|
||||
{документации к ядру}.
|
||||
\end{itemize}
|
||||
|
||||
Последние две опции недоступны для SysV-служб. Тем не~менее, вы можете
|
||||
подготовить для них соответствующие service-файлы, которые, помимо упомянутых
|
||||
выше параметров, содержат вызов соответствующего init-скрипта с аргументом
|
||||
+start+ в +ExecStart=+, и с аргументом +stop+~--- в +ExecStop=+.
|
||||
(Также имеет смысл задать для них параметры +RemainAfterExit=1+ и
|
||||
+Type=forking+.)
|
||||
|
||||
Отметим, что все вышесказанное касается только системных служб, и не~затрагивает
|
||||
пользовательские сеансы. По умолчанию, программы пользователя размещаются в
|
||||
корневой группе контроллера +cpu+, и поэтому вышеописанные ограничения их
|
||||
не~касаются.
|
||||
|
||||
Мы надеемся, что в будущем ядро будет исправлено таким образом, чтобы
|
||||
не~требовать явного задания realtime-бюджета для получения приоритета реального
|
||||
времени (а при получении такого приоритета, бюджет процесса должен автоматически
|
||||
выделяться из бюджета ближайшей родительской группы). В идеале, мы хотели бы
|
||||
распространить практику выделения cpu-групп не~только на системные службы, но и
|
||||
на пользовательские сеансы, чтобы уравнять пользователей в правах на
|
||||
процессорное время, вне зависимости от того, сколько процессов запускает каждый
|
||||
конкретный пользователь.
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user