Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4015fe4fa7 | ||
|
|
1c4dab825e | ||
|
|
5ebef8d95a | ||
|
|
56e266c439 | ||
|
|
d7012437df | ||
|
|
c24887c795 | ||
|
|
15e9a095a1 | ||
|
|
01f2aafc02 | ||
|
|
71b6656ebb |
875
s4a.tex
875
s4a.tex
@@ -13,8 +13,9 @@
|
||||
% Заполняем поля PDF уже со включенной опцией unicode
|
||||
\hypersetup{pdftitle={systemd для администраторов},%
|
||||
pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||||
% Небольшое сокращение
|
||||
% Несколько сокращений
|
||||
\newcommand{\sectiona}[1]{\section*{#1}\addcontentsline{toc}{section}{#1}}
|
||||
\newcommand{\hreftt}[2]{\href{#1}{\texttt{#2}}}
|
||||
% Настройка макета страницы
|
||||
\setlength{\hoffset}{-1.5cm}
|
||||
\addtolength{\textwidth}{2cm}
|
||||
@@ -391,8 +392,8 @@ $ ps xawf -eo pid,user,cgroup,args
|
||||
|
||||
Обратите внимание на третий столбец, показывающий имя контрольной группы,
|
||||
которое systemd присваивает каждому процессу. Например, процесс +udev+
|
||||
находится в группе +name=systemd:/systemd-1/sysinit.service+. В этой группе
|
||||
находятся процессы, порожденные службой +sysinit.service+, которая запускается
|
||||
находится в группе +name=systemd:/systemd-1/sysinit.service+. В эту группу
|
||||
входят процессы, порожденные службой +sysinit.service+, которая запускается
|
||||
на ранней стадии загрузки.
|
||||
|
||||
Вы можете очень сильно упростить себе работу, если назначите для
|
||||
@@ -836,7 +837,7 @@ systemd запустит процесс abrtd, который уже не~буд
|
||||
падения. Или, например, добавив +OOMScoreAdjust=-500+, мы попросим ядро сберечь
|
||||
эту службу, даже если OOM Killer выйдет на тропу войны. А если мы добавим
|
||||
строчку +CPUSchedulingPolicy=idle+, процесс abrtd будет работать только в те
|
||||
моменты, когда система больше ничем не~занята, что позволит не создавать помех
|
||||
моменты, когда система больше ничем не~занята, что позволит не~создавать помех
|
||||
для процессов, активно использующих CPU.
|
||||
|
||||
За более подробным описанием всех опций настройки, вы можете обратиться к
|
||||
@@ -859,7 +860,7 @@ service-файлы. Но, к счастью, <<проблемных>> скрип
|
||||
Впрочем, этот метод не~вполне корректен, так как он действует не~только на
|
||||
самого демона, но и на другие процессы с тем же именем. Иногда подобное
|
||||
поведение может привести к неприятным последствиям. Более правильным будет
|
||||
использование pid-файла: +kill $(cat /var/run/syslogd.pid)+. Вот, вроде
|
||||
использование pid-файла: +kill $(cat /var/run/syslogd.pid)$+. Вот, вроде
|
||||
бы, и все, что вам нужно\ldots{} Или мы упускаем еще что-то?
|
||||
|
||||
Действительно, мы забываем одну простую вещь: существуют службы, такие, как
|
||||
@@ -946,4 +947,868 @@ systemd и на этот случай есть простое решение, и
|
||||
инструментов, позволяющих корректно отправить сигнал службе в целом, а
|
||||
не~отдельному процессу.
|
||||
|
||||
\section{Три уровня выключения}
|
||||
|
||||
В \href{http://www.freedesktop.org/wiki/Software/systemd}{systemd} существует
|
||||
три уровня (разновидности) действий, направленных на прекращение работы службы
|
||||
(или любого другого юнита):
|
||||
|
||||
\begin{itemize}
|
||||
\fvset{gobble=3}
|
||||
\item Вы можете \emph{остановить} службу, то есть прекратить
|
||||
выполнение уже запущенных процессов службы. При этом
|
||||
сохраняется возможность ее последующего запуска, как ручного
|
||||
(через команду +systemctl start+), так и автоматического (при
|
||||
загрузке системы, при поступлении запроса через сокет или
|
||||
системную шину, при срабатывании таймера, при подключении
|
||||
соответствующего оборудования и т.д.). Таким образом,
|
||||
остановка службы является временной мерой, не~дающей никаких
|
||||
гарантий на будущее.
|
||||
|
||||
В качестве примера рассмотрим остановку службы NTPd
|
||||
(отвечающей за синхронизацию времени по сети):
|
||||
\begin{Verbatim}
|
||||
systemctl stop ntpd.service
|
||||
\end{Verbatim}
|
||||
|
||||
Аналогом этой команды в классическом SysV init является
|
||||
\begin{Verbatim}
|
||||
service ntpd stop
|
||||
\end{Verbatim}
|
||||
|
||||
Заметим, что в Fedora~15, использующей в качестве системы
|
||||
инициализации systemd, в целях обеспечения обратной
|
||||
совместимости допускается использование классических
|
||||
SysV-команд, и systemd будет корректно воспринимать их.
|
||||
В~частности, вторая приведенная здесь команда будет эквивалентна
|
||||
первой.
|
||||
|
||||
\item Вы можете \emph{отключить} службу, то есть отсоединить ее от всех
|
||||
триггеров активации. В результате служба уже не~будет
|
||||
автоматически запускаться ни~при загрузке системы, ни~при
|
||||
обращении к сокету или адресу на шине, ни~при подключении
|
||||
оборудования, и т.д. Но при этом сохраняется возможность
|
||||
<<ручного>> запуска службы (командой +systemctl start+).
|
||||
Обратите внимание, что при отключении уже запущенной службы, ее
|
||||
выполнение в текущем сеансе не~останавливается~--- это нужно
|
||||
сделать отдельно, иначе процессы службы будут работать до
|
||||
момента выключения системы (но при следующем включении,
|
||||
разумеется, уже не~запустятся).
|
||||
|
||||
Рассмотрим отключение службы на примере все того же NTPd:
|
||||
\begin{Verbatim}
|
||||
systemctl disable ntpd.service
|
||||
\end{Verbatim}
|
||||
|
||||
В классических SysV-системах аналогичная команда будет иметь
|
||||
вид
|
||||
\begin{Verbatim}
|
||||
chkconfig ntpd off
|
||||
\end{Verbatim}
|
||||
|
||||
Как и в предыдущем случае, в Fedora~15 вторая из этих команд
|
||||
будет действовать аналогично первой.
|
||||
|
||||
Довольно часто приходится сочетать действия отключения и
|
||||
остановки службы~--- такая комбинированная операция
|
||||
гарантирует, что уже исполняющиеся процессы службы будут
|
||||
прекращены, и служба больше не~будет запускаться автоматически
|
||||
(но может быть запущена вручную):
|
||||
\begin{Verbatim}
|
||||
systemctl disable ntpd.service
|
||||
systemctl stop ntpd.service
|
||||
\end{Verbatim}
|
||||
Подобное сочетание команд используется,
|
||||
например, при деинсталляции пакетов в Fedora.
|
||||
|
||||
Обратите внимание, что отключение службы является перманентной
|
||||
мерой, и действует вплоть до явной отмены соответствующей
|
||||
командой. Перезагрузка системы не~отменяет отключения службы.
|
||||
|
||||
\item Вы можете \emph{заблокировать} (замаскировать) службу. Действие
|
||||
этой операции аналогично отключению, но дает более сильный
|
||||
эффект. Если при отключении отменяется только возможность
|
||||
автоматического запуска службы, но сохраняется возможность
|
||||
ручного запуска, то при блокировке исключаются обе эти
|
||||
возможности. Отметим, что использование данной опции при
|
||||
непонимании принципов ее работы может привести к трудно
|
||||
диагностируемым ошибкам.
|
||||
|
||||
Тем не~менее, рассмотрим пример блокировки все той же службы NTPd:
|
||||
\begin{Verbatim}
|
||||
ln -s /dev/null /etc/systemd/system/ntpd.service
|
||||
systemctl daemon-reload
|
||||
\end{Verbatim}
|
||||
|
||||
Итак, блокировка сводится к созданию символьной ссылки
|
||||
с именем соответствующей службы, указывающей на +/dev/null+.
|
||||
После такой операции служба не~может быть запущена ни~вручную,
|
||||
ни~автоматически. Символьная ссылка создается в каталоге
|
||||
+/etc/systemd/system/+, а ее имя должно соответствовать имени
|
||||
файла описания службы из каталога +/lib/systemd/system/+ (в
|
||||
нашем случае +ntpd.service+).
|
||||
|
||||
Заметим, что systemd читает файлы конфигурации из обоих этих
|
||||
каталогов, но файлы из +/etc+ (управляемые системным
|
||||
администратором) имеют приоритет над файлами из +/lib+ (которые
|
||||
управляются пакетным менеджером). Таким образом, создание
|
||||
символьной ссылки (или обычного файла)
|
||||
+/etc/systemd/system/ntpd.service+ предотвращает чтение
|
||||
штатного файла конфигурации +/lib/systemd/system/ntpd.service+.
|
||||
|
||||
В выводе +systemctl status+ заблокированные службы отмечаются
|
||||
словом +masked+. Попытка запустить такие службы командой
|
||||
+systemctl start+ завершится ошибкой.
|
||||
|
||||
В рамках классического SysV init, штатная реализация такой
|
||||
возможности отсутствует. Похожий эффект может быть
|
||||
достигнут с помощью <<костылей>>, например, путем добавления
|
||||
команды +exit 0+ в начало init-скрипта. Однако, подобные решения
|
||||
имеют ряд недостатков, например, потенциальная возможность
|
||||
конфликтов с пакетным менеджером (при очередном обновлении
|
||||
исправленный скрипт может быть просто затерт соответствующим
|
||||
файлом из пакета).
|
||||
|
||||
Стоит отметить, что блокировка службы, как и ее отключение,
|
||||
является перманентной мерой\footnote{Прим. перев.: подробно
|
||||
описав принцип работы блокировки службы (юнита), автор забывает
|
||||
привести практические примеры ситуаций, когда эта возможность
|
||||
оказывается полезной.
|
||||
|
||||
В частности, иногда бывает необходимо
|
||||
полностью предотвратить запуск службы в любой ситуации. При этом
|
||||
не~стоит забывать, что в post-install скриптах пакетного
|
||||
менеджера или, скажем, в~заданиях cron, вместо
|
||||
+systemctl try-restart+ (+service condrestart+) может быть
|
||||
ошибочно указано +systemctl restart+ (+service restart+), что
|
||||
является прямым указанием на запуск службы, если она еще
|
||||
не~запущена. Вследствие таких ошибок, отключенная служба может
|
||||
<<ожить>> в самый неподходящий момент.
|
||||
|
||||
Другой пример~---
|
||||
ограничение возможностей непривилегированного пользователя при
|
||||
управлении системой. Даже если такому пользователю делегировано
|
||||
(через механизмы sudo или PolicyKit) право на использование
|
||||
+systemctl+, это еще не~означает, что он сможет запустить
|
||||
заблокированную службу~--- права на выполнение +rm+ (удаление
|
||||
блокирующей символьной ссылки) выдаются отдельно.}.
|
||||
\end{itemize}
|
||||
|
||||
После прочтения изложенного выше, у читателя может возникнуть вопрос: как
|
||||
отменить произведенные изменения? Что ж, ничего сложного тут нет:
|
||||
+systemctl start+ отменяет действия +systemctl stop+, +systemctl enable+
|
||||
отменяет действие +systemctl disable+, а +rm+ отменяет действие +ln+.
|
||||
|
||||
\section{Смена корня}
|
||||
|
||||
Практически все администраторы и разработчики рано или поздно встречаются с
|
||||
\href{http://linux.die.net/man/1/chroot}{chroot-окружениями}. Системный вызов
|
||||
+chroot()+ позволяет задать для определенного процесса (и его потомков) каталог,
|
||||
который они будут рассматривать как корневой +/+, тем самым ограничивая для них
|
||||
область видимости иерархии файловой системы отдельным поддеревом. Большинство
|
||||
применений chroot-окружений можно отнести к двум классам задач:
|
||||
\begin{enumerate}
|
||||
\item Обеспечение безопасности. Потенциально уязвимый демон chroot'ится
|
||||
в отдельный каталог, и даже в случае успешной атаки, взломщик
|
||||
увидит лишь содержимое этого каталога, а не~всю файловую
|
||||
систему~--- он окажется в ловушке chroot'а.
|
||||
\item Подготовка и управление образом операционной системы при отладке,
|
||||
тестировании, компиляции, установке или восстановлении. При этом
|
||||
вся иерархия файловых систем гостевой ОС монтируется или
|
||||
создается в каталоге системы-хоста, и при запуске оболочки (или
|
||||
любого другого приложения) внутри этой иерархии, их корень
|
||||
сдвигается в этот каталог. Система, которую <<видят>> такие
|
||||
программы, может сильно отличаться от ОС хоста. Например, это
|
||||
может быть другой дистрибутив, или даже другая аппаратная
|
||||
архитектура (запуск i386-гостя на x86\_64-хосте). Гостевая ОС
|
||||
не~может увидеть полной иерархии ОС хоста.
|
||||
\end{enumerate}
|
||||
|
||||
В системах, использующих классический SysV init, использовать chroot-окружения
|
||||
сравнительно несложно. Например, чтобы запустить выбранного демона внутри
|
||||
иерархии гостевой ОС, достаточно смонтировать внутри этой иерархии +/proc+,
|
||||
+/sys+ и остальные API ФС, воспользоваться программой +chroot(1)+ для входа в
|
||||
окружение, и выполнить соответствующий init-скрипт, запустив +/sbin/service+
|
||||
внутри окружения.
|
||||
|
||||
Но в системах, использующих systemd, уже не~все так просто. Одно из важнейших
|
||||
достоинств systemd состоит в том, что параметры среды, в которой запускаются
|
||||
демоны, никак не~зависит от метода их запуска. В системах, использующих SysV
|
||||
init, многие параметры среды выполнения (в частности, лимиты на системные
|
||||
ресурсы, переменные окружения, и т.п.) наследуются от оболочки, из которой был
|
||||
запущен init-скрипт. При использовании systemd ситуация меняется радикально:
|
||||
пользователь просто уведомляет init-демона о необходимости запустить ту или иную
|
||||
службу, и тот запускает демона в чистом, созданном <<с нуля>> и тщательно
|
||||
настроенном окружении, параметры которого никак не~зависят от настроек среды, из
|
||||
которой была отдана команда. Такой подход полностью отменяет традиционный метод
|
||||
запуска демонов в chroot-окружениях: теперь демон порождается процессом init
|
||||
(PID~1) и наследует корневой каталог от него, вне зависимости от того, находился
|
||||
ли пользователь, отдавший команду на запуск, в chroot-окружении, или нет. Кроме
|
||||
того, стоит особо отметить, что взаимодействие управляющих программ с systemd
|
||||
происходит через сокеты, находящиеся в каталоге +/run/systemd+, так что
|
||||
программы, запущенные в chroot-окружении, просто не~смогут взаимодействовать с
|
||||
init-подсистемой (и это, в общем, неплохо, а если такое ограничение будет
|
||||
создавать проблемы, его можно легко обойти, используя bind-монтирование).
|
||||
|
||||
В свете вышесказанного, возникает вопрос: как правильно использовать
|
||||
chroot-окружения в системах на основе systemd? Что ж, постараемся дать подробный
|
||||
и всесторонний ответ на этот вопрос.
|
||||
|
||||
Для начала рассмотрим первое из перечисленных выше применений chroot: изоляция в
|
||||
целях безопасности. Прежде всего, стоит заметить, что защита, предоставляемая
|
||||
chroot'ом, весьма эфемерна и ненадежна, так как chroot не~является <<дорогой с
|
||||
односторонним движением>>. Выйти из chroot-окружения сравнительно несложно, и
|
||||
соответствующее предупреждение даже
|
||||
\href{http://linux.die.net/man/2/chroot}{присутствует на странице руководства}.
|
||||
Действительно эффективной защиты можно достичь, только сочетая chroot с другими
|
||||
методиками. В большинстве случаев, это возможно только при наличии поддержки
|
||||
chroot в самой программе. Прежде всего, корректное конфигурирование
|
||||
chroot-окружения требует глубокого понимания принципов работы программы.
|
||||
Например, нужно точно знать, какие сокеты использует программа, чтобы обеспечить
|
||||
bind-монтирование соответствующих каталогов. С учетом вышесказанного,
|
||||
эффективная chroot-защита обеспечивается в том случае, когда она реализована в
|
||||
коде самого демона. Именно разработчик лучше других знает (\emph{обязан} знать),
|
||||
как правильно сконфигурировать chroot-окружение, и какой минимальный набор
|
||||
файлов, каталогов и файловых систем необходим внутри него для нормальной работы
|
||||
демона. Уже сейчас существуют демоны, имеющие встроенную поддержку chroot.
|
||||
К сожалению, в системе Fedora, установленной с параметрами по умолчанию, таких
|
||||
демонов всего два: \href{http://avahi.org/}{Avahi} и RealtimeKit. Оба они
|
||||
написаны одним очень хитрым человеком ;-) (Вы можете собственноручно
|
||||
убедится в этом, выполнив команду +ls -l /proc/*/root+.)
|
||||
|
||||
Возвращаясь к тема нашего обсуждения: разумеется, systemd позволяет помещать
|
||||
выбранных демонов в chroot, и управлять ими точно так же, как и другими.
|
||||
Достаточно лишь указать параметр +RootDirectory=+ в соответствующем
|
||||
service-файле. Например:
|
||||
\begin{Verbatim}
|
||||
[Unit]
|
||||
Description=A chroot()ed Service
|
||||
|
||||
[Service]
|
||||
RootDirectory=/srv/chroot/foobar
|
||||
ExecStartPre=/usr/local/bin/setup-foobar-chroot.sh
|
||||
ExecStart=/usr/bin/foobard
|
||||
RootDirectoryStartOnly=yes
|
||||
\end{Verbatim}
|
||||
|
||||
Рассмотрим этот пример подробнее. Параметр +RootDirectory=+ задает каталог, в
|
||||
который производится chroot перед запуском исполняемого файла, заданного
|
||||
параметром +ExecStart=+. Заметим, что путь к этому файлу должен быть указан
|
||||
относительно каталога chroot (так что, в нашем случае, с точки зрения основной
|
||||
системы, на исполнение будет запущен файл +/srv/chroot/foobar/usr/bin/foobard+).
|
||||
Перед запуском демона будет вызван сценарий оболочки +setup-foobar-chroot.sh+,
|
||||
который должен обеспечить подготовку chroot-окружения к запуску демона
|
||||
(например, смонтировать в нем +/proc+ и/или другие файловые системы, необходимые
|
||||
для работы демона). Указав +RootDirectoryStartOnly=yes+, мы задаем, что
|
||||
+chroot()+ будет выполняться только перед выполнением файла из +ExecStart=+, а
|
||||
команды из других директив, в частности, +ExecStartPre=+, будут иметь полный
|
||||
доступ к иерархии файловых систем ОС (иначе наш скрипт просто не~сможет
|
||||
выполнить bind-монтирование нужных каталогов). Более подробную информацию по
|
||||
опциям конфигурации вы можете получить на
|
||||
\href{http://0pointer.de/public/systemd-man/systemd.service.html}{страницах}
|
||||
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{руководства}.
|
||||
|
||||
Поместив приведенный выше текст примера в файл
|
||||
+/etc/systemd/system/foobar.service+, вы сможете запустить chroot'нутого демона
|
||||
командой +systemctl start foobar.service+. Информацию о его текущем состоянии
|
||||
можно получить с помощью команды +systemctl status foobar.service+. Команды
|
||||
управления и мониторинга службы не~зависят от того, запущена ли она в chroot'е,
|
||||
или нет. Этим systemd отличается от классического SysV init.
|
||||
|
||||
Новые ядра Linux поддерживают возможность создания независимых пространств имен
|
||||
файловых систем (в дальнейшем FSNS, от <<file system namespaces>>). По
|
||||
функциональности этот механизм аналогичен +chroot()+, однако предоставляет
|
||||
гораздо более широкие возможности, и в нем отсутствуют проблемы с безопасностью,
|
||||
характерные для chroot. systemd позволяет использовать при конфигурировании
|
||||
юнитов некоторые возможности, предоставляемые FSNS. В частности, использование
|
||||
FSNS часто является гораздо более простой и удобной альтернативой созданию
|
||||
полноценных chroot-окружений. Используя директивы +ReadOnlyDirectories=+,
|
||||
+InaccessibleDirectories=+, вы можете задать ограничения по использованию
|
||||
иерархии файловых систем для заданной службы: ее корнем будет системный корневой
|
||||
каталог, однако указанные в этих директивах подкаталоги будут доступны только
|
||||
для чтения или вообще недоступны для нее. Например:
|
||||
\begin{Verbatim}
|
||||
[Unit]
|
||||
Description=A Service With No Access to /home
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/foobard
|
||||
InaccessibleDirectories=/home
|
||||
\end{Verbatim}
|
||||
|
||||
Такая служба будет иметь доступ ко всей иерархии файловых систем ОС, с
|
||||
единственным исключением~--- она не~будет видеть каталог +/home+, что позволит
|
||||
защитить данные пользователей от потенциальных хакеров. (Подробнее об этих
|
||||
опциях можно почитать на
|
||||
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{странице
|
||||
руководства}.)
|
||||
|
||||
Фактически, FSNS по множеству параметров превосходят +chroot()+. Скорее всего,
|
||||
Avahi и ReltimeKit в ближайшем будущем перейдут с +chroot()+ к использованию
|
||||
FSNS.
|
||||
|
||||
Итак, мы рассмотрели вопросы использования chroot для обеспечения безопасности.
|
||||
Переходим ко второму пункту: Подготовка и управление образом операционной
|
||||
системы при отладке, тестировании, компиляции, установке или восстановлении.
|
||||
|
||||
chroot-окружения, по сути, весьма примитивно: они изолируют только иерархии
|
||||
файловых систем. Даже после chroot'а в определенный подкаталог, процесс
|
||||
по-прежнему имеет полный доступ к системным вызовам, может убить любой процесс
|
||||
из основной системы, и т.п. Вследствие этого, запуск полноценной ОС (или ее
|
||||
части) внутри chroot'а несет угрозу для хост-системы: у гостя и хоста отличаются
|
||||
лишь содержимое файловой системы, все остальное у них общее. Например, если вы
|
||||
обновляете дистрибутив, установленный в chroot-окружении, и пост-установочный
|
||||
скрипт пакета отправляет +SIGTERM+ процессу init для его
|
||||
перезапуска\footnote{Прим. перев.: Во избежание путаницы отметим, что перезапуск
|
||||
процесса init (PID~1) <<на лету>> при получении +SIGTERM+ поддерживается только
|
||||
в systemd, в классическом SysV init такой возможности нет}, на него среагирует
|
||||
именно хост-система! Кроме того, хост и chroot'нутая система будут иметь общую
|
||||
разделяемую память SysV (SysV shared memory), общие сокеты из абстрактных
|
||||
пространств имен (abstract namespace sockets) и другие элементы IPC. Для
|
||||
отладки, тестирования, компиляции, установки и восстановлении ОС не~требуется
|
||||
абсолютно безопасная изоляция, однако нужна защита от \emph{случайного}
|
||||
воздействия на ОС хоста изнутри chroot-окружения, иначе вы можете получить целый
|
||||
букет проблем, как минимум, от пост-инсталляционных скриптов при установке
|
||||
пакетов в chroot-окружении.
|
||||
|
||||
systemd имеет целый ряд возможностей, полезных для работы с chroot-системами:
|
||||
|
||||
Прежде всего, управляющая программа +systemctl+ автоматически определяет, что
|
||||
она запущена в chroot-системе. В такой ситуации будут работать только команды
|
||||
+systemctl enable+ и +systemctl disable+, во всех остальных случаях +systemctl+
|
||||
просто не~будет ничего делать, возвращая код успешного завершения операции.
|
||||
Таким образом, пакетные скрипты смогут включить/отключить запуск <<своих>> служб
|
||||
при загрузке (или в других ситуациях), однако команды наподобие
|
||||
+systemctl restart+ (обычно выполняется при обновлении пакета) не~дадут никакого
|
||||
эффекта внутри chroot-окружения\footnote{Прим. перев.: автор забывает отметить
|
||||
не~вполне очевидный момент: такое поведение +systemctl+ проявляется только в
|
||||
<<мертвых>> окружениях, т.е. в тех, где не~запущен процесс init, и
|
||||
соответственно отсутствуют управляющие сокеты в +/run/systemd+. Такая ситуация
|
||||
возникает, например, при установке системы в chroot через
|
||||
debootstrap/febootstrap. В этом случае возможности +systemctl+ ограничиваются
|
||||
операциями с символьными ссылками, определяющими триггеры активации юнитов, т.е.
|
||||
выполнением действий +enable+ и +disable+, не~требующих непосредственного
|
||||
взаимодействия с процессом init.}.
|
||||
|
||||
Однако, куда более интересные возможности предоставляет программа
|
||||
\href{http://0pointer.de/public/systemd-man/systemd-nspawn.html}{systemd-nspawn},
|
||||
входящая в стандартный комплект поставки systemd. По сути, это улучшенный аналог
|
||||
+chroot(1)+~--- она не~только подменяет корневой каталог, но и создает отдельные
|
||||
пространства имен для дерева файловых систем (FSNS) и для идентификаторов
|
||||
процессов (PID NS), предоставляя легковесную реализацию системного
|
||||
контейнера\footnote{Прим. перев.: Используемые в +systemd-nspawn+ механизмы
|
||||
ядра Linux, такие, как FS NS и PID NS, также лежат в основе
|
||||
\href{http://lxc.sourceforge.net/}{LXC}, системы контейнерной изоляции для
|
||||
Linux, которая позиционируется как современная альтернатива классическому
|
||||
\href{http://wiki.openvz.org/Main_Page}{OpenVZ}. Стоит отметить, что LXC
|
||||
ориентирована прежде всего на создание независимых виртуальных окружений,
|
||||
с поддержкой раздельных сетевых стеков, ограничением на ресурсы, сохранением
|
||||
настроек и т.п., в то время как +systemd-nspawn+ является лишь более удобной и
|
||||
эффективной заменой команды +chroot(1)+, предназначенной прежде всего для
|
||||
развертывания, восстановления, сборки и тестирования операционных систем. Далее
|
||||
автор разъясняет свою точку зрения на этот вопрос.}.
|
||||
+systemd-nspawn+ проста в использовании как +chroot(1)+, однако изоляция
|
||||
от хост-системы является более полной и безопасной. Всего одной командой
|
||||
вы можете загрузить внутри контейнера \emph{полноценную} ОС (на базе systemd
|
||||
или SysV init). Благодаря использованию независимых пространств идентификаторов
|
||||
процессов, процесс init внутри контейнера получит PID~1, что позволит работать
|
||||
ему в штатном режиме. Также, в отличие от +chroot(1)+, внутри окружения
|
||||
будут автоматически смонтированы +/proc+ и +/sys+.
|
||||
|
||||
Следующий пример иллюстрирует возможность запустить Debian в на Fedora-хосте
|
||||
всего тремя командами:
|
||||
\begin{Verbatim}
|
||||
# yum install debootstrap
|
||||
# debootstrap --arch=amd64 unstable debian-tree/
|
||||
# systemd-nspawn -D debian-tree/
|
||||
\end{Verbatim}
|
||||
|
||||
Вторая из этих команд обеспечивает развертывание в подкаталоге +./debian-tree/+
|
||||
файловой структуры дистрибутива Debian, после чего третья команда запускает
|
||||
внутри полученной системы процесс командной оболочки. Если вы хотите запустить
|
||||
внутри контейнера полноценную ОС, воспользуйтесь командой
|
||||
\begin{Verbatim}
|
||||
# systemd-nspawn -D debian-tree/ /sbin/init
|
||||
\end{Verbatim}
|
||||
|
||||
После быстрой загрузки вы получите приглашение оболочки, запущенной внутри
|
||||
полноценной ОС, функционирующей в контейнере. Изнутри контейнера невозможно
|
||||
увидеть процессы, которые находятся вне его. Контейнер сможет пользоваться сетью
|
||||
хоста, однако не~имеет возможности изменить ее настройки (это может привести к
|
||||
серии ошибок в процессе загрузки гостевой ОС, но ни~одна из этих ошибок
|
||||
не~должна быть критической). Контейнер получает доступ к +/sys+ и +/proc/sys+,
|
||||
однако, во избежание вмешательства контейнера в конфигурацию ядра и аппаратного
|
||||
обеспечения хоста, эти каталоги будут смонтированы только для чтения. Обратите
|
||||
внимание, что эта защита блокирует лишь \emph{случайные}, \emph{непредвиденные}
|
||||
попытки изменения параметров. При необходимости, процесс внутри контейнера,
|
||||
обладающий достаточными полномочиями, сможет перемонтировать эти файловые
|
||||
системы в режиме чтения-записи.
|
||||
|
||||
Итак, что же такого хорошего в +systemd-nspawn+?
|
||||
\begin{enumerate}
|
||||
\item Использовать эту утилиту очень просто. Вам даже не~нужно вручную монтировать
|
||||
внутри окружения +/proc+ и +/sys+~--- она сделает это за вас, а
|
||||
ядро автоматически отмонтирует их, когда последний процесс
|
||||
контейнера завершится.
|
||||
\item Обеспечивается надежная изоляция, предотвращающая случайные
|
||||
изменения параметров ОС хоста изнутри контейнера.
|
||||
\item Теперь вы можете загрузить внутри контейнера полноценную ОС, а
|
||||
не~одну-единственную оболочку.
|
||||
\item Эта утилита очень компактна и присутствует везде, где установлен
|
||||
systemd. Она не~требует специальной установки и настройки.
|
||||
\end{enumerate}
|
||||
|
||||
systemd уже подготовлен для работы внутри таких контейнеров. Например, когда
|
||||
подается команда на выключение системы внутри контейнера, systemd на последнем
|
||||
шаге вызывает не~+reboot()+, а просто +exit()+.
|
||||
|
||||
Стоит отметить, что +systemd-nspawn+ все же не~является полноценной системой
|
||||
контейнерной виртуализации/изоляции~--- если нужно именно это, воспользуйтесь
|
||||
\href{ http://lxc.sourceforge.net/}{LXC}. Этот проект использует те же самые
|
||||
механизмы ядра, но предоставляет куда более широкие возможности, включая
|
||||
виртуализацию сети. Если вам угодно, +systemd-nspawn+ как реализация контейнера
|
||||
похожа на GNOME~3~--- компактна и проста в использовании, опций для настройки
|
||||
очень мало. В то время как LXC больше похож на KDE: опций для настройки больше,
|
||||
чем строк кода. Я создал +systemd-nspawn+ специально для тестирования, отладки,
|
||||
сборки, восстановления. Именно для этих задач вам стоит ее использовать~--- она
|
||||
неплохо с ними справляется, куда лучше, чем +chroot(1)+.
|
||||
|
||||
Что ж, пора заканчивать. Итак:
|
||||
\begin{enumerate}
|
||||
\item Использование +chroot()+ для обеспечения безопасности дает
|
||||
наилучший результат, когда оно реализовано непосредственно в
|
||||
коде самой программы.
|
||||
\item +ReadOnlyDirectories=+ и +InaccessibleDirectories=+ могут быть
|
||||
удобной альтернативой созданию полновесных chroot-окружений.
|
||||
\item Если вам нужно поместить в chroot-окружение какую-либо службу,
|
||||
воспользуйтесь опцией +RootDirectory=+.
|
||||
\item +systemd-nspawn+~--- очень неплохая штука.
|
||||
\item chroot'ы убоги, FSNS~---
|
||||
\href{http://ru.wikipedia.org/wiki/Leet}{1337}.
|
||||
\end{enumerate}
|
||||
|
||||
И все это уже сейчас доступно в Fedora~15.
|
||||
|
||||
\section{Поиск виновных}
|
||||
|
||||
Fedora~15\footnote{Величайший в истории релиз свободной ОС}
|
||||
является первым релизом Fedora, использующим systemd в качестве системы
|
||||
инициализации по умолчанию. Основной нашей целью при работе над выпуском F15
|
||||
является обеспечение полной взаимной интеграции и корректной работы всех
|
||||
компонентов. При подготовке следующего релиза, F16, мы сконцентрируемся на
|
||||
дальнейшей полировке и ускорении системы. Для этого мы подготовили ряд
|
||||
инструментов (доступных уже в F15), которые должны помочь нам в поиске проблем,
|
||||
связанных с процессом загрузки. В этой статье я попытаюсь рассказать о том, как
|
||||
найти виновников медленной загрузки вашей системы, и о том, что с ними делать
|
||||
дальше.
|
||||
|
||||
Первый инструмент, который мы можем вам предложить, очень прост: по завершении
|
||||
загрузки, systemd регистрирует в системном журнале информацию о суммарном
|
||||
времени загрузки:
|
||||
\begin{Verbatim}
|
||||
systemd[1]: Startup finished in 2s 65ms 924us (kernel) + 2s 828ms 195us (initrd)
|
||||
+ 11s 900ms 471us (userspace) = 16s 794ms 590us.
|
||||
\end{Verbatim}
|
||||
|
||||
Эта запись означает следующее: на инициализацию ядра (до момента запуска initrd,
|
||||
т.е. dracut) ушло 2 секунды. Далее, чуть менее трех секунд работал initrd. И
|
||||
наконец, почти 12 секунд было потрачено systemd на запуск программ из
|
||||
пространства пользователя. Итоговое время, начиная с того момента, как загрузчик
|
||||
передал управление коду ядра, до того момента, как systemd завершил все
|
||||
операции, связанные с загрузкой системы, составило почти 17 секунд. Казалось
|
||||
бы, смысл этого числа вполне очевиден\ldots{} Однако не~стоит делать поспешных
|
||||
выводов. Прежде всего, сюда не~входит время, затраченное на
|
||||
инициализацию вашего сеанса в GNOME, так как эта задача уже выходит за рамки
|
||||
задач процесса init. Кроме того, в этом показателе учитывается только время
|
||||
работы systemd, хотя часто бывает так, что некоторые демоны продолжают
|
||||
\emph{свою} работу по инициализации уже после того, как секундомер остановлен.
|
||||
Проще говоря: приведенные числа позволяют лишь оценить общую скорость
|
||||
загрузки, однако они не~являются точной характеристикой длительности процесса.
|
||||
|
||||
Кроме того, эта информация носит поверхностный характер: она не~сообщает, какие
|
||||
именно системные компоненты заставляют systemd ждать так долго. Чтобы исправить
|
||||
это упущение, мы ввели команду +systemd-analyze blame+:
|
||||
\begin{Verbatim}
|
||||
$ systemd-analyze blame
|
||||
6207ms udev-settle.service
|
||||
5228ms cryptsetup@luks\x2d9899b85d\x2df790\x2d4d2a\x2da650\x2d8b7d2fb92cc3.service
|
||||
735ms NetworkManager.service
|
||||
642ms avahi-daemon.service
|
||||
600ms abrtd.service
|
||||
517ms rtkit-daemon.service
|
||||
478ms fedora-storage-init.service
|
||||
396ms dbus.service
|
||||
390ms rpcidmapd.service
|
||||
346ms systemd-tmpfiles-setup.service
|
||||
322ms fedora-sysinit-unhack.service
|
||||
316ms cups.service
|
||||
310ms console-kit-log-system-start.service
|
||||
309ms libvirtd.service
|
||||
303ms rpcbind.service
|
||||
298ms ksmtuned.service
|
||||
288ms lvm2-monitor.service
|
||||
281ms rpcgssd.service
|
||||
277ms sshd.service
|
||||
276ms livesys.service
|
||||
267ms iscsid.service
|
||||
236ms mdmonitor.service
|
||||
234ms nfslock.service
|
||||
223ms ksm.service
|
||||
218ms mcelog.service
|
||||
...
|
||||
\end{Verbatim}
|
||||
|
||||
Она выводит список юнитов systemd, активированных при загрузке, с указанием
|
||||
времени инициализации для каждого из них. Список отсортирован по убыванию этого
|
||||
времени, поэтому наибольший интерес для нас представляют первые строчки. В нашем
|
||||
случае это +udev-settle.service+ и
|
||||
+cryptsetup@luks\x2d9899b85d\x2df790\x2d4d2a\x2da650\x2d8b7d2fb92cc3.service+,
|
||||
инициализация которых занимает более одной секунды. Стоит отметить, что к
|
||||
анализу вывода команды +systemd-analyze blame+ тоже следует подходить с
|
||||
осторожностью: она не~поясняет, \emph{почему} тот или иной юнит тратит
|
||||
столько-то времени, она лишь констатирует факт, что время было затрачено. Кроме
|
||||
того, не~стоит забывать, что юниты могут запускаться параллельно. В частности,
|
||||
если две службы были запущены одновременно, то время их инициализации будет
|
||||
значительно меньше, чем сумма времен инициализации каждой из них.
|
||||
|
||||
Рассмотрим повнимательнее первого осквернителя нашей загрузки: службу
|
||||
+udev-settle.service+. Почему ей требуется так много времени для запуска, и что
|
||||
мы можем с этим сделать? Эта служба выполняет очень простую задачу: она ожидает,
|
||||
пока udev завершит опрос устройств, после чего завершается. Опрос же устройств
|
||||
может занимать довольно много времени. Например, в нашем случае опрос устройств
|
||||
занимает более 6~секунд из-за встроенного в компьютер 3G-модема, в котором
|
||||
отсутствует SIM-карта. Этот модем очень долго отвечает на запросы udev. Опрос
|
||||
устройств является частью схемы, обеспечивающей работу ModemManager'а и
|
||||
позволяющей NetworkManager'у упростить для вас настройку 3G. Казалось бы,
|
||||
очевидно, что виновником задержки является именно ModemManager, так как опрос
|
||||
устройств для него занимает слишком много времени. Но такое обвинение будет
|
||||
заведомо ошибочным. Дело в том, что опрос устройств очень часто оказывается довольно
|
||||
длительной процедурой. Медленный опрос 3G-устройств для ModemManager является
|
||||
частным случаем, отражающим это общее правило. Хорошая система опроса устройств
|
||||
обязательно должна учитывать тот факт, что операция опроса любого из устройств
|
||||
может затянуться надолго. Истинной причиной наших проблем является необходимость
|
||||
ожидать завершения опроса устройств, т.е., наличие службы
|
||||
+udev-settle.service+ как обязательной части нашего процесса загрузки.
|
||||
|
||||
Но почему эта служба вообще присутствует в нашем процессе загрузки? На самом
|
||||
деле, мы можем прекрасно обойтись и без нее. Она нужна лишь как часть
|
||||
используемой в Fedora схемы инициализации устройств хранения, а именно,
|
||||
набора скриптов, выполняющих настройку LVM, RAID и multipath-устройств. На
|
||||
сегодняшний день, реализация этих систем не~поддерживает собственного механизма
|
||||
поиска и опроса устройств, и поэтому их запуск должен производиться только после
|
||||
того, как эта работа уже проделана~--- тогда они могут просто последовательно
|
||||
перебирать все диски. Однако, такой подход противоречит одному из
|
||||
фундаментальных требований к современным компьютерам:
|
||||
возможности подключать и отключать оборудование в любой момент, как при
|
||||
выключенном компьютере, так и при включенном. Для некоторых
|
||||
технологий невозможно точно определить момент завершения формирования списка устройств
|
||||
(например, это характерно для USB и iSCSI), и поэтому процесс опроса
|
||||
таких устройств обязательно должен включать некоторую фиксированную задержку,
|
||||
гарантирующую, что все подключенные устройства успеют отозваться. С точки зрения
|
||||
скорости загрузки это, безусловно, негативный эффект: соответствующие скрипты
|
||||
заставляют нас ожидать завершения опроса устройств, хотя большинство этих
|
||||
устройств не~являются необходимыми на данной стадии загрузки. В частности, в
|
||||
рассматриваемой нами системе LVM, RAID и multipath вообще
|
||||
не~используются!\footnote{Наиболее правильным решением в данном случае будет
|
||||
ожидание событий подключения устройств (реализованное через libudev или
|
||||
аналогичную технологию) с соответствующей обработкой каждого такого события~---
|
||||
подобный подход позволит нам продолжить загрузку, как только будут готовы все
|
||||
устройства, необходимые для ее продолжения. Для того, чтобы загрузка была
|
||||
быстрой, мы должны ожидать завершения инициализации только тех устройств, которые
|
||||
\emph{действительно} необходимы для ее продолжения на данной стадии. Ожидать
|
||||
остальные устройства в данном случае смысла нет. Кроме того, стоит отметить, что
|
||||
в числе программ, не~приспособленных для работы с динамически меняющимся
|
||||
оборудованием и построенных в предположении о неизменности списка устройств,
|
||||
кроме служб хранения, есть и другие подсистемы. Например, в нашем случае работа
|
||||
initrd занимает так много времени главным образом из-за того, что для запуска
|
||||
Plymouth необходимо дождаться завершения инициализации всех устройств
|
||||
видеовывода. По неизвестной причине (во всяком случае, неизвестной для меня)
|
||||
подгрузка модулей для моих видеокарт Intel занимает довольно продолжительное
|
||||
время, что приводит к беспричинной задержке процесса загрузки. (Нет, я протестую
|
||||
не~против опроса устройств, но против необходимости ожидать его завершения, чтобы
|
||||
продолжить загрузку.)}
|
||||
|
||||
С учетом вышесказанного, мы можем спокойно исключить +udev-settle.service+ из
|
||||
нашего процесса загрузки, так как мы не~используем ни~LVM, ни~RAID,
|
||||
ни~multipath. Замаскируем эти службы, чтобы увеличить скорость загрузки:
|
||||
\begin{Verbatim}
|
||||
# ln -s /dev/null /etc/systemd/system/udev-settle.service
|
||||
# ln -s /dev/null /etc/systemd/system/fedora-wait-storage.service
|
||||
# ln -s /dev/null /etc/systemd/system/fedora-storage-init.service
|
||||
# systemctl daemon-reload
|
||||
\end{Verbatim}
|
||||
|
||||
После перезагрузки мы видим, что загрузка стала на одну секунду быстрее. Но
|
||||
почему выигрыш оказался таким маленьким? Из-за второго осквернителя нашей
|
||||
загрузки~--- cryptsetup. На рассматриваемой нами системе зашифрован раздел
|
||||
+/home+. Специально для тестирования я записал пароль в файл, чтобы исключить
|
||||
влияние скорости ручного набора пароля. К сожалению, для подключения
|
||||
шифрованного раздела cryptsetup требует более пяти секунд. Будем ленивы, и
|
||||
вместо того, чтобы исправлять ошибку в cryptsetup\footnote{На самом деле, я
|
||||
действительно пытался исправить эту ошибку. Задержки в cryptsetup, по
|
||||
моим наблюдениям, обусловлены, главным образом, слишком большим значением по
|
||||
умолчанию для опции +--iter-time+. Я попытался доказать сопровождающим пакета
|
||||
cryptsetup, что снижение этого времени с 1 секунды до 100~миллисекунд
|
||||
не~приведет к трагическим последствиям для безопасности, однако они мне
|
||||
не~поверили.}, попробуем найти обходной путь\footnote{Вообще-то я предпочитаю
|
||||
решать проблемы, а не~искать пути для их обхода, однако в данном конкретном
|
||||
случае возникает отличная возможность продемонстрировать одну интересную
|
||||
возможность systemd\ldots{}}. Во время загрузки systemd должен дождаться, пока
|
||||
все файловые системы, перечисленные в +/etc/fstab+ (кроме помеченных как
|
||||
+noauto+) будут обнаружены, проверены и смонтированы. Только после этого systemd
|
||||
может продолжить загрузку и приступить к запуску служб. Но первое обращение
|
||||
к +/home+ (в отличие, например, от +/var+), происходит на поздней стадии
|
||||
процесса загрузки (когда пользователь входит в систему). Следовательно, нам
|
||||
нужно сделать так, чтобы этот каталога автоматически монтировался при загрузке,
|
||||
но процесс загрузки не~ожидал завершения работы +cryptsetup+, +fsck+ и +mount+
|
||||
для этого раздела. Как же сделать точку монтирования доступной, не~ожидая, пока
|
||||
завершится процесс монтирования? Это можно сделать, воспользовавшись магической
|
||||
силой systemd~--- просто добавим опцию монтирования +comment=systemd.automount+
|
||||
в +/etc/fstab+. После этого, systemd будет создавать в +/home+ точку
|
||||
автоматического монтирования, и при первом же обращении к этому каталогу,
|
||||
если файловая система еще не~будет готова к работе,
|
||||
systemd подготовит соответствующее устройство, проверит и смонтирует ее.
|
||||
|
||||
После внесения изменений в +/etc/fstab+ и перезагрузки мы получаем:
|
||||
\begin{Verbatim}
|
||||
systemd[1]: Startup finished in 2s 47ms 112us (kernel) + 2s 663ms 942us (initrd)
|
||||
+ 5s 540ms 522us (userspace) = 10s 251ms 576us.
|
||||
\end{Verbatim}
|
||||
|
||||
Прекрасно! Несколькими простыми действиями мы выиграли почти семь секунд. И эти
|
||||
два изменения исправляют только две наиболее очевидные проблемы. При более
|
||||
аккуратном и детальном исследовании, обнаружится еще множество моментов, которые
|
||||
можно улучшить. Например, на другом моем компьютере, лаптопе X300 двухлетней
|
||||
давности (и даже два года назад он был не~самым быстрым на Земле), после
|
||||
небольшой доработки, время загрузки до полноценной среды GNOME
|
||||
составило около четырех секунд, и это еще не~предел совершенства.
|
||||
|
||||
+systemd-analyze blame+~--- простой и удобный инструмент для поиска медленно
|
||||
запускающихся служб, однако он обладает одним существенным недостатком: он
|
||||
не~показывает, насколько эффективно параллельный запуск снижает потерю времени
|
||||
для медленно запускающихся служб. Чтобы вы могли наглядно оценить этот фактор,
|
||||
мы подготовили команду +systemd-analyze plot+. Использовать ее очень просто:
|
||||
\begin{Verbatim}
|
||||
$ systemd-analyze plot > plot.svg
|
||||
$ eog plot.svg
|
||||
\end{Verbatim}
|
||||
|
||||
Она создает наглядные диаграммы, показывающие моменты запуска служб и время,
|
||||
затраченное на их запуск, по отношению к другим службам. На текущий момент, она
|
||||
не~показывает явно, кто кого ожидает, но догадаться обычно несложно.
|
||||
|
||||
Чтобы продемонстрировать эффект, порожденный двумя нашими оптимизациями,
|
||||
приведем ссылки на соответствующие графики:
|
||||
\href{http://0pointer.de/public/blame.svg}{до} и
|
||||
\href{http://0pointer.de/public/blame2.svg}{после} (для полноты описания приведем также и
|
||||
соответствующие данные +systemd-analyze blame+:
|
||||
\href{http://0pointer.de/public/blame.txt}{до} и
|
||||
\href{http://0pointer.de/public/blame2.txt}{после}).
|
||||
|
||||
У наиболее эрудированных читателей может возникнуть вопрос: как это соотносится с
|
||||
программой \href{https://github.com/mmeeks/bootchart}{bootchart}? Действительно,
|
||||
+systemd-analyze plot+ и +bootchart+ рисуют похожие графики. Однако, bootchart
|
||||
является намного более мощным инструментом~--- он детально показывает, что
|
||||
именно происходило во время загрузки, и отображает соответствующие графики
|
||||
использования процессора и ввода-вывода. +systemd-analyze plot+ оперирует более
|
||||
высокоуровневой информацией: сколько времени затратила та или иная служба во
|
||||
время запуска, и какие службы были вынуждены ее ожидать. Используя оба эти
|
||||
инструмента, вы значительно упростите себе поиск причин замедления вашей
|
||||
загрузки.
|
||||
|
||||
Но прежде, чем вы вооружитесь описанными здесь средствами и начнете
|
||||
отправлять багрепорты авторам и сопровождающим программ, которые замедляют вашу
|
||||
загрузку, обдумайте все еще раз. Эти инструменты предоставляют вам <<сырую>>
|
||||
информацию. Постарайтесь не~ошибиться, интерпретируя ее. Например, в
|
||||
при рассмотрении приведенного выше примера я показал, что проблема была вовсе
|
||||
не~в +udev-settle.service+, и не~в опросе устройств для ModemManager'а, а в
|
||||
неудачной реализации подсистемы хранения, требующей ожидать окончания опроса
|
||||
устройств для продолжения загрузки. Именно эту проблему и нужно исправлять.
|
||||
Поэтому постарайтесь правильно определить источник проблем. Возлагайте вину на
|
||||
тех, кто действительно виноват.
|
||||
|
||||
Как уже говорилось выше, все три описанных здесь инструмента доступны в
|
||||
Fedora~15 <<из коробки>>.
|
||||
|
||||
Итак, какие же выводы мы можем сделать из этой истории?
|
||||
\begin{itemize}
|
||||
\item +systemd-analyze+~--- отличный инструмент. Фактически, это
|
||||
встроенный профилировщик systemd.
|
||||
\item Постарайтесь не~ошибиться, интерпретируя вывод профилировщика!
|
||||
\item Всего два небольших изменения могут ускорить загрузку системы на
|
||||
семь секунд.
|
||||
\item Программное обеспечение, не~способное работать с динамически
|
||||
меняющимся набором устройств, создает проблемы, и должно быть
|
||||
исправлено.
|
||||
\item Принудительное использование в стандартной установке Fedora~15
|
||||
промышленной реализации подсистем хранения, возможно, является
|
||||
не~самым правильным решением.
|
||||
\end{itemize}
|
||||
|
||||
\section{Новые конфигурационные файлы}
|
||||
|
||||
Одно из наиболее масштабных нововведений
|
||||
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd}~--- наличие
|
||||
полного набора программ, необходимых на ранних стадиях загрузки, причем эти
|
||||
программы написаны на простом, быстром, надежном и легко поддающемся
|
||||
распараллеливанию языке C. Теперь можно отказаться от <<простыней>>
|
||||
shell-скриптов, разработанных для этих задач различными дистрибутивами. Наш
|
||||
<<Проект нулевой оболочки>>\footnote{Наш девиз~--- <<Первой оболочкой,
|
||||
запускающейся при старте системы, должна быть GNOME shell>>. Формулировка
|
||||
оставляет желать лучшего, но все же неплохо передает основную идею.} увенчался
|
||||
полным успехом. Уже сейчас возможности предоставляемого нами инструментария
|
||||
покрывают практически все нужды настольных и встраиваемых систем, а также
|
||||
большую часть потребностей серверных систем:
|
||||
\begin{itemize}
|
||||
\item Проверка и монтирование всех файловых систем.
|
||||
\item Обновление и активация квот на всех файловых системах.
|
||||
\item Установка имени хоста.
|
||||
\item Конфигурирование интерфейса обратной петли (+lo+).
|
||||
\item Подгрузка правил SELinux, обновление
|
||||
меток безопасности в динамических каталогах +/run+ и +/dev+.
|
||||
\item Регистрация в ядре дополнительных бинарных форматов (например,
|
||||
Java, Mono, WINE) через API-файловую систему +binfmt_misc+.
|
||||
\item Установка системной локали.
|
||||
\item Настройка шрифта и раскладки клавиатуры в консоли.
|
||||
\item Создание, очистка, удаление временных файлов и каталогов.
|
||||
\item Применение предписанных в +/etc/fstab+ опций к смонтированным
|
||||
ранее API-файловым системам.
|
||||
\item Применение настроек +sysctl+.
|
||||
\item Поддержка технологии упреждающего чтения (read ahead), включая
|
||||
автоматический сбор информации.
|
||||
\item Обновление записей в +utmp+ при включении и выключении системы.
|
||||
\item Сохранение и восстановление затравки для генерации случайных чисел
|
||||
(random seed).
|
||||
\item Принудительная загрузка указанных модулей ядра.
|
||||
\item Поддержка шифрованных дисков и разделов.
|
||||
\item Автоматический запуск +getty+ на serial-консолях.
|
||||
\item Взаимодействие с Plymouth.
|
||||
\item Создание уникального идентификатора системы.
|
||||
\item Установка часового пояса.
|
||||
\end{itemize}
|
||||
|
||||
В стандартной установке Fedora~15 запуск shell-скриптов требуется только для
|
||||
некоторых устаревших служб, а также для подсистемы хранения данных (поддержка
|
||||
LVM, RAID и multipath). Если они вам не~нужны, вы легко можете отключить их, и
|
||||
наслаждаться загрузкой, полностью очищенной от shell-костылей (я это сделал уже
|
||||
давно). Такая загрузка является уникальной возможностью Linux-систем.
|
||||
|
||||
Большинство перечисленных выше компонентов настраиваются через конфигурационные
|
||||
файлы в каталоге +/etc+. Некоторые из этих файлов стандартизированы для всех
|
||||
дистрибутивов, и поэтому реализация их поддержки в наших инструментах
|
||||
не~представляла особого труда. Например, это относится к файлам +/etc/fstab+,
|
||||
+/etc/crypttab+, +/etc/sysctl.conf+. Однако множество других, нестандартно
|
||||
расположенных файлов и каталогов вынуждали нас добавлять множество операторов
|
||||
+#ifdef+, чтобы обеспечить поддержку различных вариантов расположения
|
||||
конфигураций в разных дистрибутивах. Такой положение дел сильно усложняет
|
||||
жизнь нам всем, и при этом ничем не~оправдано~--- все эти файлы решают одни и те
|
||||
же задачи, но делают это немного по-разному.
|
||||
|
||||
Чтобы улучшить ситуацию и установить единый стандарт расположения базовых
|
||||
конфигурационных файлов во всех дистрибутивах, мы заставили systemd пользоваться
|
||||
дистрибутивно-специфическими конфигурациями только в качестве \emph{резервного}
|
||||
варианта~--- основным источником информации становится определенный нами
|
||||
стандартный набор конфигурационных файлов. Разумеется, там, где это возможно, мы
|
||||
старались не~придумывать чего-то принципиально нового, а брали лучшее из
|
||||
решений, предложенных существующими дистрибутивами. Ниже приводится небольшой
|
||||
обзор этого нового набора конфигурационных файлов, поддерживаемых systemd во
|
||||
всех дистрибутивах:
|
||||
\begin{itemize}
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/hostname.html}{/etc/hostname}:
|
||||
имя хоста для данной системы. Одна из наиболее простых и важных
|
||||
системных настроек. В разных дистрибутивах оно настраивалось
|
||||
по-разному: Fedora использовала +/etc/sysconfig/network+,
|
||||
OpenSUSE~--- +/etc/HOSTNAME+, Debian~--- +/etc/hostname+. Мы
|
||||
остановились на варианте, предложенном Debian.
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/vconsole.conf.html}{/etc/vconsole.conf}:
|
||||
конфигурация раскладки клавиатуры и шрифта для консоли.
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/locale.conf.html}{/etc/locale.conf}:
|
||||
конфигурация общесистемной локали.
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/modules-load.d.html}{/etc/modules-load.d/*.conf}:
|
||||
каталог\footnote{Прим. перев.: для описания этого и трех
|
||||
последующих каталогов автор пользуется термином <<drop-in
|
||||
directory>>. Этот термин означает каталог, в который можно
|
||||
поместить множество независимых файлов настроек, и при чтении
|
||||
конфигурации все эти файлы будут обработаны (впрочем, часто
|
||||
накладывается ограничение~--- обрабатываются только файлы с
|
||||
именами, соответствующими маске, обычно +*.conf+). Такой подход
|
||||
позволяет значительно упростить процесс как ручного, так и
|
||||
автоматического конфигурирования различных компонентов~--- для
|
||||
внесения изменений в настройки уже не~нужно редактировать
|
||||
основной конфигурационный файл, достаточно лишь
|
||||
скопировать/переместить в нужный каталог небольшой файл с
|
||||
указанием специфичных параметров.} для перечисления модулей
|
||||
ядра, которые нужно принудительно подгрузить при загрузке
|
||||
(впрочем, необходимость в этом возникает достаточно редко).
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/sysctl.d.html}{/etc/sysctl.d/*.conf}:
|
||||
каталог для задания параметров ядра (+sysctl+). Дополняет
|
||||
классический конфигурационный файл +/etc/sysctl.conf+.
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/tmpfiles.d.html}{/etc/tmpfiles.d/*.conf}:
|
||||
каталог для управления настройками временных файлов (systemd
|
||||
обеспечивает создание, очистку и удаление временных файлов и
|
||||
каталогов, как во время загрузки, так и во время работы
|
||||
системы).
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/binfmt.d.html}{/etc/binfmt.d/*.conf}:
|
||||
каталог для регистрации дополнительных бинарных форматов
|
||||
(например, форматов Java, Mono, WINE).
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/os-release.html}{/etc/os-release}:
|
||||
стандарт для файла, обеспечивающего идентификацию дистрибутива и
|
||||
его версии. Сейчас различные дистрибутивы используют для этого
|
||||
разные файлы (например, +/etc/fedora-release+ в Fedora), и
|
||||
поэтому для решения такой простой задачи, как вывод имени
|
||||
дистрибутива, необходимо использовать базу данных, содержащую
|
||||
перечень возможных названий файлов. Проект LSB попытался создать
|
||||
такой инструмент~---
|
||||
\hreftt{http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/lsbrelease.html}{lsb\_release}~---
|
||||
однако реализация такой простой вещи через скрипт на Python'е
|
||||
является не~самым оптимальным решением. Чтобы исправить
|
||||
сложившуюся ситуацию, мы решили перейти к единому простому
|
||||
формату представления этой информации.
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/machine-id.html}{/etc/machine-id}:
|
||||
файл с идентификатором данного компьютера (перекрывает
|
||||
аналогичный идентификатор D-Bus). Гарантируется, что в любой
|
||||
системе, использующей systemd, этот файл будет существовать и
|
||||
содержать корректную информацию (если его нет, он автоматически
|
||||
создается при загрузке). Мы вынесли этот файл из-под эгиды
|
||||
D-Bus, чтобы упростить решение множества задач, требующих
|
||||
наличия уникального и постоянного идентификатора компьютера.
|
||||
\item
|
||||
\hreftt{http://0pointer.de/public/systemd-man/machine-info.html}{/etc/machine-info}:
|
||||
новый конфигурационный файл, хранящий информации о полном имени
|
||||
(описательном) хоста (например, <<Компьютер Леннарта>>) и
|
||||
значке, которым он будет обозначаться в графических оболочках,
|
||||
работающих с сетью (раньше этот значок мог определяться,
|
||||
например, файлом +/etc/favicon.png+). Данный конфигурационный
|
||||
файл обслуживается демоном
|
||||
\hreftt{http://www.freedesktop.org/wiki/Software/systemd/hostnamed}{systemd-hostnamed}.
|
||||
\end{itemize}
|
||||
|
||||
Одна из важнейших для нас задач~--- убедить \emph{вас} использовать эти новые
|
||||
конфигурационные файлы в ваших инструментах для настройки системы. Если ваши
|
||||
конфигурационные фронтенды будут использовать новые файлы, а не~их старые
|
||||
аналоги, это значительно облегчит портирование таких фронтендов между
|
||||
дистрибутивами, и вы внесете свой вклад в стандартизацию Linux, и в конечном
|
||||
счете упростится жизнь и у администраторов, и для пользователей. Разумеется, на
|
||||
текущий момент эти файлы полностью поддерживаются только дистрибутивами,
|
||||
основанными на systemd, но уже сейчас в их число входят практически все ключевые
|
||||
дистрибутивы, \href{http://www.ubuntu.com/}{за исключением
|
||||
одного}\footnote{Прим. перев.: В конце 2010~года энтузиаст Andrew Edmunds
|
||||
\href{http://cgit.freedesktop.org/systemd/commit/?id=858dae181bb5461201ac1c04732d3ef4c67a0256}{добавил}
|
||||
в systemd базовую поддержку Ubuntu и
|
||||
\href{https://wiki.ubuntu.com/systemd}{подготовил} соответствующие пакеты,
|
||||
однако его инициатива не~встретила поддержки среди менеджеров Canonical. На
|
||||
момент написания этих строк (май 2011 года) проект остается заброшенным уже пять
|
||||
месяцев (с середины декабря 2010~г.).}.
|
||||
|
||||
\end{document}
|
||||
|
||||
vim:ft=tex:tw=80:spell:spelllang=ru
|
||||
|
||||
Reference in New Issue
Block a user