950 lines
78 KiB
TeX
950 lines
78 KiB
TeX
\documentclass[10pt,oneside,a4paper]{article}
|
||
\usepackage{cmap} % Copy-paste из PDF без проблем с кодировкой
|
||
\usepackage[utf8]{inputenc}
|
||
\usepackage[english,russian]{babel} % Русские переносы и проч.
|
||
\usepackage{graphicx,color}
|
||
\usepackage[T1,T2A]{fontenc}
|
||
\usepackage{indentfirst} % Отступ в первом абзаце главы
|
||
\usepackage{fancyvrb} % Продвинутые листинги и in-line commands
|
||
% listings для данной ситуации, имхо, избыточен
|
||
\usepackage{pdflscape} % Внимание! При выводе в DVI выборочный
|
||
% поворот страниц работать не будет, хотя текст будет повернут.
|
||
\usepackage[colorlinks,unicode,urlcolor=blue]{hyperref}
|
||
% Заполняем поля PDF уже со включенной опцией unicode
|
||
\hypersetup{pdftitle={systemd для администраторов},%
|
||
pdfauthor={Lennart Poettering, Sergey Ptashnick}}
|
||
% Небольшое сокращение
|
||
\newcommand{\sectiona}[1]{\section*{#1}\addcontentsline{toc}{section}{#1}}
|
||
% Настройка макета страницы
|
||
\setlength{\hoffset}{-1.5cm}
|
||
\addtolength{\textwidth}{2cm}
|
||
\setlength{\voffset}{-2cm}
|
||
\addtolength{\textheight}{3cm}
|
||
\addtolength{\footskip}{5pt}
|
||
% Настройка форматирования in-line commands
|
||
\DefineShortVerb{\+}
|
||
\VerbatimFootnotes
|
||
% И листингов
|
||
\definecolor{gray}{gray}{0.75}
|
||
\fvset{frame=leftline,rulecolor=\color{gray},framerule=1mm}
|
||
% Запрет висячих строк
|
||
\clubpenalty=10000
|
||
\widowpenalty=10000
|
||
|
||
\begin{document}
|
||
\sloppy
|
||
\title{systemd для администраторов}
|
||
\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
|
||
\sectiona{Предисловие автора}
|
||
Многие из вас, наверное, уже знают, что
|
||
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd}~--- это
|
||
новая система инициализации дистрибутива Fedora, начиная с
|
||
Fedora~14\footnote{Прим. перев.: к сожалению, разработчики Fedora приняли
|
||
решение оставить в Fedora~14 в качестве системы инициализации по умолчанию
|
||
upstart, однако systemd все равно будет включен в этот релиз и может быть
|
||
использован в качестве альтернативной системы инициализации}. Помимо Fedora,
|
||
systemd также поддерживает и другие дистрибутивы, в частности,
|
||
\href{http://en.opensuse.org/SDB:Systemd}{OpenSUSE}.
|
||
systemd предоставляет администраторам целый ряд новых возможностей,
|
||
значительно упрощающих процесс обслуживания системы. Эта статья является
|
||
первой в серии публикаций, планируемых в ближайшие месяцы. В каждой из этих
|
||
статей я попытаюсь рассказать об очередной новой возможности systemd.
|
||
Большинство этих возможностей можно описать легко и просто, и подобные статьи
|
||
должны быть интересны довольно широкой аудитории. Однако, время от времени
|
||
мы будем рассматривать ключевые новшества systemd, что может потребовать
|
||
несколько более подробного изложения.
|
||
\begin{flushright}
|
||
Lennart P\"{o}ttering, 23 августа 2010~г.
|
||
\end{flushright}
|
||
|
||
\section{Контроль процесса загрузки}
|
||
Как правило, во время загрузки Linux по экрану быстро пробегает огромное
|
||
количество различных сообщений. Так как мы интенсивно работаем над
|
||
параллелизацией и ускорением процесса загрузки, с каждой новой версией
|
||
systemd эти сообщения будут пробегать все быстрее и быстрее, вследствие чего,
|
||
читать их будет все труднее. К тому же, многие пользователи применяют
|
||
графические оболочки загрузки (например, Plymouth), полностью скрывающие эти
|
||
сообщения. Тем не~менее, информация, которую несут эти сообщения, была и
|
||
остается чрезвычайно важной~--- они показывают, успешно ли запустилась каждая
|
||
служба, или попытка ее запуска закончилась ошибкой (зеленое
|
||
\texttt{[~\textcolor{green}{OK}~]} или красное
|
||
\texttt{[~\textcolor{red}{FAILED}~]} соответственно). Итак, с ростом скорости
|
||
загрузки систем, возникает неприятная ситуация: информация о результатах
|
||
запуска служб бывает очень важна, а просматривать ее все тяжелее. systemd
|
||
предлагает выход из этой ситуации: он отслеживает и запоминает факты успешного
|
||
или неудачного запуска служб на этапе загрузки, а также сбои служб во время
|
||
работы. К таким случая относятся выходы с ненулевым кодом, ошибки
|
||
сегментирования и т.п. Введя +systemctl status+ в своей командной оболочке, вы
|
||
можете ознакомиться с состоянием всех служб, как <<родных>> (native) для
|
||
systemd, так и классических SysV/LSB служб, поддерживаемых в целях
|
||
совместимости:
|
||
|
||
\begin{landscape}
|
||
\begin{Verbatim}[fontsize=\small]
|
||
[root@lambda] ~# systemctl
|
||
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
|
||
dev-hugepages.automount loaded active running Huge Pages File System Automount Point
|
||
dev-mqueue.automount loaded active running POSIX Message Queue File System Automount Point
|
||
proc-sys-fs-binfmt_misc.automount loaded active waiting Arbitrary Executable File Formats File System Automount Point
|
||
sys-kernel-debug.automount loaded active waiting Debug File System Automount Point
|
||
sys-kernel-security.automount loaded active waiting Security File System Automount Point
|
||
sys-devices-pc...0000:02:00.0-net-eth0.device loaded active plugged 82573L Gigabit Ethernet Controller
|
||
[...]
|
||
sys-devices-virtual-tty-tty9.device loaded active plugged /sys/devices/virtual/tty/tty9
|
||
-.mount loaded active mounted /
|
||
boot.mount loaded active mounted /boot
|
||
dev-hugepages.mount loaded active mounted Huge Pages File System
|
||
dev-mqueue.mount loaded active mounted POSIX Message Queue File System
|
||
home.mount loaded active mounted /home
|
||
proc-sys-fs-binfmt_misc.mount loaded active mounted Arbitrary Executable File Formats File System
|
||
abrtd.service loaded active running ABRT Automated Bug Reporting Tool
|
||
accounts-daemon.service loaded active running Accounts Service
|
||
acpid.service loaded active running ACPI Event Daemon
|
||
atd.service loaded active running Execution Queue Daemon
|
||
auditd.service loaded active running Security Auditing Service
|
||
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
|
||
bluetooth.service loaded active running Bluetooth Manager
|
||
console-kit-daemon.service loaded active running Console Manager
|
||
cpuspeed.service loaded active exited LSB: processor frequency scaling support
|
||
crond.service loaded active running Command Scheduler
|
||
cups.service loaded active running CUPS Printing Service
|
||
dbus.service loaded active running D-Bus System Message Bus
|
||
getty@tty2.service loaded active running Getty on tty2
|
||
getty@tty3.service loaded active running Getty on tty3
|
||
getty@tty4.service loaded active running Getty on tty4
|
||
getty@tty5.service loaded active running Getty on tty5
|
||
getty@tty6.service loaded active running Getty on tty6
|
||
haldaemon.service loaded active running Hardware Manager
|
||
hdapsd@sda.service loaded active running sda shock protection daemon
|
||
irqbalance.service loaded active running LSB: start and stop irqbalance daemon
|
||
iscsi.service loaded active exited LSB: Starts and stops login and scanning of iSCSI devices.
|
||
iscsid.service loaded active exited LSB: Starts and stops login iSCSI daemon.
|
||
livesys-late.service loaded active exited LSB: Late init script for live image.
|
||
livesys.service loaded active exited LSB: Init script for live image.
|
||
lvm2-monitor.service loaded active exited LSB: Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
|
||
mdmonitor.service loaded active running LSB: Start and stop the MD software RAID monitor
|
||
modem-manager.service loaded active running Modem Manager
|
||
netfs.service loaded active exited LSB: Mount and unmount network filesystems.
|
||
NetworkManager.service loaded active running Network Manager
|
||
ntpd.service loaded maintenance maintenance Network Time Service
|
||
polkitd.service loaded active running Policy Manager
|
||
prefdm.service loaded active running Display Manager
|
||
rc-local.service loaded active exited /etc/rc.local Compatibility
|
||
rpcbind.service loaded active running RPC Portmapper Service
|
||
rsyslog.service loaded active running System Logging Service
|
||
rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy Service
|
||
sendmail.service loaded active running LSB: start and stop sendmail
|
||
sshd@172.31.0.53:22-172.31.0.4:36368.service loaded active running SSH Per-Connection Server
|
||
sysinit.service loaded active running System Initialization
|
||
systemd-logger.service loaded active running systemd Logging Daemon
|
||
udev-post.service loaded active exited LSB: Moves the generated persistent udev rules to /etc/udev/rules.d
|
||
udisks.service loaded active running Disk Manager
|
||
upowerd.service loaded active running Power Manager
|
||
wpa_supplicant.service loaded active running Wi-Fi Security Service
|
||
avahi-daemon.socket loaded active listening Avahi mDNS/DNS-SD Stack Activation Socket
|
||
cups.socket loaded active listening CUPS Printing Service Sockets
|
||
dbus.socket loaded active running dbus.socket
|
||
rpcbind.socket loaded active listening RPC Portmapper Socket
|
||
sshd.socket loaded active listening sshd.socket
|
||
systemd-initctl.socket loaded active listening systemd /dev/initctl Compatibility Socket
|
||
systemd-logger.socket loaded active running systemd Logging Socket
|
||
systemd-shutdownd.socket loaded active listening systemd Delayed Shutdown Socket
|
||
dev-disk-by\x1...x1db22a\x1d870f1adf2732.swap loaded active active /dev/disk/by-uuid/fd626ef7-34a4-4958-b22a-870f1adf2732
|
||
basic.target loaded active active Basic System
|
||
bluetooth.target loaded active active Bluetooth
|
||
dbus.target loaded active active D-Bus
|
||
getty.target loaded active active Login Prompts
|
||
graphical.target loaded active active Graphical Interface
|
||
local-fs.target loaded active active Local File Systems
|
||
multi-user.target loaded active active Multi-User
|
||
network.target loaded active active Network
|
||
remote-fs.target loaded active active Remote File Systems
|
||
sockets.target loaded active active Sockets
|
||
swap.target loaded active active Swap
|
||
sysinit.target loaded active active System Initialization
|
||
|
||
LOAD = Reflects whether the unit definition was properly loaded.
|
||
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
|
||
SUB = The low-level unit activation state, values depend on unit type.
|
||
JOB = Pending job for the unit.
|
||
|
||
221 units listed. Pass --all to see inactive units, too.
|
||
[root@lambda] ~#
|
||
\end{Verbatim}
|
||
(Листинг был сокращен за счет удаления строк, не~относящихся к теме статьи.)
|
||
\end{landscape}
|
||
|
||
Обратите внимание на графу ACTIVE, в которой отображается обобщенный статус
|
||
службы (или любого другого юнита systemd: устройства, сокета, точки
|
||
монтирования~--- их мы рассмотрим подробнее в последующих статьях). Основными
|
||
значениями обобщенного статуса являются active (служба выполняется) и inactive
|
||
(служба не~была запущена). Также существуют и другие статусы. Например,
|
||
внимательно посмотрев на листинг выше, вы можете заметить, что служба ntpd
|
||
(сервер точного времени) находится в состоянии, обозначенном как maintenance.
|
||
Чтобы узнать, что же произошло с ntpd, воспользуемся командой
|
||
+systemctl status+:
|
||
\begin{Verbatim}[commandchars=\\\{\}]
|
||
[root@lambda] ~# systemctl status ntpd.service
|
||
ntpd.service - Network Time Service
|
||
Loaded: loaded (/etc/systemd/system/ntpd.service)
|
||
Active: \textcolor{red}{maintenance}
|
||
Main: 953 (code=exited, status=255)
|
||
CGroup: name=systemd:/systemd-1/ntpd.service
|
||
[root@lambda] ~#
|
||
\end{Verbatim}
|
||
|
||
systemd сообщает нам, что ntpd был запущен (с идентификатором процесса 953) и
|
||
аварийно завершил работу (с кодом выхода 255).
|
||
|
||
В последующих версиях systemd, мы планируем добавить возможность вызова в
|
||
таких ситуациях ABRT (Automated Bug Report Tool), но для этого необходима
|
||
поддержка со стороны самого ABRT. Соответствующий запрос уже
|
||
\href{https://bugzilla.redhat.com/show_bug.cgi?id=622773}{направлен} его
|
||
разработчикам, однако пока не~встретил среди них поддержки.
|
||
|
||
Резюме: использование +systemctl+ и +systemctl status+ является современной,
|
||
более удобной и эффективной альтернативой разглядыванию быстро пробегающих по
|
||
экрану сообщений в классическом SysV. +systemctl status+ дает возможность
|
||
получить развернутую информацию о характере ошибки и, кроме того, в отличие
|
||
от сообщений SysV, показывает не~только ошибки при запуске, но и ошибки,
|
||
возникшие во время исполнения службы.
|
||
|
||
\section{О службах и процессах}
|
||
В большинстве современных Linux-систем количество одновременно работающих
|
||
процессов обычно весьма значительно. Понять, откуда взялся и что делает тот
|
||
или иной процесс, становится все сложнее и сложнее. Многие службы используют
|
||
сразу несколько рабочих процессов, и это отнюдь не~всегда можно легко
|
||
распознать по выводу команды +ps+. Встречаются еще более сложные ситуации,
|
||
когда демон запускает сторонние процессы~--- например, веб-сервер выполняет
|
||
CGI-программы, а демон cron~--- команды, предписанные ему в crontab.
|
||
|
||
Немного помочь в решении этой проблемы может древовидная иерархия процессов,
|
||
отображаемая по команде +ps xaf+. Именно <<немного помочь>>, а не~решить
|
||
полностью. В частности, процессы, родители которых умирают раньше их самих,
|
||
становят потомками PID~1 (процесса init), что сразу затрудняет процесс
|
||
выяснения их происхождения. Кроме того, процесс может избавиться от связи с
|
||
родителем через две последовательные операции +fork()+ (в целом, эта возможность
|
||
признается нужной и полезной, и является частью используемого в Unix подхода
|
||
к разработке демонов). Также, не~будем забывать, что процесс легко может
|
||
изменить свое имя посредством +PR_SETNAME+, или задав значение
|
||
+argv[0]+, что также усложняет процесс его опознания\footnote{Прим.
|
||
перев.: стоит отметить, что перечисленные ситуации могут возникнуть не~только
|
||
вследствие ошибок в коде и/или конфигурации программ, но и в результате злого
|
||
умысла. Например, очень часто встречается ситуация, когда установленный на
|
||
взломанном сервере процесс-бэкдор маскируется под нормального демона, меняя
|
||
себе имя, скажем, на httpd}.
|
||
|
||
systemd предлагает простой путь для решения обсуждаемой задачи. Запуская
|
||
очередной новый процесс, systemd помещает его в отдельную контрольную группу
|
||
с соответствующим именем. Контрольные группы Linux предоставляют очень
|
||
удобный инструмент для иерархической структуризации процессов: когда
|
||
какой-либо процесс порождает потомка, этот потомок автоматически включается в
|
||
ту же группу, что и родитель. При этом, что очень важно, непривилегированные
|
||
процессы не~могут изменить свое положение в этой иерархии. Таким образом,
|
||
контрольные группы позволяют точно установить происхождение конкретного
|
||
процесса, вне зависимости от того, сколько раз он форкался и переименовывал
|
||
себя~--- имя его контрольной группы невозможно спрятать или изменить. Кроме
|
||
того, при штатном завершении родительской службы, будут завершены и все
|
||
порожденные ею процессы, как бы они ни~пытались сбежать. С systemd уже
|
||
невозможна ситуация, когда после остановки web-сервера, некорректно
|
||
форкнувшийся CGI-процесс продолжает исполняться вплоть до последних секунд
|
||
работы системы.
|
||
|
||
В этой статье мы рассмотрим две простых команды, которые позволят вам
|
||
наглядно оценить схему взаимоотношений systemd и порожденных им процессов.
|
||
Первая из этих команд~--- все та же +ps+, однако на этот раз в ее параметры
|
||
добавлено указание выводить сведения по контрольным группам, а также другую
|
||
интересную информацию:
|
||
|
||
\begin{landscape}
|
||
\begin{Verbatim}[fontsize=\small]
|
||
$ ps xawf -eo pid,user,cgroup,args
|
||
PID USER CGROUP COMMAND
|
||
2 root - [kthreadd]
|
||
3 root - \_ [ksoftirqd/0]
|
||
[...]
|
||
4281 root - \_ [flush-8:0]
|
||
1 root name=systemd:/systemd-1 /sbin/init
|
||
455 root name=systemd:/systemd-1/sysinit.service /sbin/udevd -d
|
||
28188 root name=systemd:/systemd-1/sysinit.service \_ /sbin/udevd -d
|
||
28191 root name=systemd:/systemd-1/sysinit.service \_ /sbin/udevd -d
|
||
1096 dbus name=systemd:/systemd-1/dbus.service /bin/dbus-daemon --system --address=systemd: --nofork --systemd-activation
|
||
1131 root name=systemd:/systemd-1/auditd.service auditd
|
||
1133 root name=systemd:/systemd-1/auditd.service \_ /sbin/audispd
|
||
1135 root name=systemd:/systemd-1/auditd.service \_ /usr/sbin/sedispatch
|
||
1171 root name=systemd:/systemd-1/NetworkManager.service /usr/sbin/NetworkManager --no-daemon
|
||
4028 root name=systemd:/systemd-1/NetworkManager.service \_ /sbin/dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf /var/run/dhclient-wlan0.pid -lf /var/lib/dhclient/dhclient-7d32a784-ede9-4cf6-9ee3-60edc0bce5ff-wlan0.lease -
|
||
1175 avahi name=systemd:/systemd-1/avahi-daemon.service avahi-daemon: running [epsilon.local]
|
||
1194 avahi name=systemd:/systemd-1/avahi-daemon.service \_ avahi-daemon: chroot helper
|
||
1193 root name=systemd:/systemd-1/rsyslog.service /sbin/rsyslogd -c 4
|
||
1195 root name=systemd:/systemd-1/cups.service cupsd -C /etc/cups/cupsd.conf
|
||
1207 root name=systemd:/systemd-1/mdmonitor.service mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.pid
|
||
1210 root name=systemd:/systemd-1/irqbalance.service irqbalance
|
||
1216 root name=systemd:/systemd-1/dbus.service /usr/sbin/modem-manager
|
||
1219 root name=systemd:/systemd-1/dbus.service /usr/libexec/polkit-1/polkitd
|
||
1242 root name=systemd:/systemd-1/dbus.service /usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -B -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid
|
||
1249 68 name=systemd:/systemd-1/haldaemon.service hald
|
||
1250 root name=systemd:/systemd-1/haldaemon.service \_ hald-runner
|
||
1273 root name=systemd:/systemd-1/haldaemon.service \_ hald-addon-input: Listening on /dev/input/event3 /dev/input/event9 /dev/input/event1 /dev/input/event7 /dev/input/event2 /dev/input/event0 /dev/input/event8
|
||
1275 root name=systemd:/systemd-1/haldaemon.service \_ /usr/libexec/hald-addon-rfkill-killswitch
|
||
1284 root name=systemd:/systemd-1/haldaemon.service \_ /usr/libexec/hald-addon-leds
|
||
1285 root name=systemd:/systemd-1/haldaemon.service \_ /usr/libexec/hald-addon-generic-backlight
|
||
1287 68 name=systemd:/systemd-1/haldaemon.service \_ /usr/libexec/hald-addon-acpi
|
||
1317 root name=systemd:/systemd-1/abrtd.service /usr/sbin/abrtd -d -s
|
||
1332 root name=systemd:/systemd-1/getty@.service/tty2 /sbin/mingetty tty2
|
||
1339 root name=systemd:/systemd-1/getty@.service/tty3 /sbin/mingetty tty3
|
||
1342 root name=systemd:/systemd-1/getty@.service/tty5 /sbin/mingetty tty5
|
||
1343 root name=systemd:/systemd-1/getty@.service/tty4 /sbin/mingetty tty4
|
||
1344 root name=systemd:/systemd-1/crond.service crond
|
||
1346 root name=systemd:/systemd-1/getty@.service/tty6 /sbin/mingetty tty6
|
||
1362 root name=systemd:/systemd-1/sshd.service /usr/sbin/sshd
|
||
1376 root name=systemd:/systemd-1/prefdm.service /usr/sbin/gdm-binary -nodaemon
|
||
1391 root name=systemd:/systemd-1/prefdm.service \_ /usr/libexec/gdm-simple-slave --display-id /org/gnome/DisplayManager/Display1 --force-active-vt
|
||
1394 root name=systemd:/systemd-1/prefdm.service \_ /usr/bin/Xorg :0 -nr -verbose -auth /var/run/gdm/auth-for-gdm-f2KUOh/database -nolisten tcp vt1
|
||
1495 root name=systemd:/user/lennart/1 \_ pam: gdm-password
|
||
1521 lennart name=systemd:/user/lennart/1 \_ gnome-session
|
||
1621 lennart name=systemd:/user/lennart/1 \_ metacity
|
||
1635 lennart name=systemd:/user/lennart/1 \_ gnome-panel
|
||
1638 lennart name=systemd:/user/lennart/1 \_ nautilus
|
||
1640 lennart name=systemd:/user/lennart/1 \_ /usr/libexec/polkit-gnome-authentication-agent-1
|
||
1641 lennart name=systemd:/user/lennart/1 \_ /usr/bin/seapplet
|
||
1644 lennart name=systemd:/user/lennart/1 \_ gnome-volume-control-applet
|
||
1646 lennart name=systemd:/user/lennart/1 \_ /usr/sbin/restorecond -u
|
||
1652 lennart name=systemd:/user/lennart/1 \_ /usr/bin/devilspie
|
||
1662 lennart name=systemd:/user/lennart/1 \_ nm-applet --sm-disable
|
||
1664 lennart name=systemd:/user/lennart/1 \_ gnome-power-manager
|
||
1665 lennart name=systemd:/user/lennart/1 \_ /usr/libexec/gdu-notification-daemon
|
||
1670 lennart name=systemd:/user/lennart/1 \_ /usr/libexec/evolution/2.32/evolution-alarm-notify
|
||
1672 lennart name=systemd:/user/lennart/1 \_ /usr/bin/python /usr/share/system-config-printer/applet.py
|
||
1674 lennart name=systemd:/user/lennart/1 \_ /usr/lib64/deja-dup/deja-dup-monitor
|
||
1675 lennart name=systemd:/user/lennart/1 \_ abrt-applet
|
||
1677 lennart name=systemd:/user/lennart/1 \_ bluetooth-applet
|
||
1678 lennart name=systemd:/user/lennart/1 \_ gpk-update-icon
|
||
1408 root name=systemd:/systemd-1/console-kit-daemon.service /usr/sbin/console-kit-daemon --no-daemon
|
||
1419 gdm name=systemd:/systemd-1/prefdm.service /usr/bin/dbus-launch --exit-with-session
|
||
1453 root name=systemd:/systemd-1/dbus.service /usr/libexec/upowerd
|
||
1473 rtkit name=systemd:/systemd-1/rtkit-daemon.service /usr/libexec/rtkit-daemon
|
||
1496 root name=systemd:/systemd-1/accounts-daemon.service /usr/libexec/accounts-daemon
|
||
1499 root name=systemd:/systemd-1/systemd-logger.service /lib/systemd/systemd-logger
|
||
1511 lennart name=systemd:/systemd-1/prefdm.service /usr/bin/gnome-keyring-daemon --daemonize --login
|
||
1534 lennart name=systemd:/user/lennart/1 dbus-launch --sh-syntax --exit-with-session
|
||
1535 lennart name=systemd:/user/lennart/1 /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
|
||
1603 lennart name=systemd:/user/lennart/1 /usr/libexec/gconfd-2
|
||
1612 lennart name=systemd:/user/lennart/1 /usr/libexec/gnome-settings-daemon
|
||
1615 lennart name=systemd:/user/lennart/1 /usr/libexec/gvfsd
|
||
1626 lennart name=systemd:/user/lennart/1 /usr/libexec//gvfs-fuse-daemon /home/lennart/.gvfs
|
||
1634 lennart name=systemd:/user/lennart/1 /usr/bin/pulseaudio --start --log-target=syslog
|
||
1649 lennart name=systemd:/user/lennart/1 \_ /usr/libexec/pulse/gconf-helper
|
||
1645 lennart name=systemd:/user/lennart/1 /usr/libexec/bonobo-activation-server --ac-activate --ior-output-fd=24
|
||
1668 lennart name=systemd:/user/lennart/1 /usr/libexec/im-settings-daemon
|
||
1701 lennart name=systemd:/user/lennart/1 /usr/libexec/gvfs-gdu-volume-monitor
|
||
1707 lennart name=systemd:/user/lennart/1 /usr/bin/gnote --panel-applet --oaf-activate-iid=OAFIID:GnoteApplet_Factory --oaf-ior-fd=22
|
||
1725 lennart name=systemd:/user/lennart/1 /usr/libexec/clock-applet
|
||
1727 lennart name=systemd:/user/lennart/1 /usr/libexec/wnck-applet
|
||
1729 lennart name=systemd:/user/lennart/1 /usr/libexec/notification-area-applet
|
||
1733 root name=systemd:/systemd-1/dbus.service /usr/libexec/udisks-daemon
|
||
1747 root name=systemd:/systemd-1/dbus.service \_ udisks-daemon: polling /dev/sr0
|
||
1759 lennart name=systemd:/user/lennart/1 gnome-screensaver
|
||
1780 lennart name=systemd:/user/lennart/1 /usr/libexec/gvfsd-trash --spawner :1.9 /org/gtk/gvfs/exec_spaw/0
|
||
1864 lennart name=systemd:/user/lennart/1 /usr/libexec/gvfs-afc-volume-monitor
|
||
1874 lennart name=systemd:/user/lennart/1 /usr/libexec/gconf-im-settings-daemon
|
||
1903 lennart name=systemd:/user/lennart/1 /usr/libexec/gvfsd-burn --spawner :1.9 /org/gtk/gvfs/exec_spaw/1
|
||
1909 lennart name=systemd:/user/lennart/1 gnome-terminal
|
||
1913 lennart name=systemd:/user/lennart/1 \_ gnome-pty-helper
|
||
1914 lennart name=systemd:/user/lennart/1 \_ bash
|
||
29231 lennart name=systemd:/user/lennart/1 | \_ ssh tango
|
||
2221 lennart name=systemd:/user/lennart/1 \_ bash
|
||
4193 lennart name=systemd:/user/lennart/1 | \_ ssh tango
|
||
2461 lennart name=systemd:/user/lennart/1 \_ bash
|
||
29219 lennart name=systemd:/user/lennart/1 | \_ emacs systemd-for-admins-1.txt
|
||
15113 lennart name=systemd:/user/lennart/1 \_ bash
|
||
27251 lennart name=systemd:/user/lennart/1 \_ empathy
|
||
29504 lennart name=systemd:/user/lennart/1 \_ ps xawf -eo pid,user,cgroup,args
|
||
1968 lennart name=systemd:/user/lennart/1 ssh-agent
|
||
1994 lennart name=systemd:/user/lennart/1 gpg-agent --daemon --write-env-file
|
||
18679 lennart name=systemd:/user/lennart/1 /bin/sh /usr/lib64/firefox-3.6/run-mozilla.sh /usr/lib64/firefox-3.6/firefox
|
||
18741 lennart name=systemd:/user/lennart/1 \_ /usr/lib64/firefox-3.6/firefox
|
||
28900 lennart name=systemd:/user/lennart/1 \_ /usr/lib64/nspluginwrapper/npviewer.bin --plugin /usr/lib64/mozilla/plugins/libflashplayer.so --connection /org/wrapper/NSPlugins/libflashplayer.so/18741-6
|
||
4016 root name=systemd:/systemd-1/sysinit.service /usr/sbin/bluetoothd --udev
|
||
4094 smmsp name=systemd:/systemd-1/sendmail.service sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
|
||
4096 root name=systemd:/systemd-1/sendmail.service sendmail: accepting connections
|
||
4112 ntp name=systemd:/systemd-1/ntpd.service /usr/sbin/ntpd -n -u ntp:ntp -g
|
||
27262 lennart name=systemd:/user/lennart/1 /usr/libexec/mission-control-5
|
||
27265 lennart name=systemd:/user/lennart/1 /usr/libexec/telepathy-haze
|
||
27268 lennart name=systemd:/user/lennart/1 /usr/libexec/telepathy-logger
|
||
27270 lennart name=systemd:/user/lennart/1 /usr/libexec/dconf-service
|
||
27280 lennart name=systemd:/user/lennart/1 /usr/libexec/notification-daemon
|
||
27284 lennart name=systemd:/user/lennart/1 /usr/libexec/telepathy-gabble
|
||
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+, которая запускается
|
||
на ранней стадии загрузки.
|
||
|
||
Вы можете очень сильно упростить себе работу, если назначите для
|
||
вышеприведенной команды какой-нибудь простой и короткий псевдоним, например
|
||
\begin{Verbatim}
|
||
alias psc='ps xawf -eo pid,user,cgroup,args'
|
||
\end{Verbatim}
|
||
---~теперь для получения исчерпывающей информации по процессам достаточно будет
|
||
нажать всего четыре клавиши.
|
||
|
||
Альтернативный способ получить ту же информацию~--- воспользоваться утилитой
|
||
+systemd-cgls+, входящей в комплект поставки systemd. Она отображает иерархию
|
||
контрольных групп в виде псевдографической диаграммы-дерева:
|
||
|
||
\begin{landscape}
|
||
\begin{Verbatim}[fontsize=\small]
|
||
$ systemd-cgls
|
||
+ 2 [kthreadd]
|
||
[...]
|
||
+ 4281 [flush-8:0]
|
||
+ user
|
||
| \ lennart
|
||
| \ 1
|
||
| + 1495 pam: gdm-password
|
||
| + 1521 gnome-session
|
||
| + 1534 dbus-launch --sh-syntax --exit-with-session
|
||
| + 1535 /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
|
||
| + 1603 /usr/libexec/gconfd-2
|
||
| + 1612 /usr/libexec/gnome-settings-daemon
|
||
| + 1615 /ushr/libexec/gvfsd
|
||
| + 1621 metacity
|
||
| + 1626 /usr/libexec//gvfs-fuse-daemon /home/lennart/.gvfs
|
||
| + 1634 /usr/bin/pulseaudio --start --log-target=syslog
|
||
| + 1635 gnome-panel
|
||
| + 1638 nautilus
|
||
| + 1640 /usr/libexec/polkit-gnome-authentication-agent-1
|
||
| + 1641 /usr/bin/seapplet
|
||
| + 1644 gnome-volume-control-applet
|
||
| + 1645 /usr/libexec/bonobo-activation-server --ac-activate --ior-output-fd=24
|
||
| + 1646 /usr/sbin/restorecond -u
|
||
| + 1649 /usr/libexec/pulse/gconf-helper
|
||
| + 1652 /usr/bin/devilspie
|
||
| + 1662 nm-applet --sm-disable
|
||
| + 1664 gnome-power-manager
|
||
| + 1665 /usr/libexec/gdu-notification-daemon
|
||
| + 1668 /usr/libexec/im-settings-daemon
|
||
| + 1670 /usr/libexec/evolution/2.32/evolution-alarm-notify
|
||
| + 1672 /usr/bin/python /usr/share/system-config-printer/applet.py
|
||
| + 1674 /usr/lib64/deja-dup/deja-dup-monitor
|
||
| + 1675 abrt-applet
|
||
| + 1677 bluetooth-applet
|
||
| + 1678 gpk-update-icon
|
||
| + 1701 /usr/libexec/gvfs-gdu-volume-monitor
|
||
| + 1707 /usr/bin/gnote --panel-applet --oaf-activate-iid=OAFIID:GnoteApplet_Factory --oaf-ior-fd=22
|
||
| + 1725 /usr/libexec/clock-applet
|
||
| + 1727 /usr/libexec/wnck-applet
|
||
| + 1729 /usr/libexec/notification-area-applet
|
||
| + 1759 gnome-screensaver
|
||
| + 1780 /usr/libexec/gvfsd-trash --spawner :1.9 /org/gtk/gvfs/exec_spaw/0
|
||
| + 1864 /usr/libexec/gvfs-afc-volume-monitor
|
||
| + 1874 /usr/libexec/gconf-im-settings-daemon
|
||
| + 1882 /usr/libexec/gvfs-gphoto2-volume-monitor
|
||
| + 1903 /usr/libexec/gvfsd-burn --spawner :1.9 /org/gtk/gvfs/exec_spaw/1
|
||
| + 1909 gnome-terminal
|
||
| + 1913 gnome-pty-helper
|
||
| + 1914 bash
|
||
| + 1968 ssh-agent
|
||
| + 1994 gpg-agent --daemon --write-env-file
|
||
| + 2221 bash
|
||
| + 2461 bash
|
||
| + 4193 ssh tango
|
||
| + 15113 bash
|
||
| + 18679 /bin/sh /usr/lib64/firefox-3.6/run-mozilla.sh /usr/lib64/firefox-3.6/firefox
|
||
| + 18741 /usr/lib64/firefox-3.6/firefox
|
||
| + 27251 empathy
|
||
| + 27262 /usr/libexec/mission-control-5
|
||
| + 27265 /usr/libexec/telepathy-haze
|
||
| + 27268 /usr/libexec/telepathy-logger
|
||
| + 27270 /usr/libexec/dconf-service
|
||
| + 27280 /usr/libexec/notification-daemon
|
||
| + 27284 /usr/libexec/telepathy-gabble
|
||
| + 27285 /usr/libexec/telepathy-salut
|
||
| + 27297 /usr/libexec/geoclue-yahoo
|
||
| + 28900 /usr/lib64/nspluginwrapper/npviewer.bin --plugin /usr/lib64/mozilla/plugins/libflashplayer.so --connection /org/wrapper/NSPlugins/libflashplayer.so/18741-6
|
||
| + 29219 emacs systemd-for-admins-1.txt
|
||
| + 29231 ssh tango
|
||
| \ 29519 systemd-cgls
|
||
\ systemd-1
|
||
+ 1 /sbin/init
|
||
+ ntpd.service
|
||
| \ 4112 /usr/sbin/ntpd -n -u ntp:ntp -g
|
||
+ systemd-logger.service
|
||
| \ 1499 /lib/systemd/systemd-logger
|
||
+ accounts-daemon.service
|
||
| \ 1496 /usr/libexec/accounts-daemon
|
||
+ rtkit-daemon.service
|
||
| \ 1473 /usr/libexec/rtkit-daemon
|
||
+ console-kit-daemon.service
|
||
| \ 1408 /usr/sbin/console-kit-daemon --no-daemon
|
||
+ prefdm.service
|
||
| + 1376 /usr/sbin/gdm-binary -nodaemon
|
||
| + 1391 /usr/libexec/gdm-simple-slave --display-id /org/gnome/DisplayManager/Display1 --force-active-vt
|
||
| + 1394 /usr/bin/Xorg :0 -nr -verbose -auth /var/run/gdm/auth-for-gdm-f2KUOh/database -nolisten tcp vt1
|
||
| + 1419 /usr/bin/dbus-launch --exit-with-session
|
||
| \ 1511 /usr/bin/gnome-keyring-daemon --daemonize --login
|
||
+ getty@.service
|
||
| + tty6
|
||
| | \ 1346 /sbin/mingetty tty6
|
||
| + tty4
|
||
| | \ 1343 /sbin/mingetty tty4
|
||
| + tty5
|
||
| | \ 1342 /sbin/mingetty tty5
|
||
| + tty3
|
||
| | \ 1339 /sbin/mingetty tty3
|
||
| \ tty2
|
||
| \ 1332 /sbin/mingetty tty2
|
||
+ abrtd.service
|
||
| \ 1317 /usr/sbin/abrtd -d -s
|
||
+ crond.service
|
||
| \ 1344 crond
|
||
+ sshd.service
|
||
| \ 1362 /usr/sbin/sshd
|
||
+ sendmail.service
|
||
| + 4094 sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
|
||
| \ 4096 sendmail: accepting connections
|
||
+ haldaemon.service
|
||
| + 1249 hald
|
||
| + 1250 hald-runner
|
||
| + 1273 hald-addon-input: Listening on /dev/input/event3 /dev/input/event9 /dev/input/event1 /dev/input/event7 /dev/input/event2 /dev/input/event0 /dev/input/event8
|
||
| + 1275 /usr/libexec/hald-addon-rfkill-killswitch
|
||
| + 1284 /usr/libexec/hald-addon-leds
|
||
| + 1285 /usr/libexec/hald-addon-generic-backlight
|
||
| \ 1287 /usr/libexec/hald-addon-acpi
|
||
+ irqbalance.service
|
||
| \ 1210 irqbalance
|
||
+ avahi-daemon.service
|
||
| + 1175 avahi-daemon: running [epsilon.local]
|
||
+ NetworkManager.service
|
||
| + 1171 /usr/sbin/NetworkManager --no-daemon
|
||
| \ 4028 /sbin/dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf /var/run/dhclient-wlan0.pid -lf /var/lib/dhclient/dhclient-7d32a784-ede9-4cf6-9ee3-60edc0bce5ff-wlan0.lease -cf /var/run/nm-dhclient-wlan0.conf wlan0
|
||
+ rsyslog.service
|
||
| \ 1193 /sbin/rsyslogd -c 4
|
||
+ mdmonitor.service
|
||
| \ 1207 mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.pid
|
||
+ cups.service
|
||
| \ 1195 cupsd -C /etc/cups/cupsd.conf
|
||
+ auditd.service
|
||
| + 1131 auditd
|
||
| + 1133 /sbin/audispd
|
||
| \ 1135 /usr/sbin/sedispatch
|
||
+ dbus.service
|
||
| + 1096 /bin/dbus-daemon --system --address=systemd: --nofork --systemd-activation
|
||
| + 1216 /usr/sbin/modem-manager
|
||
| + 1219 /usr/libexec/polkit-1/polkitd
|
||
| + 1242 /usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -B -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid
|
||
| + 1453 /usr/libexec/upowerd
|
||
| + 1733 /usr/libexec/udisks-daemon
|
||
| + 1747 udisks-daemon: polling /dev/sr0
|
||
| \ 29509 /usr/libexec/packagekitd
|
||
+ dev-mqueue.mount
|
||
+ dev-hugepages.mount
|
||
\ sysinit.service
|
||
+ 455 /sbin/udevd -d
|
||
+ 4016 /usr/sbin/bluetoothd --udev
|
||
+ 28188 /sbin/udevd -d
|
||
\ 28191 /sbin/udevd -d
|
||
\end{Verbatim}
|
||
(Как и предыдущий, этот листинг был сокращен за счет удаления перечня потоков
|
||
ядра.)
|
||
\end{landscape}
|
||
|
||
Как видно из листинга, данная команда наглядно показывает принадлежность
|
||
процессов к их контрольным группам, а следовательно, и к службам, так как
|
||
systemd именует группы в соответствии с названиями служб. Например, из
|
||
приведенного листинга нетрудно понять, что служба системного аудита
|
||
+auditd.service+ порождает три отдельных процесса: +auditd+,
|
||
+audispd+ и +sedispatch+.
|
||
|
||
Наиболее внимательные читатели, вероятно, уже заметили, что некоторые процессы
|
||
помещены в группу +/user/lennart/1+. Дело в том, что systemd занимается
|
||
отслеживанием и группировкой не~только процессов, относящихся к системным
|
||
службам, но и процессов, запущенных в рамках пользовательских сеансов. В
|
||
последующих статьях мы обсудим этот вопрос более подробно.
|
||
|
||
\section{HOW-TO: преобразование SysV init-скрипта в systemd service-файл}
|
||
|
||
Традиционно, службы Unix и Linux (демоны) запускаются через SysV init-скрипты.
|
||
Эти скрипты пишутся на языке Bourne Shell (+/bin/sh+), располагаются в
|
||
специальном каталоге (обычно +/etc/rc.d/init.d/+) и вызываются с одним из
|
||
стандартных параметров (+start+, +stop+, +reload+ и т.п.)~--- таким образом
|
||
указывается действие, которое необходимо прозвести над службой (запустить,
|
||
остановить, заставить перечитать конфигурацию). При запуске службы такой
|
||
скрипт, как правило, вызывает бинарник демона, который, в свою очередь,
|
||
форкается, порождая фоновый процесс (т.е. демонизируется). Заметим, что
|
||
shell-скрипты, как правило, отличается низкой скоростью работы, излишней
|
||
подробностью изложения и крайней хрупкостью. Читать их, из-за изобилия
|
||
всевозможного вспомогательного и дополнительного кода, чрезвычайно тяжело.
|
||
Впрочем, нельзя не~упомянуть, что эти скрипты являются очень гибким
|
||
инструментом (ведь, по сути, это всего лишь код, который можно модифицировать
|
||
как угодно). С другой стороны, многие задачи, возникающие при работе со
|
||
службами, довольно тяжело решить средствами shell-скриптов. К таким
|
||
задачам относятся: организация параллельного исполнения, корректное
|
||
отслеживание процессов, конфигурирование различных параметров среды исполнения
|
||
процесса. systemd обеспечивает совместимость с init-скриптами, однако, с учетом
|
||
описанных выше их недостатков, более правильным решением будет использование
|
||
штатных service-файлов systemd для всех установленных в системе служб. Стоит
|
||
отметить что, в отличие от init-скриптов, которые часто приходится
|
||
модифицировать при переносе из одного дистрибутива в другой, один и тот же
|
||
service-файл будет работать в любом дистрибутиве, использующем systemd (а таких
|
||
дистрибутивов с каждым днем становится все больше и больше). Далее мы вкратце
|
||
рассмотрим процесс преобразования SysV init-скрипта в service-файл systemd.
|
||
Вообще говоря, service-файл должен создаваться разработчиками каждого демона, и
|
||
включаться в комплект его поставки. Если вам удалось успешно создать
|
||
работоспособный service-файл для какого-либо демона, настоятельно рекомендуем
|
||
вам отправить этот файл разработчикам. Вопросы по полноценной интеграции
|
||
демонов с systemd, с максимальным использованием всех его возможностей, будут
|
||
рассмотрены в последующих статьях этого цикла, пока же ограничимся ссылкой на
|
||
\href{http://0pointer.de/public/systemd-man/daemon.html}{страницу} официальной
|
||
документации.
|
||
|
||
Итак, приступим. В качестве пример возьмем init-скрипт демона ABRT (Automatic
|
||
Bug Reporting Tool, службы, занимающейся сбором crash dump'ов). Исходный
|
||
скрипт (в варианте для дистрибутива Fedora) можно загрузить
|
||
\href{http://0pointer.de/public/abrtd}{здесь}.
|
||
|
||
Начнем с того, что прочитаем исходный скрипт (неожиданный ход, правда?) и
|
||
выделим полезную информацию из груды хлама. Практически у всех init-скриптов
|
||
б\'{о}льшая часть кода является чисто вспомогательной, и мало чем отличается от
|
||
одного скрипта к другому. Как правило, при создании новых скриптов этот код
|
||
просто копируется из уже существующих (разработка в стиле copy-paste). Итак,
|
||
в исследуемом скрипте нас интересует следующая информация:
|
||
|
||
\begin{itemize}
|
||
\item Строка описания службы: <<Daemon to detect crashing apps>>. Как
|
||
нетрудно заметить, комментарии в заголовке скрипта весьма
|
||
пространны и описывают не~сколько саму службу, сколько
|
||
скрипт, ее запускающий. service-файлы systemd также включают
|
||
описание, но оно относится исключительно к службе, а не~к
|
||
service-файлу.
|
||
\item LSB-заголовок\footnote{LSB-заголовок~--- определенная в
|
||
\href{http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html}{Linux
|
||
Standard Base} схема записи метаданных о службах в блоках
|
||
комментариев соответствующих init-скриптов. Изначально эта
|
||
схема была введена именно для того, чтобы стандартизировать
|
||
init-скрипты во всех дистрибутивах. Однако разработчики
|
||
многих дистрибутивов не~считают нужным точно исполнять
|
||
требования LSB, и поэтому формы представления метаданных в
|
||
различных дистрибутивах могут отличаться. Вследствие этого,
|
||
при переносе init-скрипта из одного дистрибутива в другой,
|
||
скрипт приходится модифицировать. Например, демон пересылки
|
||
почты при описании зависимостей может именоваться
|
||
+MTA+ или +smtpdaemon+ (Fedora), +smtp+
|
||
(openSUSE), +mail-transport-agent+ (Debian и Ubuntu),
|
||
+mail-transfer-agent+. Таким образом, можно утверждать, что
|
||
стандарт LSB не~справляется с возложенной на него задачей},
|
||
содержащий информацию о зависимостях. systemd, базирующийся
|
||
на идеях socket-активации, обычно не~требует явного описания
|
||
зависимостей (либо требует самого минимального описания).
|
||
Заметим, что основополагающие принципы systemd, включая
|
||
socket-активацию, рассмотрены в статье
|
||
\href{http://0pointer.de/blog/projects/systemd.html}{Rethinking
|
||
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}.
|
||
Возвращаясь к нашему примеру: в данном случае ценной
|
||
информацией о зависимостях является только строка
|
||
+Required-Start: $syslog+, сообщающая, что для работы
|
||
abrtd требуется демон системного лога. Информация о второй
|
||
зависимости, +$local_fs+, является избыточной, так как
|
||
systemd приступает к запуску служб уже после того, как все
|
||
файловые системы готовы для работы.
|
||
\item Также, LSB-заголовок сообщает, что данная служба должна быть
|
||
запущена на уровнях исполнения (runlevels) 3 (консольный
|
||
многопользовательский) и 5 (графический
|
||
многопользовательской).
|
||
\item Исполняемый бинарник демона называется +/usr/sbin/abrtd+.
|
||
\end{itemize}
|
||
|
||
Вот и вся полезная информация. Все остальное содержимое 115-строчного скрипта
|
||
является чисто вспомогательным кодом: операции синхронизации и упорядочивания
|
||
запуска (код, относящийся к lock-файлам), вывод информационных сообщений
|
||
(команды +echo+), разбор входных параметров (монструозный блок
|
||
+case+).
|
||
|
||
На основе приведенной выше информации, мы можем написать следующий
|
||
service-файл:
|
||
\begin{Verbatim}
|
||
[Unit]
|
||
Description=Daemon to detect crashing apps
|
||
After=syslog.target
|
||
|
||
[Service]
|
||
ExecStart=/usr/sbin/abrtd
|
||
Type=forking
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
\end{Verbatim}
|
||
|
||
Рассмотрим этот файл поподробнее.
|
||
|
||
Секция +[Unit]+ содержит самую общую информацию о службе. Не~будем
|
||
забывать, что systemd управляет не~только службами, но и многими другими
|
||
объектами, в частности, устройствами, точками монтирования, таймерами и т.п.
|
||
Общее наименование всех этих объектов~--- юнит (unit). Одноименная секция
|
||
конфигурационного файла определяет наиболее общие свойства, которые могут
|
||
быть присущи любому юниту. В нашем случае это, во-первых, строка описания, и
|
||
во-вторых, указание, что данный юнит рекомендуется активировать после запуска
|
||
демона системного лога\footnote{Строго говоря, эту зависимость здесь
|
||
указывать не~нужно~--- в системах, в которых демон системного лога активируется
|
||
через сокет, эта зависимость является избыточной. Современные реализации
|
||
демона системного лога (например, rsyslog начиная с пятой версии)
|
||
поддерживают активацию через сокет. В системах, использующих такие
|
||
реализации, явное указание +After=syslog.target+ будет избыточным, так
|
||
как соответствующая функциональность поддерживается автоматически. Однако,
|
||
эту строчку стоит все-таки указать для обеспечения совместимости с системами,
|
||
использующими устаревшие реализации демона системного лога}. Эта информация,
|
||
как мы помним, была указана в LSB-заголовке исходного init-скрипта. В нашем
|
||
конфигурационном файле мы указываем зависимость от демона системного лога при
|
||
помощи директивы +After+, указывающей на юнит +syslog.taget+. Это
|
||
специальный юнит, позволяющий ссылаться на любую реализацию демона системного
|
||
лога, независимо от используемой программы (например, rsyslog или syslog-ng)
|
||
и типа активации (как обычной службы или через log-сокет). Подробнее о таких
|
||
специальных юнитах можно почитать
|
||
\href{http://0pointer.de/public/systemd-man/systemd.special.html}{страницу}
|
||
официальной документации. Обратите внимание, что директива +After+, в
|
||
отсутствие директивы +Requires+, задает лишь порядок загрузки, но
|
||
не~задает жесткой зависимости. То есть, если при загрузке конфигурация
|
||
systemd будет предписывать запуск как демона системного лога, так и abrtd, то
|
||
сначала будет запущен демон системного лога, и только потом abrtd. Если же
|
||
конфигурация не~будет содержать явного указания запустить демон системного
|
||
лога, он не~будет запущен даже при запуске abrtd. И это поведение нас
|
||
полностью устраивает, так как abrtd прекрасно может обходиться и без демона
|
||
системного лога. В противном случае, мы могли бы воспользоваться директивой
|
||
+Requires+, задающей жесткую зависимость между юнитами.
|
||
|
||
Следующая секция, +[Service]+, содержит информацию о службе. Сюда включаются
|
||
настройки, относящие именно к службам, но не~к другим типам юнитов. В нашем
|
||
случае, таких настроек две: +ExecStart+, определяющая расположение бинарника
|
||
демона и аргументы, с которыми он будет вызван (в нашем случае они
|
||
отсутствуют), и +Type+, позволяющая задать метод, по которому systemd определит
|
||
окончание периода запуска службы. Традиционный для Unix метод демонизации
|
||
процесса, когда исходный процесс форкается, порождая демона, после чего
|
||
завершается, описывается типом +forking+ (как в нашем случае). Таким образом,
|
||
systemd считает службу запущенной с момента завершения работы исходного
|
||
процесса, и рассматривает в качестве основного процесса этой службы
|
||
порожденный им процесс-демон.
|
||
|
||
И наконец, третья секция, +[Install]+. Она содержит рекомендации по
|
||
установке конкретного юнита, указывающие, в каких ситуациях он должен быть
|
||
активирован. В нашем случае, служба abrtd запускается при активации юнита
|
||
+multi-user.target+. Это специальный юнит, примерно соответствующий роли
|
||
третьего уровня исполнения классического SysV\footnote{В том контексте, в
|
||
котором он используется в большинстве дистрибутивов семейства Red Hat, а
|
||
именно, многопользовательский режим без запуска графической оболочки}.
|
||
Директива +WantedBy+ никак не~влияет на уже работающую службу, но она
|
||
играет важную роль при выполнении команды +systemctl enable+, задавая, в каких
|
||
условиях должен активироваться устанавливаемый юнит. В нашем примере, служба
|
||
abrtd будет активироваться при переходе в состояние +multi-user.target+,
|
||
т.е., при каждой нормальной загрузке\footnote{Обратите внимание, что режим
|
||
графической загрузки в systemd (+graphical.target+, аналог runlevel 5
|
||
в SysV) является надстройкой над режимом многопользовательской консольной
|
||
загрузки (+multi-user.target+, аналог runlevel 3 в SysV). Таким
|
||
образом, все службы, запускаемые в режиме +multi-user.target+, будут
|
||
также запускаться и в режиме +graphical.target+} (к <<ненормальным>>
|
||
можно отнести, например, загрузки в режиме +emergency.target+, который
|
||
является аналогом первого уровня исполнения в классической SysV).
|
||
|
||
Вот и все. Мы получили минимальный рабочий service-файл systemd. Чтобы
|
||
проверить его работоспособность, скопируем его в
|
||
+/etc/systemd/system/abrtd.service+, после чего командой
|
||
+systemctl daemon-reload+ уведомим systemd об изменении конфигурации.
|
||
Теперь нам остается только запустить нашу службу:
|
||
+systemctl start abrtd.service+. Проверить состояние службы можно
|
||
командой +systemctl status abrtd.service+, а чтобы остановить ее, нужно
|
||
скомандовать +systemctl stop abrtd.service+. И наконец, команда
|
||
+systemctl enable abrtd.service+ выполнит установку service-файла,
|
||
обеспечив его активацию при каждой загрузке (аналог +chkconfig abrtd on+
|
||
в классическом SysV).
|
||
|
||
Приведенный выше service-файл является практический точным переводом
|
||
исходного init-скрипта, и он никак не~использует широкий спектр возможностей,
|
||
предоставляемых systemd. Ниже приведен немного улучшенный вариант этого же
|
||
файла:
|
||
|
||
\begin{Verbatim}
|
||
[Unit]
|
||
Description=ABRT Automated Bug Reporting Tool
|
||
After=syslog.target
|
||
|
||
[Service]
|
||
Type=dbus
|
||
BusName=com.redhat.abrt
|
||
ExecStart=/usr/sbin/abrtd -d -s
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
\end{Verbatim}
|
||
|
||
Чем же новый вариант отличается от предыдущего? Ну, прежде всего, мы уточнили
|
||
описание службы. Однако, ключевым изменением является замена значения +Type+ с +forking+
|
||
на +dbus+ и связанные с ней изменения: добавление имени службы в шине D-Bus
|
||
(директива +BusName+) и задание дополнительных аргументов abrtd <<+-d -s+>>. Но
|
||
зачем вообще нужна эта замена? Каков ее практический смысл? Чтобы ответить на
|
||
этот вопрос, мы снова возвращаемся к демонизации. В ходе этой операции процесс
|
||
дважды форкается и отключается от всех терминалов. Это очень удобно при запуске
|
||
демона через скрипт, но в случае использования таких продвинутых систем
|
||
инициализации, как systemd, подобное поведение не~дает никаких преимуществ, но
|
||
вызывает неоправданные задержки. Даже если мы оставим в стороне вопрос скорости
|
||
загрузки, останется такой важный аспект, как отслеживание состояния служб.
|
||
systemd решает и эту задачу, контролируя работу службы и при необходимости
|
||
реагируя на различные события. Например, при неожиданном падении основного
|
||
процесса службы, systemd должен зарегистрировать идентификатор и код выхода
|
||
процесса, также, в зависимости от настроек, он может попытаться перезапустить
|
||
службу, либо активировать какой-либо заранее заданный юнит. Операция
|
||
демонизации несколько затрудняет решение этих задач, так как обычно довольно
|
||
сложно найти связь демонизированного процесса с исходным (собственно, смысл
|
||
демонизации как раз и сводится к уничтожению этой связи) и, соответственно, для
|
||
systemd сложнее определить, какой из порожденных в рамках данной службы
|
||
процессов является основным. Чтобы упростить для него решение этой задачи, мы и
|
||
воспользовались типом запуска +dbus+. Он подходит для всех служб, которые в
|
||
конце процесса инициализации регистрируют свое имя на шине D-Bus\footnote{В
|
||
настоящее время практически все службы дистрибутива Fedora после запуска
|
||
регистрируется на шине D-Bus}. ABRTd относится к ним. С новыми настройками,
|
||
systemd запустит процесс abrtd, который уже не~будет форкаться (согласно
|
||
указанным нами ключам <<+-d -s+>>), и в качестве момента окончания периода
|
||
запуска данной службы systemd будет рассматривать момент регистрации имени
|
||
+com.redhat.abrt+ на шине D-Bus. В этом случае основным для данной службы будет
|
||
считаться процесс, непосредственно порожденный systemd. Таким образом, systemd
|
||
располагает удобным методом для определения момента окончания запуска службы, а
|
||
также может легко отслеживать ее состояние.
|
||
|
||
Собственно, это все, что нужно было сделать. Мы получили простой
|
||
конфигурационный файл, в 10 строчках которого содержится больше полезной
|
||
информации, чем в 115 строках исходного init-скрипта. Добавляя в наш файл по
|
||
одной строчке, мы можем использовать различные полезные функции systemd,
|
||
создание аналога которых в традиционном init-скрипте потребовало бы
|
||
значительных усилий. Например, добавив строку +Restart=restart-always+, мы
|
||
приказываем systemd автоматически перезапускать службу после каждого ее
|
||
падения. Или, например, добавив +OOMScoreAdjust=-500+, мы попросим ядро сберечь
|
||
эту службу, даже если OOM Killer выйдет на тропу войны. А если мы добавим
|
||
строчку +CPUSchedulingPolicy=idle+, процесс abrtd будет работать только в те
|
||
моменты, когда система больше ничем не~занята, что позволит не создавать помех
|
||
для процессов, активно использующих CPU.
|
||
|
||
За более подробным описанием всех опций настройки, вы можете обратиться к
|
||
страницам рукводства
|
||
\href{http://0pointer.de/public/systemd-man/systemd.unit.html}{systemd.unit},
|
||
\href{http://0pointer.de/public/systemd-man/systemd.service.html}{systemd.service},
|
||
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{systemd.exec}. Полный
|
||
список доступных страниц можно просмотреть
|
||
\href{http://0pointer.de/public/systemd-man/}{здесь}.
|
||
|
||
Конечно, отнюдь не~все init-скрипты так же легко преобразовать в
|
||
service-файлы. Но, к счастью, <<проблемных>> скриптов не~так уж и много.
|
||
|
||
\section{Убить демона}
|
||
|
||
Убить системного демона нетрудно, правда? Или\ldots{} все не~так просто?
|
||
|
||
Если ваш демон функционирует как один процесс, все действительно очень просто.
|
||
Вы командуете +killall rsyslogd+, и демон системного лога останавливается.
|
||
Впрочем, этот метод не~вполне корректен, так как он действует не~только на
|
||
самого демона, но и на другие процессы с тем же именем. Иногда подобное
|
||
поведение может привести к неприятным последствиям. Более правильным будет
|
||
использование pid-файла: +kill $(cat /var/run/syslogd.pid)+. Вот, вроде
|
||
бы, и все, что вам нужно\ldots{} Или мы упускаем еще что-то?
|
||
|
||
Действительно, мы забываем одну простую вещь: существуют службы, такие, как
|
||
Apache, crond, atd, которые по роду служебной деятельности должны запускать
|
||
дочерние процессы. Это могут быть совершенно посторонние, указанные
|
||
пользователем программы (например, задачи cron/at, CGI-скрипты) или полноценные
|
||
серверные процессы (например, Apache workers). Когда вы убиваете основной
|
||
процесс, он может остановить все дочерние процессы. А может и не~остановить. В
|
||
самом деле, если служба функционирует в штатном режиме, ее обычно останавливают
|
||
командой +stop+. К прямому вызову +kill+ администратор, как правило,
|
||
прибегает только в аварийной ситуации, когда служба работает неправильно и
|
||
может не~среагировать на стандартную команду остановки. Таким образом, убив,
|
||
например, основной сервер Apache, вы можете получить от него в наследство
|
||
работающие CGI-скрипты, причем их родителем автоматически станет PID~1 (init),
|
||
так что установить их происхождение будет не~так-то просто.
|
||
|
||
\href{http://www.freedesktop.org/wiki/Software/systemd}{systemd} спешит к нам
|
||
на помощь. Команда +systemctl kill+ позволит отправить сигнал всем
|
||
процессам, порожденным в рамках данной службы. Например:
|
||
|
||
\begin{Verbatim}
|
||
# systemctl kill crond.service
|
||
\end{Verbatim}
|
||
|
||
Вы можете быть уверены, что всем процессам службы cron будет отправлен сигнал
|
||
+SIGTERM+. Разумеется, можно отправить и любой другой сигнал. Скажем, если ваши
|
||
дела совсем уж плохи, вы можете воспользоваться и +SIGKILL+:
|
||
|
||
\begin{Verbatim}
|
||
# systemctl kill -s SIGKILL crond.service
|
||
\end{Verbatim}
|
||
|
||
После ввода этой команды, служба cron будет жестоко убита вместе со всеми ее
|
||
дочерними процессами, вне зависимости от того, сколько раз она форкалась, и
|
||
как бы она ни пыталась сбежать из-под нашего контроля при помощи двойного
|
||
форка или
|
||
\href{http://ru.wikipedia.org/wiki/Fork-%D0%B1%D0%BE%D0%BC%D0%B1%D0%B0}{форк-бомбардировки}%
|
||
\footnote{Прим. перев.: стоит особо отметить, что использование контрольных
|
||
групп не~только упрощает процесс уничтожения форк-бомб, но и значительно
|
||
уменьшает ущерб от работающей форк-бомбы. Так как systemd автоматически
|
||
помещает каждую службу и каждый пользовательский сеанс в свою контрольную
|
||
группу по ресурсу процессорного времени, запуск форк-бомбы одним
|
||
пользователем или службой не~создаст значительных проблем с отзывчивостью
|
||
системы у других пользователей и служб. Таким образом, в качестве основной
|
||
угрозы форк-бомбардировки остаются лишь возможности исчерпания памяти и
|
||
идентификаторов процессов (PID)}.
|
||
|
||
В некоторый случах возникает необходимость отправить сигнал именно основному
|
||
процессу службы. Например, используя +SIGHUP+, мы можем заставить демона
|
||
перечитать файлы конфигурации. Разумеется, передавать HUP вспомогательным процессам
|
||
в этом случае совершенно необязательно. Для решения подобной
|
||
задачи неплохо подойдет и классический метод с pid-файлом, однако у
|
||
systemd и на этот случай есть простое решение, избавляющее вас от
|
||
необходимости искать нужный файл:
|
||
|
||
\begin{Verbatim}
|
||
# systemctl kill -s HUP --kill-who=main crond.service
|
||
\end{Verbatim}
|
||
|
||
Итак, что же принципиально новое привносит systemd в рутинный процесс
|
||
убийства демона? Прежде всего: впервые в истории Linux представлен способ
|
||
принудительной остановки службы, не~зависящий от того, насколько
|
||
добросовестно основной процесс службы выполняет свои обязательства по
|
||
остановке дочерних процессов. Как уже упоминалось выше, необходимость
|
||
отправить процессу +SIGTERM+ или +SIGKILL+ обычно возникает именно
|
||
в нештатной ситуации, когда вы уже не~можете быть уверены, что демон
|
||
корректно исполнит все свои обязанности.
|
||
|
||
После прочтения сказанного выше у вас может возникнуть вопрос: в чем разница
|
||
между +systemctl kill+ и +systemctl stop+? Отличие состоит в том,
|
||
что +kill+ просто отправляет сигнал заданному процессу, в то время как
|
||
+stop+ действует по <<официально>> определенному методу, вызывая команду,
|
||
определенную в параметре +ExecStop+ конфигурации службы. Обычно команды
|
||
+stop+ бывает вполне достаточно для остановки службы, и к +kill+
|
||
приходится прибегать только в крайних случаях, например, когда служба
|
||
<<зависла>> и не~реагирует на команды.
|
||
|
||
Кстати говоря, при использовании параметра <<+-s+>>, вы можете указывать
|
||
названия сигналов как с префиксом SIG, так и без него~--- оба варианта будут
|
||
работать.
|
||
|
||
В завершение стоит сказать, что для нас весьма интересным и неожиданным
|
||
оказался тот факт, что до появления systemd в Linux просто не~существовало
|
||
инструментов, позволяющих корректно отправить сигнал службе в целом, а
|
||
не~отдельному процессу.
|
||
|
||
\end{document}
|