воскресенье, 21 октября 2012 г.

Заметки о systemd, часть 2, управление

Как ним управлять?


Сразу переходим к частностям. Почему к частностям? Потому, что внедрение systemd в дистрибутивы идёт опережающими темпами (опережающими развитие самого проекта systemd, опережающими наличие технических описаний на компоненты systemd ... -  так сильно спешим). И если пользователь установит на сегодня свежий дистрибутив Fedora или OpenSUSE (а кто ставит не свежий дистрибутив?), то очень скоро столкнётся с сугубо конкретным вопросом, типа: "А почему у меня не запускается SSH сервер?" ... и ни в одном из руководств последних 20-ти лет не найдёт верного ответа. Поэтому, пока сосредоточимся только на том, как решить конкретные проблемы пользователя (непосредственно те, с которыми я сам столкнулся в инсталляции Fedora 17).

Итак, вперёд к обузданию systemd. Некоторые вещи я буду описывать как это делается в FAQ: вопрос - ответ...

Управление загруженными сервисами


Управление сервисами делаем, естественно, только с правами root.

Прежде каких-либо действий, разумно поинтересоваться тем, какие вообще сервисы находятся под управлением systemd, ведь это, в значительной степени, зависит от предыстории ваших инсталляций:

$ cd /lib/systemd/system/
$ ls -w120 *.service
abrt-ccpp.service halt-local.service     rpcbind.service
abrtd.service halt.service     rpcgssd.service
abrt-oops.service hibernate.service     rpcidmapd.service
abrt-vmcore.service instperf.service     rpcsvcgssd.service
accounts-daemon.service ip6tables.service     rsyslog.service
alsa-restore.service iptables.service     rtkit-daemon.service
alsa-store.service irda.service     saslauthd.service
anaconda@.service irqbalance.service     sendmail.service
anaconda-shell@.service jetty.service     serial-getty@.service
apg@.service kexec.service     single.service
arp-ethers.service ksm.service     smb.service
atd.service ksmtuned.service     sm-client.service
auditd.service lldpad.service     sshd.service
autovt@.service lvm2-monitor.service     sssd.service
avahi-daemon.service mcelog.service     suspend.service
bluetooth.service mdmonitor.service     svnserve.service
canberra-system-bootup.service mdmonitor-takeover.service     systemd-ask-password-console.service
canberra-system-shutdown-reboot.service  messagebus.service     systemd-ask-password-plymouth.service
canberra-system-shutdown.service multipathd.service     systemd-ask-password-wall.service
chronyd.service named.service     systemd-binfmt.service
chrony-wait.service NetworkManager.service     systemd-debug-shell.service
colord-sane.service NetworkManager-wait-online.service  systemd-hostnamed.service
colord.service nfs-blkmap.service     systemd-initctl.service
console-getty.service nfs-idmap.service     systemd-journald.service
console-shell.service nfs-lock.service     systemd-localed.service
cpupower.service nfslock.service     systemd-logind.service
crond.service nfs-mountd.service     systemd-modules-load.service
cups.service nfs-rquotad.service     systemd-random-seed-load.service
cvs@.service nfs-secure-server.service     systemd-random-seed-save.service
dbus-org.freedesktop.hostname1.service nfs-secure.service     systemd-readahead-collect.service
dbus-org.freedesktop.locale1.service nfs-server.service     systemd-readahead-done.service
dbus-org.freedesktop.login1.service nfs.service     systemd-readahead-replay.service
dbus-org.freedesktop.timedate1.service nmb.service     systemd-remount-fs.service
dbus.service openvpn@.service     systemd-shutdownd.service
display-manager.service plymouth-halt.service     systemd-sysctl.service
dm-event.service plymouth-kexec.service     systemd-timedated.service
dnsmasq.service plymouth-poweroff.service     systemd-tmpfiles-clean.service
dnssec-triggerd-keygen.service plymouth-quit.service     systemd-tmpfiles-setup.service
dnssec-triggerd.service plymouth-quit-wait.service     systemd-update-utmp-runlevel.service
dracut-shutdown.service plymouth-read-write.service     systemd-update-utmp-shutdown.service
emergency.service plymouth-reboot.service     systemd-user-sessions.service
fcoe.service plymouth-start.service     systemd-vconsole-setup.service
fedora-autorelabel-mark.service poweroff.service     system-setup-keyboard.service
fedora-autorelabel.service pppoe-server.service     udev-configure-printer.service
fedora-configure.service prefdm.service     udev.service
fedora-import-state.service proftpd.service     udev-settle.service
fedora-loadmodules.service psacct.service     udev-trigger.service
fedora-readonly.service qemu-guest-agent.service     udisks2.service
fedora-storage-init-late.service quotacheck.service     unbound-keygen.service
fedora-storage-init.service quotaon.service     unbound.service
fedora-wait-storage.service rc-local.service     upower.service
firstboot-graphical.service rdisc.service     user@.service
fsck-root.service reboot.service     wpa_supplicant.service
fsck@.service rescue.service     xinetd.service
getty@.service restorecond.service     yum-updatesd.service
gpm.service rngd.service     zvbid.service

