В течении многих лет в подавляющем большинстве Linux систем использовался менеджер инициализации
sysvinit
(
Содержание
SysV && Upstart
Назначение sysvinit
— запуск пространства пользователя: во время загрузки ядро запускает процесс с PID == 1 с именем init
, который запускает все остальные процессы и является их «родителем»:
$ pstree init─┬─ModemManager───2*[{ModemManager}] ├─NetworkManager─┬─2*[dhclient] │ ├─dnsmasq │ └─3*[{NetworkManager}] ├─accounts-daemon───2*[{accounts-daemon}] ├─acpid ├─bluetoothd ...
sysvinit
и upstart
запускают процессы по очереди, в зависимости от его
# ls -l /etc/ | grep "rc[0-9].d" drwxr-xr-x 2 root root 4096 кві 29 11:59 rc0.d drwxr-xr-x 2 root root 4096 кві 29 11:59 rc1.d drwxr-xr-x 2 root root 4096 кві 29 11:59 rc2.d drwxr-xr-x 2 root root 4096 кві 29 11:59 rc3.d drwxr-xr-x 2 root root 4096 кві 29 11:59 rc4.d drwxr-xr-x 2 root root 4096 кві 29 11:59 rc5.d drwxr-xr-x 2 root root 4096 кві 29 11:59 rc6.d
В зависимости от операционной системы — назначение уровней может варьироваться, но в любой системе есть три общих уровня:
- level 0: выключение системы
- level 1: Single-user (resque) mode
- level 6: перезагрузка
Уровни 2-5:
- level 2: RHEL/CentOS — многопользовательский режим без поддержки сети, Debian/Ubuntu — ссылка на level 5 и загрузка полноценной системы
- level 3: RHEL/CentOS — многопользовательский режим с поддержкой сети
- level 4: не используется
- level 5: RHEL/CentOS — многопользовательский режим с поддержкой сети и X-Windows системой
Затем менеджер проверяет зависимости запущенного процесса, ожидает его полного запуска — и только после этого переходят к запуску следующего процесса из списка init-файлов в /etc/rcN.d
, в зависимости от номера в имени скрипта:
# ls -l /etc/rc2.d/ total 4 -rw-r--r-- 1 root root 677 лют 17 06:59 README lrwxrwxrwx 1 root root 20 бер 9 10:23 S20kerneloops -> ../init.d/kerneloops lrwxrwxrwx 1 root root 15 бер 9 10:23 S20rsync -> ../init.d/rsync lrwxrwxrwx 1 root root 24 кві 1 11:28 S20screen-cleanup -> ../init.d/screen-cleanup ... lrwxrwxrwx 1 root root 18 бер 9 10:23 S99ondemand -> ../init.d/ondemand lrwxrwxrwx 1 root root 18 бер 9 10:23 S99rc.local -> ../init.d/rc.local
S99rc.local
будет выполняться последним, т.к. имеет самый большой номер — 99.
Из-за вынужденного ожидания запуска каждого демона во время загрузки — системы с SysV и Upstart загружались сравнительно долго.
Systemd
Для улучшения ситуации и улучшения управления зависимостями во время запуска служб — появилась система systemd
.
На самом деле, запускаемому демону не важно — запущен ли демон, о которого он зависит, или нет. Новому процессу достаточно получить доступ к
Увидеть их можно с помощью netstat
, lsof
и т.п.:
# netstat -a --protocol=unix | head -n 5 Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node Path unix 2 [ ACC ] STREAM LISTENING 16763 @/tmp/.ICE-unix/2633 unix 2 [ ACC ] STREAM LISTENING 15724 /tmp/.X11-unix/X0 unix 2 [ ACC ] STREAM LISTENING 17454 /run/user/1000/keyring-bRTxOS/control ...
Таким образом — можно одним шагом создать все сокеты, а вторым — запустить демоны, которые эти сокеты используют. Все запросы к демону, который ещё не запущен — будут записаны в
# sysctl net.core.rmem_max net.core.rmem_max = 212992 # sysctl net.core.wmem_max net.core.wmem_max = 212992
и переданы демону после его запуска.
Ещё один недостаток sysvinit
— это необходимость всякий раз помнить о правильном порядке очеди запуска служб, например — выполнять запуск ntpd
после запуска самой сети. Кроме того — вам необходимо запускать все службы во время загрузки системы, так как после её старта — sysvinit
уходит в «спячку» и запускать службы вам придётся уже вручную.
Systemd
Общую схему работы systemd
можно представить так:
systemd
использует «агрессивную параллелизацию», используя сокеты и cgroups
В отличии от SysV — в Systemd нет понятия «runlevel«, а вместо этого используются концепция «целей» (targets).
Такие target-ы всегда имеют расширение .target
, и единственное их предназначениие — группровка различных юнитов, через цепочку зависимостей.
Например — юнит graphical.target
, который используется для запуска графической сессии, запускает такие сервисы как gdm.server
) или службу учётных записей (accounts-daemon.service
) и активирует юнит multi-user.target
. Аналогично — multi-user.target
юнит запускает другие необходимые службы, такие как NetworkManager.service
) или D-Bus (dbus.service
) и активирует юнит basic.target
.
Для сравнения SystmV/Upstart и Systemd — можно использовать такую таблицу:
Runlevel | Target Units | Description |
---|---|---|
0 |
runlevel0.target , poweroff.target |
Shut down and power off the system. |
1 |
runlevel1.target , rescue.target |
Set up a rescue shell. |
2 |
runlevel2.target , multi-user.target |
Set up a non-graphical multi-user system. |
3 |
runlevel3.target , multi-user.target |
Set up a non-graphical multi-user system. |
4 |
runlevel4.target , multi-user.target |
Set up a non-graphical multi-user system. |
5 |
runlevel5.target , graphical.target |
Set up a graphical multi-user system. |
6 |
runlevel6.target , reboot.target |
Shut down and reboot the system. |
Пример graphical.target
из Ubuntu 16:
$ cat /lib/systemd/system/graphical.target # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Graphical Interface Documentation=man:systemd.special(7) Requires=multi-user.target Wants=display-manager.service Conflicts=rescue.service rescue.target After=multi-user.target rescue.service rescue.target display-manager.service AllowIsolate=yes
Systemd использует несколько каталогов для файлов конфигурации и юнит-файлов.
Для Ubuntu 16 это:
/etc/systemd/system
и/etc/systemd/user
— локальные файлы конфигурации/lib/systemd/system
и/usr/lib/systemd/user
— файлы юнитов установленных приложений
Про создание файлов юнитов и добавление служб к автозапуску — в другом посте.
Что бы просмотреть все зависимости отдельного юнита — используйте list-dependencies
[service name], например:
# systemctl list-dependencies multi-user.target multi-user.target ● ├─console-setup.service ● ├─cron.service ● ├─dbus.service ● ├─grub-common.service ● ├─irqbalance.service ● ├─networking.service ● ├─nginx.service ...
cgroups
cgroups
systemd
.
Из
«Control groups предоставляют механизм для объединения/разделения наборов задач (процессов) и их потомков в иерархические группы с определённым поведением».
Другими словами — cgroups
имеет возможность управлять, ограничивать и выделять ресурсы различными способами. cgroups
активно используется systemd
для работы с таргетами.
Для просмотра таких групп — используйте systemd-cgls
:
# systemd-cgls Control group /: -.slice ├─init.scope │ └─1 /sbin/init ├─system.slice │ ├─dbus.service │ │ └─520 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation │ ├─cron.service │ │ └─499 /usr/sbin/cron -f │ ├─lvm2-lvmetad.service │ │ └─280 /sbin/lvmetad -f │ ├─ifup@enp0s3.service │ │ └─712 /sbin/dhclient -1 -v -pf /run/dhclient.enp0s3.pid -lf /var/lib/dhcp/dhclient.enp0s3.leases -I -df /var/lib/dhcp/dhclient6.enp0s3.leases enp0s3 │ ├─nginx.service │ │ ├─19893 nginx: master process /usr/sbin/nginx -g daemon on; master_process on │ │ └─19894 nginx: worker process │ ├─accounts-daemon.service │ │ └─506 /usr/lib/accountsservice/accounts-daemon │ ├─systemd-journald.service ...
Либо — ps
:
# ps xawf -eo pid,user,cgroup,args PID USER CGROUP COMMAND 2 root - [kthreadd] 3 root - \_ [ksoftirqd/0] ... 520 message+ 8:pids:/system.slice/dbus.s /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 712 root 8:pids:/system.slice/ifup@e /sbin/dhclient -1 -v -pf /run/dhclient.enp0s3.pid -lf /var/lib/dhcp/dhclient.enp0s3.leases -I -df /var/lib/dhcp/dhclient6.enp0s3.leases enp0s3 740 root 8:pids:/system.slice/ssh.se /usr/sbin/sshd -D 19210 root 8:pids:/user.slice/user-900 \_ sshd: vagrant [priv] 19236 vagrant 8:pids:/user.slice/user-900 | \_ sshd: vagrant@pts/0 19237 vagrant 8:pids:/user.slice/user-900 | \_ -bash 19333 root 8:pids:/user.slice/user-900 | \_ sudo -s 19334 root 8:pids:/user.slice/user-900 | \_ /bin/bash 20088 root 8:pids:/user.slice/user-900 | \_ ps xawf -eo pid,user,cgroup,args 19393 root 8:pids:/user.slice/user-900 \_ sshd: vagrant [priv] 19414 vagrant 8:pids:/user.slice/user-900 \_ sshd: vagrant@pts/1 19415 vagrant 8:pids:/user.slice/user-900 \_ -bash 755 root 8:pids:/system.slice/system /sbin/agetty --noclear tty1 linux 762 ntp 8:pids:/system.slice/ntp.se /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 108:114 787 root 8:pids:/system.slice/vboxad /usr/sbin/VBoxService --pidfile /var/run/vboxadd-service.pid 19212 vagrant 8:pids:/user.slice/user-900 /lib/systemd/systemd --user 19217 vagrant 8:pids:/user.slice/user-900 \_ (sd-pam) 19893 root 8:pids:/system.slice/nginx. nginx: master process /usr/sbin/nginx -g daemon on; master_process on; 19894 www-data 8:pids:/system.slice/nginx. \_ nginx: worker process
Что бы определить таргет, который запускается по умолчанию — используйте get-default
:
$ systemctl get-default graphical.target
Это команада использует файл /lib/systemd/system/default.target
(/etc/systemd/system/default.target
в RHEL/CentOS), который является симлинком на юнит-файл таргета, который будет запущен:
# ls -l /lib/systemd/system/default.target lrwxrwxrwx 1 root root 16 Apr 25 11:56 /lib/systemd/system/default.target -> graphical.target
Отобразить все загруженные в данный момент таргеты:
# systemctl list-units --type target UNIT LOAD ACTIVE SUB DESCRIPTION basic.target loaded active active Basic System cryptsetup.target loaded active active Encrypted Volumes getty.target loaded active active Login Prompts ... sysinit.target loaded active active System Initialization time-sync.target loaded active active System Time Synchronized timers.target loaded active active Timers 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. 19 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'.
По умолчанию — тут отображатся только активные таргеты. Что бы вывести все — добавьте --all
:
# systemctl list-units --type target --all
Для перевода системы в однопользовательский режим (Resque mode) — выполните:
# systemctl rescue
Она аналогична команде:
# systemctl isolate rescue.target
однако дополнительно отрпавляет сообщение всем активным пользователям системы.
Для перевода системы в Emergency mode — выполните:
# systemctl emergency
В Emergency mode — система монтирует /
в режим только чтение и оставляет минимально необходимый набор служб.
Ссылки по теме
Linux: определить init систему – Systemd vs Upstart