Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c24887c795 | ||
|
|
15e9a095a1 | ||
|
|
01f2aafc02 | ||
|
|
71b6656ebb | ||
|
|
3c9bd24d22 |
660
s4a.tex
660
s4a.tex
@@ -2,12 +2,13 @@
|
||||
\usepackage{cmap} % Copy-paste из PDF без проблем с кодировкой
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[english,russian]{babel} % Русские переносы и проч.
|
||||
\usepackage[pdftex]{graphicx,color}
|
||||
\usepackage{graphicx,color}
|
||||
\usepackage[T1,T2A]{fontenc}
|
||||
\usepackage{indentfirst} % Отступ в первом абзаце главы
|
||||
\usepackage{fancyvrb} % Продвинутые листинги и in-line commands
|
||||
% listings для данной ситуации, имхо, избыточен
|
||||
\usepackage{pdflscape}
|
||||
\usepackage{pdflscape} % Внимание! При выводе в DVI выборочный
|
||||
% поворот страниц работать не будет, хотя текст будет повернут.
|
||||
\usepackage[colorlinks,unicode,urlcolor=blue]{hyperref}
|
||||
% Заполняем поля PDF уже со включенной опцией unicode
|
||||
\hypersetup{pdftitle={systemd для администраторов},%
|
||||
@@ -17,9 +18,10 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||||
% Настройка макета страницы
|
||||
\setlength{\hoffset}{-1.5cm}
|
||||
\addtolength{\textwidth}{2cm}
|
||||
\setlength{\voffset}{-1.5cm}
|
||||
\addtolength{\textheight}{2cm}
|
||||
% Настройка in-line commands
|
||||
\setlength{\voffset}{-2cm}
|
||||
\addtolength{\textheight}{3cm}
|
||||
\addtolength{\footskip}{5pt}
|
||||
% Настройка форматирования in-line commands
|
||||
\DefineShortVerb{\+}
|
||||
\VerbatimFootnotes
|
||||
% И листингов
|
||||
@@ -32,8 +34,11 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||||
\begin{document}
|
||||
\sloppy
|
||||
\title{systemd для администраторов}
|
||||
\author{Lennart P\"{o}ttering (author)\\Sergey Ptashnick (russian translation)\\%
|
||||
\small Licensed under
|
||||
\author{Lennart P\"{o}ttering (автор)\thanks{Первоисточник (на английском
|
||||
языке) опубликован на сайте автора: \url{http://0pointer.de/blog/projects}}\\%
|
||||
Сергей Пташник (русский перевод)\thanks{Актуальная версия перевода
|
||||
доступна на портале OpenNet: \url{http://wiki.opennet.ru/Systemd}}\\%
|
||||
\small Данный документ доступен на условиях лицензии
|
||||
\href{http://creativecommons.org/licenses/by-sa/3.0/legalcode}{CC-BY-SA}}
|
||||
\maketitle
|
||||
\tableofcontents%\newpage
|
||||
@@ -42,7 +47,7 @@ pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||||
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd}~--- это
|
||||
новая система инициализации дистрибутива Fedora, начиная с
|
||||
Fedora~14\footnote{Прим. перев.: к сожалению, разработчики Fedora приняли
|
||||
решение оставить в Fedora~14 в качестве системы инициалиазции по умолчанию
|
||||
решение оставить в Fedora~14 в качестве системы инициализации по умолчанию
|
||||
upstart, однако systemd все равно будет включен в этот релиз и может быть
|
||||
использован в качестве альтернативной системы инициализации}. Помимо Fedora,
|
||||
systemd также поддерживает и другие дистрибутивы, в частности,
|
||||
@@ -56,27 +61,27 @@ systemd предоставляет администраторам целый р
|
||||
мы будем рассматривать ключевые новшества systemd, что может потребовать
|
||||
несколько более подробного изложения.
|
||||
\begin{flushright}
|
||||
Lennart P\"{o}ttering, 23 августа 2010
|
||||
Lennart P\"{o}ttering, 23 августа 2010~г.
|
||||
\end{flushright}
|
||||
|
||||
\section{Контроль процесса загрузки}
|
||||
Как правило, во время загрузки Linux по экрану быстро пробегает огромное
|
||||
количество различных сообщений. Так как мы интенсивно работаем над
|
||||
параллелизацией и ускорением процесса загрузки, с каждой новой верисей
|
||||
параллелизацией и ускорением процесса загрузки, с каждой новой версией
|
||||
systemd эти сообщения будут пробегать все быстрее и быстрее, вследствие чего,
|
||||
читать их будет все труднее. К тому же, многие пользователи применяют
|
||||
графические оболочки загрузки (например, Plymouth), полностью скрывающие эти
|
||||
сообщения. Тем не~менее, информация, которую несут эти сообщения, была и
|
||||
остается чрезвычайно важной — они показывают, успешно ли запустилась каждая
|
||||
остается чрезвычайно важной~--- они показывают, успешно ли запустилась каждая
|
||||
служба, или попытка ее запуска закончилась ошибкой (зеленое
|
||||
\texttt{[~\textcolor{green}{OK}~]} или красное
|
||||
\texttt{[~\textcolor{red}{FAILED}~]} соответственно). Итак, с ростом скорости
|
||||
загрузки систем, возникает неприятная ситуация: информация о результатах
|
||||
запуска служб бывает очень важна, а просматривать ее все тяжелее. systemd
|
||||
предлагает выход из этой ситуации: он отслеживает и запоминает факты успешного
|
||||
или неудачного запуска служб на этапе загрузки, а такжи сбои служб во время
|
||||
или неудачного запуска служб на этапе загрузки, а также сбои служб во время
|
||||
работы. К таким случая относятся выходы с ненулевым кодом, ошибки
|
||||
сегментирования и т.п. Введя systemctl status в своей командной оболочке, вы
|
||||
сегментирования и т.п. Введя +systemctl status+ в своей командной оболочке, вы
|
||||
можете ознакомиться с состоянием всех служб, как <<родных>> (native) для
|
||||
systemd, так и классических SysV/LSB служб, поддерживаемых в целях
|
||||
совместимости:
|
||||
@@ -179,7 +184,7 @@ JOB = Pending job for the unit.
|
||||
Обратите внимание на графу ACTIVE, в которой отображается обобщенный статус
|
||||
службы (или любого другого юнита systemd: устройства, сокета, точки
|
||||
монтирования~--- их мы рассмотрим подробнее в последующих статьях). Основными
|
||||
значениями обощенного статуса являются active (служба выполняется) и inactive
|
||||
значениями обобщенного статуса являются active (служба выполняется) и inactive
|
||||
(служба не~была запущена). Также существуют и другие статусы. Например,
|
||||
внимательно посмотрев на листинг выше, вы можете заметить, что служба ntpd
|
||||
(сервер точного времени) находится в состоянии, обозначенном как maintenance.
|
||||
@@ -200,12 +205,12 @@ systemd сообщает нам, что ntpd был запущен (с иден
|
||||
|
||||
В последующих версиях systemd, мы планируем добавить возможность вызова в
|
||||
таких ситуациях ABRT (Automated Bug Report Tool), но для этого необходима
|
||||
соответствующая поддержка со стороны самого ABRT. Соответствующий запрос уже
|
||||
поддержка со стороны самого ABRT. Соответствующий запрос уже
|
||||
\href{https://bugzilla.redhat.com/show_bug.cgi?id=622773}{направлен} его
|
||||
разработчикам, однако пока не~встретил среди них поддержки.
|
||||
|
||||
Резюме: использование +systemctl+ и +systemctl status+ представляет современную,
|
||||
более удобную и эффективную альтернативу разглядыванию быстро пробегающих по
|
||||
Резюме: использование +systemctl+ и +systemctl status+ является современной,
|
||||
более удобной и эффективной альтернативой разглядыванию быстро пробегающих по
|
||||
экрану сообщений в классическом SysV. +systemctl status+ дает возможность
|
||||
получить развернутую информацию о характере ошибки и, кроме того, в отличие
|
||||
от сообщений SysV, показывает не~только ошибки при запуске, но и ошибки,
|
||||
@@ -216,7 +221,7 @@ systemd сообщает нам, что ntpd был запущен (с иден
|
||||
процессов обычно весьма значительно. Понять, откуда взялся и что делает тот
|
||||
или иной процесс, становится все сложнее и сложнее. Многие службы используют
|
||||
сразу несколько рабочих процессов, и это отнюдь не~всегда можно легко
|
||||
распознать по выводу команды ps. Встречаются еще более сложные ситуации,
|
||||
распознать по выводу команды +ps+. Встречаются еще более сложные ситуации,
|
||||
когда демон запускает сторонние процессы~--- например, веб-сервер выполняет
|
||||
CGI-программы, а демон cron~--- команды, предписанные ему в crontab.
|
||||
|
||||
@@ -225,9 +230,9 @@ CGI-программы, а демон cron~--- команды, предписа
|
||||
полностью. В частности, процессы, родители которых умирают раньше их самих,
|
||||
становят потомками PID~1 (процесса init), что сразу затрудняет процесс
|
||||
выяснения их происхождения. Кроме того, процесс может избавиться от связи с
|
||||
родителем через две последовательные операции +fork()+ (В целом, эта возможность
|
||||
родителем через две последовательные операции +fork()+ (в целом, эта возможность
|
||||
признается нужной и полезной, и является частью используемого в Unix подхода
|
||||
к разработке демонов.) Также, не~будем забывать, что процесс легко может
|
||||
к разработке демонов). Также, не~будем забывать, что процесс легко может
|
||||
изменить свое имя посредством +PR_SETNAME+, или задав значение
|
||||
+argv[0]+, что также усложняет процесс его опознания\footnote{Прим.
|
||||
перев.: стоит отметить, что перечисленные ситуации могут возникнуть не~только
|
||||
@@ -236,7 +241,7 @@ CGI-программы, а демон cron~--- команды, предписа
|
||||
взломанном сервере процесс-бэкдор маскируется под нормального демона, меняя
|
||||
себе имя, скажем, на httpd}.
|
||||
|
||||
systemd предоставляет простой путь для решения обсуждаемой задачи. Запуская
|
||||
systemd предлагает простой путь для решения обсуждаемой задачи. Запуская
|
||||
очередной новый процесс, systemd помещает его в отдельную контрольную группу
|
||||
с соответствующим именем. Контрольные группы Linux предоставляют очень
|
||||
удобный инструмент для иерархической структуризации процессов: когда
|
||||
@@ -247,13 +252,13 @@ systemd предоставляет простой путь для решения
|
||||
процесса, вне зависимости от того, сколько раз он форкался и переименовывал
|
||||
себя~--- имя его контрольной группы невозможно спрятать или изменить. Кроме
|
||||
того, при штатном завершении родительской службы, будут завершены и все
|
||||
порожденные ею процессы, как бы они ни пытались сбежать. С systemd уже
|
||||
порожденные ею процессы, как бы они ни~пытались сбежать. С systemd уже
|
||||
невозможна ситуация, когда после остановки web-сервера, некорректно
|
||||
форкнувшийся CGI-процесс продолжает исполняться вплоть до последних секунд
|
||||
работы системы.
|
||||
|
||||
В этой статье мы рассмотрим две простых команды, которые позволят вам
|
||||
наглядно увидеть схему взаимоотношений systemd и порожденных им процессов.
|
||||
наглядно оценить схему взаимоотношений systemd и порожденных им процессов.
|
||||
Первая из этих команд~--- все та же +ps+, однако на этот раз в ее параметры
|
||||
добавлено указание выводить сведения по контрольным группам, а также другую
|
||||
интересную информацию:
|
||||
@@ -380,14 +385,14 @@ $ ps xawf -eo pid,user,cgroup,args
|
||||
27285 lennart name=systemd:/user/lennart/1 /usr/libexec/telepathy-salut
|
||||
27297 lennart name=systemd:/user/lennart/1 /usr/libexec/geoclue-yahoo
|
||||
\end{Verbatim}
|
||||
(Данный листинг был сокращен за счет удаления из него строк, относящихся к
|
||||
потокам ядра, так как они никак не~относятся к обсуждаемой нами теме.)
|
||||
(Данный листинг был сокращен за счет удаления из него строк, описывающих
|
||||
потоки ядра, так как они никак не~относятся к обсуждаемой нами теме.)
|
||||
\end{landscape}
|
||||
|
||||
Обратите внимание на третий столбец, показывающий имя контрольной группы,
|
||||
которое systemd присваивает каждому процессу. Например, процесс +udev+
|
||||
находится в группе +name=systemd:/systemd-1/sysinit.service+. В эту группу
|
||||
помещаются процессы, запущенные службой +sysinit.service+, которая запускается
|
||||
входят процессы, порожденные службой +sysinit.service+, которая запускается
|
||||
на ранней стадии загрузки.
|
||||
|
||||
Вы можете очень сильно упростить себе работу, если назначите для
|
||||
@@ -398,9 +403,9 @@ alias psc='ps xawf -eo pid,user,cgroup,args'
|
||||
---~теперь для получения исчерпывающей информации по процессам достаточно будет
|
||||
нажать всего четыре клавиши.
|
||||
|
||||
Альтернативый способ получить ту же информацию~--- воспользоваться утилитой
|
||||
Альтернативный способ получить ту же информацию~--- воспользоваться утилитой
|
||||
+systemd-cgls+, входящей в комплект поставки systemd. Она отображает иерархию
|
||||
контрольных групп в виде превдографической диаграммы-дерева:
|
||||
контрольных групп в виде псевдографической диаграммы-дерева:
|
||||
|
||||
\begin{landscape}
|
||||
\begin{Verbatim}[fontsize=\small]
|
||||
@@ -564,11 +569,11 @@ $ systemd-cgls
|
||||
systemd именует группы в соответствии с названиями служб. Например, из
|
||||
приведенного листинга нетрудно понять, что служба системного аудита
|
||||
+auditd.service+ порождает три отдельных процесса: +auditd+,
|
||||
+audisp+ и +sedispatch+.
|
||||
+audispd+ и +sedispatch+.
|
||||
|
||||
Внимательно посмотрев на листинг, можно заметить, что некоторые процессы
|
||||
Наиболее внимательные читатели, вероятно, уже заметили, что некоторые процессы
|
||||
помещены в группу +/user/lennart/1+. Дело в том, что systemd занимается
|
||||
отслежванием и группировкой не~только процессов, относящихся к системным
|
||||
отслеживанием и группировкой не~только процессов, относящихся к системным
|
||||
службам, но и процессов, запущенных в рамках пользовательских сеансов. В
|
||||
последующих статьях мы обсудим этот вопрос более подробно.
|
||||
|
||||
@@ -588,14 +593,14 @@ shell-скрипты, как правило, отличается низкой
|
||||
Впрочем, нельзя не~упомянуть, что эти скрипты являются очень гибким
|
||||
инструментом (ведь, по сути, это всего лишь код, который можно модифицировать
|
||||
как угодно). С другой стороны, многие задачи, возникающие при работе со
|
||||
службами, бывает довольно тяжело решить средствами shell-скриптов. К таким
|
||||
задачам относятся: огранизация параллельного исполнения, корректное
|
||||
службами, довольно тяжело решить средствами shell-скриптов. К таким
|
||||
задачам относятся: организация параллельного исполнения, корректное
|
||||
отслеживание процессов, конфигурирование различных параметров среды исполнения
|
||||
процесса. systemd обеспечивает совместимость с init-скриптами, однако, с учетом
|
||||
описанных выше их недостатков, более правильным решением будет использование
|
||||
штатных service-файлов systemd для всех установленных в системе служб. Стоит
|
||||
отметить что, в отличие от init-скриптов, которые часто приходится
|
||||
модифицировать при переносе из одного дистриубтива в другой, один и тот же
|
||||
модифицировать при переносе из одного дистрибутива в другой, один и тот же
|
||||
service-файл будет работать в любом дистрибутиве, использующем systemd (а таких
|
||||
дистрибутивов с каждым днем становится все больше и больше). Далее мы вкратце
|
||||
рассмотрим процесс преобразования SysV init-скрипта в service-файл systemd.
|
||||
@@ -615,7 +620,7 @@ Bug Reporting Tool, службы, занимающейся сбором crash du
|
||||
|
||||
Начнем с того, что прочитаем исходный скрипт (неожиданный ход, правда?) и
|
||||
выделим полезную информацию из груды хлама. Практически у всех init-скриптов
|
||||
большая часть кода является чисто вспомогательной, и мало чем отличается от
|
||||
б\'{о}льшая часть кода является чисто вспомогательной, и мало чем отличается от
|
||||
одного скрипта к другому. Как правило, при создании новых скриптов этот код
|
||||
просто копируется из уже существующих (разработка в стиле copy-paste). Итак,
|
||||
в исследуемом скрипте нас интересует следующая информация:
|
||||
@@ -633,23 +638,23 @@ Bug Reporting Tool, службы, занимающейся сбором crash du
|
||||
комментариев соответствующих init-скриптов. Изначально эта
|
||||
схема была введена именно для того, чтобы стандартизировать
|
||||
init-скрипты во всех дистрибутивах. Однако разработчики
|
||||
многих дистрибутивов не~считают нужным точное исполнение
|
||||
требований LSB, и поэтому формы представления метаданных в
|
||||
многих дистрибутивов не~считают нужным точно исполнять
|
||||
требования LSB, и поэтому формы представления метаданных в
|
||||
различных дистрибутивах могут отличаться. Вследствие этого,
|
||||
при переносе init-скрипта из одного дистрибутива в другой,
|
||||
скрипт приходится модифицировать. Например, демон пересылки
|
||||
почты при описании зависимостей может именоваться
|
||||
+MTA+ или +smtpdaemon+ (Fedora), +smtp+
|
||||
(openSUSE), +mail-transport-agent+ (Debian и Ubuntu),
|
||||
+mail-transfer-agent+. Таким образом,
|
||||
стандарт LSB не~справляется с поставленной задачей},
|
||||
+mail-transfer-agent+. Таким образом, можно утверждать, что
|
||||
стандарт LSB не~справляется с возложенной на него задачей},
|
||||
содержащий информацию о зависимостях. systemd, базирующийся
|
||||
на идеях socket-активации, обычно не~требует явного описания
|
||||
зависимостей (либо требует самого минимального описания).
|
||||
Заметим, что основополагающие принципы systemd, включая
|
||||
socket-активацию, рассмотрены в статье
|
||||
\href{http://0pointer.de/blog/projects/systemd.html}{Rethinking
|
||||
PID 1}, в которой systemd был впервые представлен широкой
|
||||
PID~1}, в которой systemd был впервые представлен широкой
|
||||
публике. Ее русский перевод можно прочитать здесь:
|
||||
\href{http://tux-the-penguin.blogspot.com/2010/09/systemd.html}{часть~1},
|
||||
\href{http://tux-the-penguin.blogspot.com/2010/09/systemd-ii.html}{часть~2}.
|
||||
@@ -673,7 +678,7 @@ Bug Reporting Tool, службы, занимающейся сбором crash du
|
||||
(команды +echo+), разбор входных параметров (монструозный блок
|
||||
+case+).
|
||||
|
||||
На основе приведенной выше полезной информации, мы можем написать следующий
|
||||
На основе приведенной выше информации, мы можем написать следующий
|
||||
service-файл:
|
||||
\begin{Verbatim}
|
||||
[Unit]
|
||||
@@ -690,7 +695,7 @@ WantedBy=multi-user.target
|
||||
|
||||
Рассмотрим этот файл поподробнее.
|
||||
|
||||
Секция +[Unit]+ содежит самую общую информацию о службе. Не будем
|
||||
Секция +[Unit]+ содержит самую общую информацию о службе. Не~будем
|
||||
забывать, что systemd управляет не~только службами, но и многими другими
|
||||
объектами, в частности, устройствами, точками монтирования, таймерами и т.п.
|
||||
Общее наименование всех этих объектов~--- юнит (unit). Одноименная секция
|
||||
@@ -708,10 +713,10 @@ WantedBy=multi-user.target
|
||||
использующими устаревшие реализации демона системного лога}. Эта информация,
|
||||
как мы помним, была указана в LSB-заголовке исходного init-скрипта. В нашем
|
||||
конфигурационном файле мы указываем зависимость от демона системного лога при
|
||||
помощи директивы +After+, ссылающейся на юнит +syslog.taget+. Это
|
||||
помощи директивы +After+, указывающей на юнит +syslog.taget+. Это
|
||||
специальный юнит, позволяющий ссылаться на любую реализацию демона системного
|
||||
лога, независимо от используемой программы (например, rsyslog или syslog-ng)
|
||||
и типа активации (как обычной службы или через log-сокет). Подробнее о таки
|
||||
и типа активации (как обычной службы или через log-сокет). Подробнее о таких
|
||||
специальных юнитах можно почитать
|
||||
\href{http://0pointer.de/public/systemd-man/systemd.special.html}{страницу}
|
||||
официальной документации. Обратите внимание, что директива +After+, в
|
||||
@@ -726,8 +731,8 @@ systemd будет предписывать запуск как демона с
|
||||
+Requires+, задающей жесткую зависимость между юнитами.
|
||||
|
||||
Следующая секция, +[Service]+, содержит информацию о службе. Сюда включаются
|
||||
настройки, относящие именно к службам, но не~к другим типа юнитов. В нашем
|
||||
случае, таких настроек две: +ExecStart+ определяет расположение бинарника
|
||||
настройки, относящие именно к службам, но не~к другим типам юнитов. В нашем
|
||||
случае, таких настроек две: +ExecStart+, определяющая расположение бинарника
|
||||
демона и аргументы, с которыми он будет вызван (в нашем случае они
|
||||
отсутствуют), и +Type+, позволяющая задать метод, по которому systemd определит
|
||||
окончание периода запуска службы. Традиционный для Unix метод демонизации
|
||||
@@ -745,7 +750,7 @@ systemd считает службу запущенной с момента за
|
||||
котором он используется в большинстве дистрибутивов семейства Red Hat, а
|
||||
именно, многопользовательский режим без запуска графической оболочки}.
|
||||
Директива +WantedBy+ никак не~влияет на уже работающую службу, но она
|
||||
играет важную роль при выполнении команды systemctl enable, задавая, в каких
|
||||
играет важную роль при выполнении команды +systemctl enable+, задавая, в каких
|
||||
условиях должен активироваться устанавливаемый юнит. В нашем примере, служба
|
||||
abrtd будет активироваться при переходе в состояние +multi-user.target+,
|
||||
т.е., при каждой нормальной загрузке\footnote{Обратите внимание, что режим
|
||||
@@ -755,7 +760,7 @@ abrtd будет активироваться при переходе в сос
|
||||
образом, все службы, запускаемые в режиме +multi-user.target+, будут
|
||||
также запускаться и в режиме +graphical.target+} (к <<ненормальным>>
|
||||
можно отнести, например, загрузки в режиме +emergency.target+, который
|
||||
является аналогом первого уровня исполнения В классической SysV).
|
||||
является аналогом первого уровня исполнения в классической SysV).
|
||||
|
||||
Вот и все. Мы получили минимальный рабочий service-файл systemd. Чтобы
|
||||
проверить его работоспособность, скопируем его в
|
||||
@@ -771,7 +776,8 @@ abrtd будет активироваться при переходе в сос
|
||||
|
||||
Приведенный выше service-файл является практический точным переводом
|
||||
исходного init-скрипта, и он никак не~использует широкий спектр возможностей,
|
||||
предоставляемых systemd. Ниже приведен немного улучшенный вариант:
|
||||
предоставляемых systemd. Ниже приведен немного улучшенный вариант этого же
|
||||
файла:
|
||||
|
||||
\begin{Verbatim}
|
||||
[Unit]
|
||||
@@ -788,14 +794,14 @@ WantedBy=multi-user.target
|
||||
\end{Verbatim}
|
||||
|
||||
Чем же новый вариант отличается от предыдущего? Ну, прежде всего, мы уточнили
|
||||
описание службы. Однако, ключевым изменением является замена +Type+ с +forking+
|
||||
описание службы. Однако, ключевым изменением является замена значения +Type+ с +forking+
|
||||
на +dbus+ и связанные с ней изменения: добавление имени службы в шине D-Bus
|
||||
(директива +BusName+) и задание полонительных аргументов abrtd <<+-d -s+>>. Но
|
||||
(директива +BusName+) и задание дополнительных аргументов abrtd <<+-d -s+>>. Но
|
||||
зачем вообще нужна эта замена? Каков ее практический смысл? Чтобы ответить на
|
||||
этот вопрос, мы снова возращаемся к демонизации. В ходе этой операции, процесс
|
||||
этот вопрос, мы снова возвращаемся к демонизации. В ходе этой операции процесс
|
||||
дважды форкается и отключается от всех терминалов. Это очень удобно при запуске
|
||||
демона через скрипт, но в случае использования таких продвинутых систем
|
||||
инициализации, как systemd, такое поведение не~дает никаких преимуществ, но
|
||||
инициализации, как systemd, подобное поведение не~дает никаких преимуществ, но
|
||||
вызывает неоправданные задержки. Даже если мы оставим в стороне вопрос скорости
|
||||
загрузки, останется такой важный аспект, как отслеживание состояния служб.
|
||||
systemd решает и эту задачу, контролируя работу службы и при необходимости
|
||||
@@ -805,14 +811,14 @@ systemd решает и эту задачу, контролируя работу
|
||||
службу, либо активировать какой-либо заранее заданный юнит. Операция
|
||||
демонизации несколько затрудняет решение этих задач, так как обычно довольно
|
||||
сложно найти связь демонизированного процесса с исходным (собственно, смысл
|
||||
демонизации как раз и сводится к уничтожению этой связи) и, сооветственно, для
|
||||
демонизации как раз и сводится к уничтожению этой связи) и, соответственно, для
|
||||
systemd сложнее определить, какой из порожденных в рамках данной службы
|
||||
процессов является основным. Чтобы упростить для него решение этой задачи, мы и
|
||||
воспользовались типом запуска +dbus+. Он подходит для всех служб, которые в
|
||||
конце процесса инициализации регистрируют свое имя на шине D-Bus\footnote{В
|
||||
настоящее время практически все службы дистрибутива Fedora после запуска
|
||||
регистрируется на шине D-Bus}. ABRTd относится к ним. С новыми настройками,
|
||||
systemd запусит процесс abrtd, который уже не~будет форкаться (согласно
|
||||
systemd запустит процесс abrtd, который уже не~будет форкаться (согласно
|
||||
указанным нами ключам <<+-d -s+>>), и в качестве момента окончания периода
|
||||
запуска данной службы systemd будет рассматривать момент регистрации имени
|
||||
+com.redhat.abrt+ на шине D-Bus. В этом случае основным для данной службы будет
|
||||
@@ -830,7 +836,7 @@ systemd запусит процесс abrtd, который уже не~буде
|
||||
падения. Или, например, добавив +OOMScoreAdjust=-500+, мы попросим ядро сберечь
|
||||
эту службу, даже если OOM Killer выйдет на тропу войны. А если мы добавим
|
||||
строчку +CPUSchedulingPolicy=idle+, процесс abrtd будет работать только в те
|
||||
моменты, когда система больше ничем не~занята, что позволит не создавать помех
|
||||
моменты, когда система больше ничем не~занята, что позволит не~создавать помех
|
||||
для процессов, активно использующих CPU.
|
||||
|
||||
За более подробным описанием всех опций настройки, вы можете обратиться к
|
||||
@@ -846,28 +852,28 @@ service-файлы. Но, к счастью, <<проблемных>> скрип
|
||||
|
||||
\section{Убить демона}
|
||||
|
||||
Убить системного демона нетрудно, правда? Или\ldots все не~так просто?
|
||||
Убить системного демона нетрудно, правда? Или\ldots{} все не~так просто?
|
||||
|
||||
Если ваш демон функционирует как один процесс, все действительно очень просто.
|
||||
Вы командуете +killall rsyslogd+, и демон системного лога останавливается.
|
||||
Впрочем, этот метод не~вполне корректен, так как он действует не~только на
|
||||
самого демона, но и на другие процессы с тем же именем. Иногда подобное
|
||||
поведение может привести к неприятным последствиям. Более правильным будет
|
||||
использование pid-файла: +kill \$(cat /var/run/syslogd.pid)+. Вот, вроде
|
||||
бы, и все, что вам нужно\ldots Или мы упускаем еще что-то?
|
||||
использование pid-файла: +kill $(cat /var/run/syslogd.pid)$+. Вот, вроде
|
||||
бы, и все, что вам нужно\ldots{} Или мы упускаем еще что-то?
|
||||
|
||||
Действительно, мы забываем про одну простую вещь: существуют службы, такие, как
|
||||
Apache, crond, atd, которые по роду служебной дейятельности должны запускать
|
||||
дочерние процессы. Это могут быть совершенно посторонние, указаанные
|
||||
Действительно, мы забываем одну простую вещь: существуют службы, такие, как
|
||||
Apache, crond, atd, которые по роду служебной деятельности должны запускать
|
||||
дочерние процессы. Это могут быть совершенно посторонние, указанные
|
||||
пользователем программы (например, задачи cron/at, CGI-скрипты) или полноценные
|
||||
серверные процессы (например, Apache workers). Когда вы убиваете основной
|
||||
процесс, он может остановить все дочерние процессы. А может и не~остановить. В
|
||||
самом деле, если служба функционирует в штатном режиме, ее обычно останавливают
|
||||
специальной командой stop. К прямому вызову kill администратор, как правило,
|
||||
командой +stop+. К прямому вызову +kill+ администратор, как правило,
|
||||
прибегает только в аварийной ситуации, когда служба работает неправильно и
|
||||
может не~среагировать на стандартную команду остановки. Таким образом, убив,
|
||||
например, основной сервер Apache, вы можете получить от него в наследство
|
||||
работающие CGI-скрипты, причем их родителем автоматически станет PID 1 (init),
|
||||
работающие CGI-скрипты, причем их родителем автоматически станет PID~1 (init),
|
||||
так что установить их происхождение будет не~так-то просто.
|
||||
|
||||
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd} спешит к нам
|
||||
@@ -903,10 +909,10 @@ Apache, crond, atd, которые по роду служебной дейяте
|
||||
|
||||
В некоторый случах возникает необходимость отправить сигнал именно основному
|
||||
процессу службы. Например, используя +SIGHUP+, мы можем заставить демона
|
||||
перечитать файлы конфигурации. Разумеется, вспомогательным процессам
|
||||
передавать HUP в этом случае совершенно необязательно. Для решения этой
|
||||
задачи вполbb неплохо подойдет и классический метод с pid-файлом, однако у
|
||||
systemd и на этот случай есть просто решение, избавляющее вас от
|
||||
перечитать файлы конфигурации. Разумеется, передавать HUP вспомогательным процессам
|
||||
в этом случае совершенно необязательно. Для решения подобной
|
||||
задачи неплохо подойдет и классический метод с pid-файлом, однако у
|
||||
systemd и на этот случай есть простое решение, избавляющее вас от
|
||||
необходимости искать нужный файл:
|
||||
|
||||
\begin{Verbatim}
|
||||
@@ -925,9 +931,9 @@ systemd и на этот случай есть просто решение, из
|
||||
После прочтения сказанного выше у вас может возникнуть вопрос: в чем разница
|
||||
между +systemctl kill+ и +systemctl stop+? Отличие состоит в том,
|
||||
что +kill+ просто отправляет сигнал заданному процессу, в то время как
|
||||
stop действует по <<официально>> определенному методу, вызывая команду,
|
||||
+stop+ действует по <<официально>> определенному методу, вызывая команду,
|
||||
определенную в параметре +ExecStop+ конфигурации службы. Обычно команды
|
||||
stop бывает вполне достаточно для остановки службы, и к +kill+
|
||||
+stop+ бывает вполне достаточно для остановки службы, и к +kill+
|
||||
приходится прибегать только в крайних случаях, например, когда служба
|
||||
<<зависла>> и не~реагирует на команды.
|
||||
|
||||
@@ -940,4 +946,518 @@ stop бывает вполне достаточно для остановки с
|
||||
инструментов, позволяющих корректно отправить сигнал службе в целом, а
|
||||
не~отдельному процессу.
|
||||
|
||||
\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 секунд.
|
||||
Казалось бы, смысл этого числа вполне очевиден, однако не~стоит делать поспешных
|
||||
выводов. Прежде всего, в нем не~учитывается время, затраченное на инициализацию
|
||||
вашего сеанса в 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}
|
||||
|
||||
\end{document}
|
||||
|
||||
vim:ft=tex:tw=80:spell:spelllang=ru
|
||||
|
||||
Reference in New Issue
Block a user