Инициализация системы Linux
Общие понятия
Диспетчер служб — это первая программа, запускаемая ядром в процессе загрузки, поэтому ее PID (идентификационный номер процесса) всегда равен 1
Помимо ядра, операционная система зависит от других компонентов, обеспечивающих выполнение необходимых функций. Многие из этих компонентов загружаются в процессе инициализации системы и представляют собой как простые сценарии командной оболочки, так и более сложные служебные программы. Сценарии часто используются для выполнения краткосрочных задач, которые запускаются и завершаются в процессе инициализации системы. Службы, также известные как демоны, могут работать постоянно, поскольку они отвечают за внутренние процессы операционной системы.
Инициализация операционной системы начинается с того, что загрузчик загружает ядро в оперативную память. Затем ядро берёт на себя управление центральным процессором и начинает определять и настраивать фундаментальные аспекты операционной системы, такие как базовая конфигурация оборудования и адресация памяти.
Затем ядро откроет initramfs (начальную файловую систему в оперативной памяти). Initramfs — это архив, содержащий файловую систему, которая используется в качестве временной корневой файловой системы во время загрузки. Основная цель файла initramfs — предоставить необходимые модули, чтобы ядро могло получить доступ к «настоящей» корневой файловой системе операционной системы.
Как только корневая файловая система будет доступна, ядро смонтирует все файловые системы, настроенные в /etc/fstab, а затем запустит первую программу — утилиту под названием init. Программа init отвечает за запуск всех сценариев инициализации и системных демонов. Помимо традиционного init, существуют и другие реализации системных инициализаторов, например systemd и Upstart. После загрузки программы initramfs удаляется из оперативной памяти.
Стандарт SysV
Диспетчер служб, основанный на стандарте SysVinit, определяет, какие демоны и ресурсы будут доступны, используя концепцию уровней выполнения. Уровни выполнения пронумерованы от 0 до 6 и разработаны разработчиками дистрибутива для решения конкретных задач. Во всех дистрибутивах используются только уровни выполнения 0, 1 и 6.
systemd
systemd — это современный менеджер систем и сервисов с уровнем совместимости для команд и уровней выполнения SysV. systemd имеет параллельную структуру, использует сокеты и D-Bus для активации сервисов, запуска демонов по требованию, мониторинга процессов с помощью cgroups, поддержки моментальных снимков, восстановления системных сеансов, управления точками монтирования и управления сервисами на основе зависимостей. В последние годы большинство крупных дистрибутивов Linux постепенно переходят на systemd в качестве системного менеджера по умолчанию.
Как и systemd, Upstart является заменой init. Основная задача Upstart — ускорить процесс загрузки за счёт параллельной загрузки системных служб. Upstart использовался в дистрибутивах на базе Ubuntu в предыдущих версиях, но сегодня его вытеснил systemd.
Была когда то система инициализации init (SysVinit). Скрипты управления службами лежат в /etc/init.d/. Для автозапуска этих скритов используется 7 уровней запуска(runlevels).
0 - остановка системы
1 - режим восстановления или однопользовательский режим
2-3 - многопользовательский с поддержкой и без поддержки сети
5 - графический режим
6 - перезагрузка
Для каждого из этих уровней в директории /etc/ свой каталог rc_номер_уровня.d
В каждом таком каталоге хранятся символические ссылки на скрипты в папке /etc/init.d
При выборе уровня инициализации запускаются скрипты из соответствующего каталога.
Каждый симлинк начинается с буквы которая соответствует действию в скрипте службы:
S start
K stop
За буквой следует число(приоритет) порядка запуска, чем больше число, тем выше приоритет.
Какой уровень будет выполнятся в системе, задается в /etc/inittab
Все скрипты запускаются последовательно, эту концепцию изменилась в системе инициализации Upstart(Ubuntu), которая сменилась СИ Systemd.
Systemd - подсистема инициализации и управления службами и не только...
Systemd нарушает главный принцип unix-way "одна программа-одна функция", применяет агрессивную параллелизацию
Systemd оперирует файлами конфигурации - модулями(unit). unit это основная сущность Sd, это не просто shell скрипт.
Существует несколько типов unit, например service, который используется для старта, остановки, перезапуска сервиса.
unit это текстовый ini файл разделенный на секции с параметрами.
Юниты хранятся в следующих каталогах:
/usr/lib/systemd/ - системные юниты
/etc/systemd/system - юниты администратора
/run/systemd/ - динамически создаваемые юниты
unit - служба(точка монтирования, устройство, файл, виртуальная машина)
Дополнительные модули не относятся к управляемым сервисам:
.target - группирует модули
.service - запуск служб
.timer - запуск модулей по расписанию
.path - управляет иерархией файловой системы
и др.
Systemd в отличии от традиционной SystemV, контролирует состояние служб, в зависимости от изменения их состояния.
Исходные коды менеджера устройств udev объединены в Systemd
Возможности:
Автомонтирование томов и сетевых ресурсов, как замена mount и fstab
journalctl - служба журналирования
systemd-analyse - анализ скорости и запуска служб
systemd-boot - UEFI загрузчик(замена grub)
смена корня, как замена chroot
запуск сервисов по расписанию, как замена cron
активация сокет служб(замена inetd)
service - аналог демона
target - описывает группу юнитов, директория с симлинками на другие юниты.
Являются аналогами уровней в SysVinit. Например target с именем multi-user это аналог 2-3 уровня в SysVinit. По умолчанию запускается default target (graphical.target 5 уровень)
device - подключенное устройство
timer - подобно крону может запускать юниты
slice - группирует другие юниты в cgroups, задет ограничение по используемым ресурсам
mount - точка монтирования файловой системы, где имя юнита это путь до точки монтирования
socket - запускается при подключении к конкретному сокету
path - запуск сокета при доступе к пути файловой системы
cgroups - способ объединения процессов с целью добавления общих правил или ограничений.
SysVinit
SysVinit, предоставляет заранее заданные наборы системных состояний, называемые уровнями выполнения, и соответствующие им файлы служебных скриптов для выполнения. Уровни выполнения пронумерованы от 0 до 6 и обычно используются для следующих целей:
Уровень выполнения 0 Завершение работы системы.
Уровень выполнения 1, s или одиночный Однопользовательский режим без доступа к сети и других второстепенных функций (режим обслуживания).
Уровень выполнения 2, 3 или 4 Многопользовательский режим. Пользователи могут входить в систему через консоль или по сети. Уровни выполнения 2 и 4 используются редко.
Уровень выполнения 5 Многопользовательский режим. Эквивалентен режиму 3, плюс вход в графическом режиме.
Уровень выполнения 6 Перезагрузка системы.
Программа, ответственная за управление уровнями выполнения и связанными демонами / ресурсами, является /sbin/init. Во время инициализации системы init программа идентифицирует запрошенный уровень выполнения, определенный параметром ядра или в /etc/inittab файле, и загружает соответствующие скрипты, перечисленные там для данного уровня выполнения. Каждый уровень выполнения может иметь множество связанных служебных файлов, обычно скриптов в /etc/init.d/ каталоге.
Синтаксис файла /etc/inittab имеет следующий формат:
id:runlevels:action:process
id — это общее название длиной до четырех символов используемое для идентификации записи
Запись runlevels представляет собой список номеров уровней выполнения, для которых должно быть выполнено указанное действие.
action определяет, как init будет выполнять процесс, указанный термином process.
Доступные действия:
boot - Процесс будет выполнен во время инициализации системы. Поле runlevels игнорируется.
bootwait - Процесс будет выполняться во время инициализации системы, и init будет приостановлен до его завершения. Поле runlevels игнорируется.
sysinit - Процесс будет выполнен после инициализации системы независимо от уровня выполнения. Поле runlevels игнорируется.
wait - Процесс будет выполняться для указанных уровней выполнения, и init будет ожидать его завершения, чтобы продолжить работу.
respawn - Если процесс будет прерван, он перезапустится.
ctrlaltdel - Процесс будет выполнен, когда процесс инициализации получит сигнал SIGINT, который активируется при нажатии последовательности клавиш Ctrl+Alt+Del.
Уровень выполнения по умолчанию — тот, который будет выбран, если в качестве параметра ядра не указан другой, — также определяется в /etc/inittab
В записи id:x:initdefault. x — это номер уровня выполнения по умолчанию. Это число никогда не должно быть равно 0 или 6, так как в этом случае система выключится или перезагрузится сразу после завершения процесса загрузки
Ниже приведен пример файла /etc/inittab:
# Уровень выполнения по умолчанию
id:3:initdefault:
# Скрипт конфигурации, выполняемый при загрузке
si::sysinit:/etc/init.d/rcS
# Действие при уровне выполнения S (для одного пользователя)
~:S:wait:/sbin/sulogin
# Конфигурация для каждого уровня выполнения
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Действие при нажатии клавиш Ctrl+Alt+Del
ca::ctrlaltdel:/sbin/shutdown -r now
# Включение консолей для уровней выполнения 2 и 3
1:23:respawn:/sbin/getty tty1 VC linux
2:23:respawn:/sbin/getty tty2 VC linux
3:23:respawn:/sbin/getty tty3 VC linux
4:23:respawn:/sbin/getty tty4 VC linux
# Для уровня выполнения 3 также включите последовательные
# терминалы ttyS0 и ttyS1 (модемные) консоли
S0:3:respawn:/sbin/getty -L 9600 ttyS0 vt320
S1:3:respawn:/sbin/mgetty -x0 -D ttyS1
Команду telinit q следует выполнять каждый раз после изменения файла /etc/inittab. Аргумент q (или Q) указывает init на необходимость перезагрузки конфигурации. Этот шаг важен для предотвращения остановки системы из-за неправильной конфигурации в /etc/inittab.
Скрипты, используемые init для настройки каждого уровня выполнения, хранятся в каталоге /etc/init.d/. Для каждого уровня выполнения в /etc/ есть соответствующий каталог с именами /etc/rc0.d/, /etc/rc1.d/, /etc/rc2.d/ и т. д., в котором находятся скрипты, которые должны выполняться при запуске соответствующего уровня выполнения.
Поскольку один и тот же скрипт может использоваться для разных уровней выполнения, файлы в этих каталогах являются просто символическими ссылками на реальные скрипты в /etc/init.d/
Первая буква в имени файла со ссылкой в каталоге уровня выполнения указывает, нужно ли запускать или останавливать службу для соответствующего уровня выполнения. Имя файла ссылки, начинающееся с буквы K, указывает на то, что служба будет остановлена при переходе на уровень выполнения (kill). Если имя файла начинается с буквы S, служба будет запущена при переходе на уровень выполнения (start). Например, в каталоге /etc/rc1.d/ будет много ссылок на сетевые скрипты, начинающиеся с буквы K, поскольку уровень выполнения 1 — это однопользовательский уровень выполнения без подключения к сети.
Команда runlevel показывает текущий уровень выполнения системы. Команда runlevel показывает два значения: первое — предыдущий уровень выполнения, второе — текущий уровень выполнения.
Буква N в выводе означает, что уровень выполнения не изменился с момента последней загрузки
С помощью той же программы init можно переключаться между уровнями выполнения в работающей системе без перезагрузки. Для переключения между уровнями выполнения также можно использовать команду telinit. Например, команды telinit 1, telinit s или telinit S переведут систему на уровень выполнения 1.
systemd
В настоящее время systemd — это наиболее широко используемый набор инструментов для управления системными ресурсами и службами, которые в systemd называются юнитами. Юнит состоит из имени, типа и соответствующего файла конфигурации. Например, юнит для процесса httpd (например, веб-сервера Apache) в дистрибутивах на базе Red Hat будет называться httpd.service, а его файл конфигурации — httpd.service (в дистрибутивах на базе Debian этот юнит называется apache2.service).
Существует семь различных типов модулей systemd:
service - Наиболее распространенный тип устройств для активных системных ресурсов, которые можно запускать, останавливать и перезагружать
socket - Тип сокета может быть файловым или сетевым. У всех сокетов есть соответствующий сервисный модуль, который загружается, когда сокет получает запрос.
device - Модуль устройства связан с аппаратным устройством, идентифицируемым ядром. Устройство будет считаться модулем systemd только в том случае, если для этого существует правило udev. Модуль устройства можно использовать для разрешения зависимостей конфигурации при обнаружении определенного оборудования, поскольку свойства из правила udev можно использовать в качестве параметров для модуля устройства.
mount - Точка монтирования — это определение точки монтирования в файловой системе, аналогичное записи в /etc/fstab.
automount - Точка автоматического монтирования — это также определение точки подключения в файловой системе, но монтируется она автоматически. У каждой точки автоматического монтирования есть соответствующая точка подключения, которая активируется при обращении к точке автоматического монтирования.
target - Целевое подразделение — это группа других подразделений, управляемая как единое целое.
snapshot - Снэпшот — это сохраненное состояние менеджера systemd (доступно не во всех дистрибутивах Linux).
Основная команда для управления модулями systemd — systemctl. Команда systemctl используется для выполнения всех задач, связанных с активацией, деактивацией, запуском, остановкой, мониторингом и т. д. модулей. Например, для вымышленного модуля под названием unit.service наиболее распространенными действиями systemctl будут:
systemctl start unit.service
systemctl stop unit.service
systemctl restart unit.service
systemctl status unit.service
systemctl is-active unit.service - Показывает активно, если unit запущено, и неактивно в противном случае.
systemctl enable unit.service - Включает unit, то есть unit будет загружаться при инициализации системы.
systemctl disable unit.service - unit не запустится вместе с системой.
systemctl is-enabled unit.service - Проверяет, начинается ли unit с символа системы. Ответ сохраняется в переменной $?. Значение 0 указывает на то, что unit начинается с символа системы, а значение 1 — на то, что unit не начинается с символа системы.
Команда systemctl также может управлять системными целевыми объектами. Например, модуль multi-user.target объединяет все модули, необходимые для многопользовательской системной среды. Он аналогичен уровню выполнения 3 в системе, использующей SysV.
Команда systemctl isolate переключается между различными целями. Таким образом, чтобы вручную переключиться на цель multi-user, выполните следующую команду:
systemctl isolate multi-user.target
Для уровней выполнения SysV существуют соответствующие цели, от runlevelO.target до runlevel6.target
Однако systemd не использует файл /etc/inittab
Например, чтобы использовать multi-user.target в качестве стандартной цели, в качестве параметра ядра следует указать systemd.unit=multi-user.target. Все параметры ядра можно сделать постоянными, изменив конфигурацию загрузчика.
Другой способ изменить цель по умолчанию — изменить символическую ссылку /etc/systemd/system/default.target, чтобы она указывала на нужную цель. Переопределить ссылку можно с помощью одной команды systemctl:
# systemctl set-default multi-user.target
Можно узнать, какой загрузочный раздел по умолчанию используется в вашей системе, с помощью следующей команды: $ systemctl get-default
Как и в системах, использующих SysV, целевая папка по умолчанию не должна указывать на shutdown.target, поскольку это соответствует нулевому уровню выполнения (завершение работы).
Файлы конфигурации, связанные с каждым модулем, находятся в каталоге /lib/systemd/system/
Команда systemctl list-unit-files выводит список всех доступных модулей и показывает, включены ли они для запуска при загрузке системы.
Опция --type позволяет выбрать только модули определенного типа, например systemctl list-unit-files --type=service и systemctl list-unit-files --type=target.
Активные устройства или устройства, которые были активны во время текущего сеанса работы системы, можно вывести с помощью команды systemctl list-units. Как и опция list-unit-files, команда systemctl list-units --type=service выбирает только устройства типа service, а команда systemctl list-units --type=target — только устройства типа target.
systemd также отвечает за запуск и обработку событий, связанных с энергопотреблением
Команда systemctl suspend переводит систему в режим пониженного энергопотребления, сохраняя текущие данные в памяти
Команда systemctl hibernate копирует все данные из памяти на диск, чтобы можно было восстановить текущее состояние системы после отключения питания.
Действия, связанные с такими событиями, определены в файле /etc/systemd/logind.conf или в отдельных файлах в каталоге /etc/systemd/logind.conf.d/
Однако эту функцию systemd можно использовать только в том случае, если в системе не запущен другой диспетчер питания, например демон acpid. Демон acpid является основным диспетчером энергопотребления в Linux и позволяет более точно настраивать действия, выполняемые в ответ на события, связанные с энергопотреблением, такие как закрытие крышки ноутбука, низкий уровень заряда аккумулятора или уровень заряда батареи.
Upstart
Скрипты инициализации, используемые Upstart, находятся в каталоге /etc/init/. Список системных служб можно вывести с помощью команды initctl list, которая также показывает текущее состояние служб и, при наличии, их PID.
У каждого действия Upstart есть своя отдельная команда. Например, команда start может использоваться для запуска шестого виртуального терминала:
start tty6
Текущее состояние ресурса можно проверить с помощью команды status:
status tty6
А прервать работу сервиса можно с помощью команды stop:
stop tty6
Upstart не использует файл /etc/inittab для определения уровней выполнения, но устаревшие команды runlevel и telinit по-прежнему можно использовать для проверки и переключения между уровнями выполнения.
Upstart был разработан для дистрибутива Ubuntu Linux, чтобы упростить параллельный запуск процессов. Ubuntu перестала использовать Upstart с 2015 года, когда перешла с Upstart на systemd.
Shutdown and Restart
Ккоманда, используемая для выключения или перезагрузки системы, называется shutdown. Команда shutdown добавляет дополнительные функции в процесс выключения: она автоматически уведомляет всех вошедших в систему пользователей предупреждающим сообщением в их сеансах командной оболочки и предотвращает новые входы в систему. Команда shutdown выступает в качестве посредника между процедурами SysV и systemd, то есть выполняет запрошенное действие, вызывая соответствующее действие в диспетчере служб, используемом в системе.
После выполнения shutdown все процессы получают сигнал SIGTERM, за которым следует сигнал SIGKILL, после чего система выключается или меняет свой уровень выполнения. По умолчанию, если не используются параметры -h или -r, система переключается на уровень выполнения 1, то есть в однопользовательский режим. Чтобы изменить параметры по умолчанию для shutdown, команду следует выполнять в следующем синтаксисе:
$ shutdown [опция] время [сообщение]
Параметр time определяет, когда будет выполнено запрошенное действие, и может принимать следующие значения:
hh:mm
В этом формате время выполнения указывается в часах и минутах.
+m - Этот формат указывает, сколько минут нужно подождать перед выполнением.
now или +0 - Этот формат предполагает немедленное выполнение.
Когда процесс получает SIGTERM, он может выполнить необходимые действия для освобождения ресурсов, сохранения данных или завершения текущих операций перед полным прекращением работы.
Реализация SysV допускает ограничение числа пользователей, которые смогут перезапустить компьютер, нажав Ctrl+Alt+Del. Это возможно путем размещения опции -a для shutdown команды, присутствующей в строке, касающейся ctrlaltdel в /etc/inittab файле. Таким образом, только пользователи, имена которых указаны в /etc/shutdown.allow файле, смогут перезапустить систему с помощью комбинации клавиш Ctrl+Alt+Del.
Команду systemctl также можно использовать для выключения или перезагрузки компьютера в системах, использующих systemd. Для перезагрузки системы следует использовать команду systemctl reboot . Для выключения системы следует использовать команду systemctl poweroff
#Команда telinit 6 переключит систему на уровень выполнения 6, то есть перезагрузит ее.
sudo telinit 6
Просмотр юнита
systemctl cat sshd.service
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
WantedBy Указывает уровень запуска в секции install
PIDFile= определяет директорию(путь), чтобы systemd могла отслеживать основной процесс
Restart=always автоматически стартовать сервис если он упал
user, group - пользователь или группа, под которым следует стартовать сервис
Environment=RACK_ENV=production переменные окружения
TimeoutSec= Таймаут отработки команд start stop
OOMScoreAdjust=-100 - запрет убиства сервиса в случае нехватки памяти, где -1000 полный запрет
[Install]
WantedBy=multi-user.target
Alias=sshd.service
В данном примере видно, что юнит делится на секции:
unit
service - тип юнита
install
install - это секция используется командами systemctl enable/disable при добавлении симлинка в определенный target. При выполнении определенного target, будут запущенны группа юнитов.
Description - описание юнита
After Before - порядок запуска указнных юнитов, до или после. В Before юниты не будут запущены, пока текущий блок не будет запущен. В After юниты будут запущены до текущего блока.
Wants - указывает на зависимости которые будут запущены параллельно юниту
BindsTo - аналогична Requires
Requires - указываются зависимости без запуска которых юнит работать не будет.
Conflicts - юниты которые не должны работать одновременно с текущим
Assert - проверяет различные аспекты рабочей среды
ExecStart - указывает как будет запускаться юнит
ExecReload - указывает как будет перечитан конфиг
KillMode - описывает как будет убит процесс
Restart - указывает в каких случаях будет запущен restart юнита
Systemctl
Показать список юнитов:
systemctl list-units
Показать список юнитов, учитывая тип юнитов:
systemctl list-units -t
Показать все юниты, в том числе не активные:
systemctl list-units --all
Показать общее состояние системы и список юнитов которые соответствуют запущенным процессам:
systemctl status
Показать состояние юнита:
systemctl status sshd.service
Добавить юнит в автозагрузку:
systemctl enable sshd.service
Убрать из автозагрузки:
systemctl disable sshd.service
Проверить наличие юнита в автозагрузке:
systemctl is-enabled sshd.service
Чтобы юнит не смог запуститься даже как зависимость, необходимо замаскировать его:
systemctl mask sshd.service
Команда выше создает симлинк на /dev/null в /etc/systemd/system
Обратная команда:
systemctl unmask unit_nameСоответствие target уровням
0 - poweroff.target (half.target)
1 - rescue.target
3 - multi-user.target
5 - graphical.target
6 - reboot.target
Можно запустить нужный target:
systemctl start reboot.target
systemctl reboot #Сокращенный вариант
Убийство юнита:
systemctl kill unit_name
Перезапустить все юниты:
systemctl daemon-reload
Директории systemd
/lib/systemd/system - в этой директории находятся все копии юнитов. Файлы в этом каталоге не редактируются, они переопределяются, используя другое расположение файла. Правильный способ, создать каталог с именем файла с добавлением .d в конце.
Например для сервиса test.service, создать подкаталог test.service.d. В этом каталоге файл с расширением .conf , который и будет переопределять директивы
/run/systemd/system - место для определения run-time юнитов(динамически создаваемые юниты, создаваемые во время выполнения)
Типы systemd unit-файлов
Чтобы посмотреть тип юнита, достаточно посмотреть на его префикс.
.device
.path - использует путь который будет использоваться для активации на основе пути
.timer
.snapshot
.slice
.scope
.socket описывает сетевой IPC-сокет или FIFO буфер который используется для активации сокета. Сокет связана всегда с .service, который будет запущен при socket активности.
.service
.mount
Структура systemd юнита
.automount
.swap - описывает пространство подкачки в системе
.target
Источники
Связанные темы
Структура каталогов linux(Debian)
Сценарий инициализации в Linux
Сброс пароля root в grub (Linux)
Сценарии инициализации в Linux Ubuntu