Немало!

Первейшее, что нас должно интересовать, это диагностика того, в каком текущем состоянии находится тот или иной из этих сервисов. Вот как выглядит диагностика для сервиса, например, /usr/lib/systemd/system/dnsmasq.service когда он активный (выполняющийся) и остановленный, соответственно:

$ service dnsmasq status
Redirecting to /bin/systemctl status  dnsmasq.service
dnsmasq.service - DNS caching server.
 Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled)
 Active: active (running) since Tue, 23 Oct 2012 11:27:42 +0300; 8h ago
Process: 729 ExecStart=/usr/sbin/dnsmasq -s $HOSTNAME (code=exited, status=0/SUCCESS)
Main PID: 754 (dnsmasq)
 CGroup: name=systemd:/system/dnsmasq.service
 └ 754 /usr/sbin/dnsmasq -s notebook

Oct 23 11:27:42 notebook dnsmasq[754]: started, version 2.63rc6 cachesize 150
Oct 23 11:27:42 notebook dnsmasq[754]: compile time options: IPv6 GNU-getopt DBus no-i18n no-IDN DHCP DHCPv6 n...track
Oct 23 11:27:42 notebook dnsmasq-dhcp[754]: DHCP, IP range 192.168.1.120 -- 192.168.1.159, lease time 12h
Oct 23 11:27:42 notebook dnsmasq[754]: using nameserver 4.2.2.6#53
Oct 23 11:27:42 notebook dnsmasq[754]: using nameserver 8.8.4.4#53
Oct 23 11:27:42 notebook dnsmasq[754]: using nameserver 192.168.1.1#53
Oct 23 11:27:42 notebook dnsmasq[754]: cleared cache

# service dnsmasq status
Redirecting to /bin/systemctl status  dnsmasq.service
dnsmasq.service - DNS caching server.
 Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled)
 Active: inactive (dead) since Tue, 23 Oct 2012 19:38:40 +0300; 3s ago
Process: 729 ExecStart=/usr/sbin/dnsmasq -s $HOSTNAME (code=exited, status=0/SUCCESS)
Main PID: 754 (code=exited, status=0/SUCCESS)
 CGroup: name=systemd:/system/dnsmasq.service

Запуск, остановку и перезапуск этого сервера делаем командами:

# service dnsmasq stop
Redirecting to /bin/systemctl stop dnsmasq.service

# service dnsmasq start
Redirecting to /bin/systemctl start dnsmasq.service

# service dnsmasq restart
Redirecting to /bin/systemctl restart dnsmasq.service

Из листинга команд уже понятно, что команда service делает всего лишь переадресацию к команде systemctl, поэтому прямая форма обсуждаемых действий могла бы выглядеть как-то так:

# systemctl stop dnsmasq.service

$ systemctl status dnsmasq.service
dnsmasq.service - DNS caching server.
 Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled)
 Active: inactive (dead) since Tue, 23 Oct 2012 19:46:28 +0300; 24s ago
Process: 7190 ExecStart=/usr/sbin/dnsmasq -s $HOSTNAME (code=exited, status=0/SUCCESS)
Main PID: 7192 (code=exited, status=0/SUCCESS)
 CGroup: name=systemd:/system/dnsmasq.service

# systemctl start dnsmasq.service

$ systemctl status dnsmasq.service
dnsmasq.service - DNS caching server.
 Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled)
 Active: active (running) since Tue, 23 Oct 2012 19:48:29 +0300; 2s ago
Process: 7249 ExecStart=/usr/sbin/dnsmasq -s $HOSTNAME (code=exited, status=0/SUCCESS)
Main PID: 7251 (dnsmasq)
 CGroup: name=systemd:/system/dnsmasq.service
 └ 7251 /usr/sbin/dnsmasq -s notebook

При запуске и остановке сервиса выводятся последние строки системного журнала, относящиеся непосредственно к обслуживаемому сервису.

Такие действия (запуск, останов) носят однократный характер, то есть относятся только к текущему сеансу. Это ручное управление сервисом. Если же мы хотим, чтобы сервис подымался автоматом при каждой загрузке системы, то пользуемся другой формой команды управления:  

# service dnsmasq enable

Redirecting to /bin/systemctl enable dnsmasq.service
ln -s '/usr/lib/systemd/system/dnsmasq.service' '/etc/systemd/system/multi-user.target.wants/dnsmasq.service'

# service dnsmasq disable
Redirecting to /bin/systemctl disable dnsmasq.service
rm '/etc/systemd/system/multi-user.target.wants/dnsmasq.service'


Как легко видеть, в такой форме команда также переадресуется к команде systemctl, но та просто создаёт ссылку из каталога (/etc/systemd/system/multi-user.target.wants) конфигурации нужного уровня загрузки (см. далее) на файл сервиса. В принципе, вы можете это сделать и вручную.

Замечания о совместимости


Команда service существовала и в прежней системе инициализации System V, но смысл её был другой: она выполняла инициализирующие скрипты для сервисов, расположенные в каталоге  /etc/init.d. Поле команды (3-й параметр service) определяется конкретным сервисом, но, как минимум, включает возможности start и stop.

Таким образом, выполнение команды service совместимо по синтаксису с привычным и при использовании systemd, однако ссылаемые командой сервисы описываются совсем в другом каталоге (/lib/systemd/system/). И если только сервис не найден в числе управляемых systemd, для совместимости осуществляется обработка сервисов (небольшого числа), оставшихся в /etc/init.d, например:

$ ls /etc/init.d
ceph  functions  hsqldb  ipsec livesys  livesys-late  netconsole  network  puppet  rfremixconf  spice-vdagentd  tcsd  wine

# service wine stop
Stopping wine (via systemctl):                             [  OK  ]

# service wine start
Starting wine (via systemctl):                             [  OK  ]

$ service wine status
Обработчики двоичного формата Wine зарегистрированы.

Уровни загрузки


В традиционной (System V) схеме инициализации в процессе загрузки, после инициализации ядра, ядро запускает /sbin/init как первый процесс пользовательского режима. init отвечает за всю дальнейшую загрузку системы. В операционных системах UNIX/Linux с помощью init можно изменить уровень инициализации. Уровень инициализации — степень загрузки операционной системы. При этом процесс init запускается и анализирует файл /etc/inittab. Это то, что мы могли выполнять командами вида:

# init 3

При переходе к systemd файл /etc/inittab игнорируется, а концепция уровней загрузки - отменяется, вместо неё вводится понятие цели (target). Какие цели доступны systemd смотрим там же:

$ cd /lib/systemd/system/

$ ls -w120 *.target
anaconda.target      halt.target nss-lookup.target runlevel1.target  sockets.target
basic.target     hibernate.target nss-user-lookup.target  runlevel2.target  sound.target
bluetooth.target     http-daemon.target poweroff.target runlevel3.target  suspend.target
cryptsetup.target    kexec.target printer.target runlevel4.target  swap.target
ctrl-alt-del.target  local-fs-pre.target reboot.target runlevel5.target  sysinit.target
default.target     local-fs.target remote-fs-pre.target runlevel6.target  syslog.target
emergency.target     mail-transfer-agent.target  remote-fs.target shutdown.target   systemd-timedated-ntp.target
final.target     multi-user.target rescue.target sigpwr.target   time-sync.target
getty.target     network.target rpcbind.target sleep.target   umount.target
graphical.target     nfs.target runlevel0.target smartcard.target


Уровень загрузки для сеанса мог быть только единый (например: 2 - загрузка в многопользовательском режиме без поддержки сети, 3 - загрузка в многопользовательском режиме с поддержкой сети, 5 - загрузка в многопользовательском режиме с поддержкой сети и графического входа в систему). Целей же, при инициализации сеанса, может быть несколько.

Теперь для того, чтобы переключиться на 3-й уровень загрузки, выполняем команду:

# systemctl enable multi-user.target
...


А для того, чтобы переключиться на 5-й уровень загрузки:

# systemctl enable graphical.target
...

Для достижения каждой цели systemd хранит зависимости других целей и сервисов, необходимых для инициализации требуемой цели. Вот как можно рассмотреть зависимости, требуемые для достижения цели multi-user.target : 

$ systemctl show -p "Wants" multi-user.target
Wants=systemd-update-utmp-runlevel.service crond.service gpm.service ksmtuned.service NetworkManager.service sm-client.service atd.service ksm.service abrtd.service abrt-oops.service multipathd.service sshd.service auditd.service cups.path remote-fs.target rpcbind.service rsyslog.service chronyd.service abrt-ccpp.service xinetd.service mdmonitor.service avahi-daemon.service irqbalance.service mcelog.service sendmail.service arp-ethers.service abrt-vmcore.service nfs-lock.service dnsmasq.service plymouth-quit.service
 bus.service systemd-logind.service systemd-ask-password-wall.path systemd-user-essions.service getty.target plymouth-quit-wait.service tcsd.service wine.service livesys.service livesys-late.service

P.S. Весь этот вывод осуществляется единой чудовищно длинной строкой, поэтому для изучения его нужно куда-то (в файл) переадресовать.