LINUX.ORG.RU

systemd — новый подход к инициализации системы

 , , smf, ,


2

2

Lennart Poettering, сотрудник компании Red Hat, представил концепцию принципиально нового механизма управления инициализацией системы — systemd (system daemon), которая вобрала в себя достоинства классического System V init и более современных launchd (Mac OS X), SMF (Solaris) и Upstart (Ubuntu, Fedora), но при этом лишена многих их недостатков. В разработке этого проекта ему помогали сотрудники Red Hat, Novell, IBM, Intel и Nokia.

systemd опирается на современные linux-технологии: cgroups, AutoFS, D-Bus, и при этом совместим с исторически устоявшимися механизмами: init-скриптами, стандартными командами shutdown, poweroff и т.п. Предоставляемый systemd функционал позволяет заменить не только систему инициализации, но и ряд других подсистем, в частности, cron, (x)inetd, xdm/kdm/gdm/..., частично даже SELinux.

Основные идеи, использованные при создании systemd:

  • Контроль над сокетами. Многие демоны, запускаемые при инициализации, взаимодействуют с другими демонами через unix domain и сетевые сокеты, и большинство существующих систем инициализации запускают демона-клиента только после того, как демон-сервер запустится и создаст сокет. Вместо этого, systemd создает сокеты, а затем запускает демонов, передавая им эти сокеты. Даже если демон-клиент запустится быстрее и начнет использовать сокет раньше сервера, ничего страшного не произойдет: его запрос будет буферизован и передан серверу, как только тот сможет его обработать. Такой подход уже используется в Mac OS X (launchd), позволяя этой ОС достигать впечатляющей скорости загрузки.

    Аналогичный принцип используется systemd и при запуске служб, использующих шину D-Bus.

    Кроме того, возможен автоматический запуск служб при обращении к заданным сокетам (см. ниже).

  • Фоновое монтирование. Такие операции, как монтирование, проверка и активация квот файловых систем, занимают весьма значительную долю загрузочного времени. В большинстве современных систем они выполняются последовательно, до запуска всех демонов. systemd же предлагает монтировать не-жизненно-важные ФС только тогда, когда они кому-то понадобятся. Для этого используется механизм AutoFS. Например, многие служебные демоны вовсе не обязаны ждать, пока смонтируется огромный и к тому же зашифрованный /home.

    Разумеется, этот подход неприменим к /, /proc, /sys и т.п.

  • Минимизация числа вспомогательных процессов. В настоящее время значительная часть работ по инициализации производится шелл-скриптами, что приводит к колоссальным времязатратам. В частности, Леннарт пишет:

    On my system the scripts in /etc/init.d call grep at least 77 times. awk is called 92 times, cut 23 and sed 74,

    при этом замечая, что почти каждый такой запуск влечет накладные расходы на поиск библиотек, подгрузку данных интернационализации (i18n) и т.п.

    В качестве альтернативы Леннарт предлагает предлагает переписать критичные участки на C, а также вынести часть функционала в самих демонов и в systemd. Сейчас для systemd уже готовы написанные на C подсистемы монтирования и установки имени хоста. До полной победы, отмечает Леннарт, работа предстоит огромная, но результат того стоит.

  • Отслеживание процессов. В ныне используемых системах инициализации в принципе возможна такая ситуация, когда при неправильном форке процесс может «потеряться». Например, так может произойти с некорректно написанным CGI-приложением, и процесс останется работать даже после остановки веб-сервера.

    Для предотвращения таких ситуаций systemd использует интегрированный в ядро Linux механизм контрольных групп (cgroups). Если приложение не имеет доступа к псевдо-ФС, управляющей работой cgroups, то оно не может самостоятельно покинуть свою группу и «потеряться».

    Также к этой группе задач относится и автоматический перезапуск демонов, перенаправление их stdout/stderr на выбранные TTY или в системный журнал, регистрация всех запусков и остановок служб, и многое другое.

  • Ограничение процессов. systemd предоставляет множество возможностей ограничить или расширить полномочия процессов, контролируя такие параметры, как uid, gid, umask, рабочий и корневой каталоги, класс и приоритет CPU и I/O, наличие доступа на чтение и запись к смонтированным файловым системам и отдельным каталогам и т.п. Также можно использовать возможности по ограничению ресурсов, предоставляемые cgroups.

Базовым элементом systemd являются модули (units), которые связаны между собой и имеют определенный тип. Каждый модуль может требовать для своей работы другие модули, конфликтовать с модулями, запускаться только после или до определенного модуля (директивы конфигурации Requires, Conflicts, Before, After, Wants). Из типов модулей определены:

  • service — обычный демон, поддерживающий операции start, stop, restart, reload. Может быть представлен родным (native) файлом конфигурации systemd или System V init-скриптом.
  • socket. При обращении к сокету генерируется событие, для которого можно настроить обработчик. Например, автоматически запускать определенные службы при обращении к заданному сокету. В этом отношении systemd похож на давно известный (x)inetd, однако при этом поддерживает unix domain сокеты и FIFO.
  • device. Отметив нужные устройства в конфигурации udev, впоследствии можно использовать такие события, как появление и удаление устройства, в качестве событий systemd, назначив на них обработчики. Например, при появлении устройства bluetooth будет запущена соответствующая служба.
  • mount. systemd контролирует все точки монтирования файловых систем. В целях обратной совместимости поддерживается сбор информации о точках монтирования из /etc/fstab.
  • automount. Для помеченных таким образом точек монтирования, монтирование выполняется только при обращении к ним.
  • target. Более гибкий аналог уровней исполнения (runlevels), используемых в System V init. Представляет собой группу служб, объединенных по функциональному назначению. Например, multi-user.target идентичен runlevel 5, а bluetooth.target приводит к инициализации подсистемы bluetooth.
  • snapshot — во многом похож на target. Позволяет «запомнить» существующую конфигурацию units (запущенных служб, открытых сокетов, смонтированных ФС) с тем, чтобы в дальнейшем восстановить это состояние. Позволяет, например, перейти в emergency shell (сейчас это init 1), а затем полностью восстановить набор запущенных служб. Другой пример — выход системы из состояния suspend.

Надо заметить, что systemd отличается от SMF, во-первых, тем, что позволяет оперировать не только зависимостями между службами, но и событиями, например, «готовность устройства» или «обращение к сокету». Во-вторых, systemd использует более простой формат файлов конфигурации (.desktop aka .INI против XML в SMF).

От upstart же systemd отличается более высокой степенью параллелизации, и как следствие, более высокой скоростью загрузки. Например, если демон A требует для работы сокет, открытый демоном B, то upstart сначала запустит демона B, а затем демона A, в то время как systemd создаст сокет сам и запустит обоих демонов одновременно, что занимает примерно в два раза меньше времени. Используемый в upstart принцип, когда ключевыми событиями является лишь запуск и остановка демона, Леннарт и его коллеги считают изначально неэффективным.

Well, the point of the part about Upstart above was to show that the core design of Upstart is flawed, in our opinion. Starting completely from scratch suggests itself if the existing solution appears flawed in its core. However, note that we took a lot of inspiration from Upstart's code-base otherwise.

>>> Подробности

★★★★

Проверено: isden ()
Последнее исправление: isden (всего исправлений: 2)
Ответ на: комментарий от tailgunner

> Об Undefined Behaviour что-нибудь слышал?

гы-гы-гы. и ты же потом выставляешь претензию неясности порядка запуска скриптов апстарту.

я еще и поподробнее отвечу.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> и ты же потом выставляешь претензию неясности порядка запуска скриптов апстарту.

Почитай про апстарт, потом будешь гыгыкать. В sysvinit есть способ пустить 100 сервисов в строшо определенном порядке. В upstart такого нет by design.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

еще раз повторю — твое непонимание в 3 часа ночи говорит не том, что у тебя мозгов нет, а о том, что система кривая

флейм дело хорошее... но мне не ясно, чем может вообще нравится грязный хак, которому место только в инди-скриптах с недельным сроком жизни?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Почитай про апстарт, потом будешь гыгыкать. В sysvinit есть способ пустить 100 сервисов в строшо определенном порядке. В upstart такого нет by design.

и как же апстарт тогда хоть что-то в порядке пускает?

если написать

в файле X001.conf: start on started X000
в файле X002.conf: start on started X001
...
в файле X999.conf: start on started X998

то он по-твоему не запустит их строго по порядку?

Проверить лень, т.к. убунты не держу, а ленни-евский дбас слишком стар для апстарта и бэкпорта не нашел.

У апстарта другая (виндо-подобная:-) проблема есть, если верить поттерингу.

И вообще не верю, что убунта — пример для подражания.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> с мейк-файлом таких проблем не было бы и в 3 часа ночи, т.к. он не уродство

Он - большее уродство с точки зрения автонастройки. Симлинки с номерами можно легко добавлять и удалять автоматически при установке/удалении пакета. А автоматически редактировать make-файл при установке, вписывая запуск в нужное место, практически нереально. То есть его придется писать руками - уродство.

anonymous
()
Ответ на: комментарий от anonymous

>Если вы полагаете, что этого делать не стоит, извольте доказать.

Вообще-то доказывать надо что что-то стоит делать а не наоборот.

Потому что выгода от выкидывания лишних прослоек вполне очевидна.


Ты анегдот про Ландау потерявшего десять страниц вывода знаешь?

Вот если бы вы переписали linux на шарпе или яве, и оно работало быстрее и надёжнее нынешнего сишного варианта


Нынешний вариант - на баше.

r ★★★★★
()
Ответ на: комментарий от anonymous

Симлинки с номерами можно легко добавлять и удалять автоматически при установке/удалении пакета. А автоматически редактировать make-файл при установке, вписывая запуск в нужное место, практически нереально.

как раз наоборот — очень просто

например, для апача можно было бы в /etc/init-make.d/ закинуть файл apache с содержанием:

apache-start: local-fs-start network-start databases-start
        ...
        /etc/init.d/network start
        /etc/init.d/apache start
network-stop: apache-stop
        /etc/init.d/apache stop
        /etc/init.d/network stop
databases-stop: apache-stop
        /etc/init.d/apache stop
        /etc/init.d/databases stop

и дальше для получения целевого мейк-файла можно даже просто cat /init-make.d/* (хотя конечно желательно проверить что все файлы начинаются со строки с нулевой позицией)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

* хотя конечно желательно проверить что все файлы начинаются со строки с алфавитно-цифровым символом в нулевой позиции

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

network-stop: apache-stop
      /etc/init.d/apache stop
      /etc/init.d/network stop

Да уж. Прописывать остановку апача в остановку сети - это Ъ-зависимость. Кто там говорил об интуитивной понятности?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Да уж. Прописывать остановку апача в остановку сети - это Ъ-зависимость. Кто там говорил об интуитивной понятности?

если ты отправляешь машинку в ребут, то *только* так и надо делать (и делается); если же тебе просто надо ifdown eth0 или допустим /etc/init.d/network stop, то никто не мешает *именно* это и сказать

тут есть что покритковать другое :-)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Да уж. Прописывать остановку апача в остановку сети - это Ъ-зависимость. Кто там говорил об интуитивной понятности?

если ты отправляешь машинку в ребут, то *только* так и надо делать (и делается)

Я знаю, как это делается. Но хоть более-менее вменяемый makefile выглядел бы так:


apache-stop: network-stop
   /etc/init.d/apache stop

Заметь отсуствие команды остановки сети в остановке apache. А вообще, правильный makefile был бы:


apache: network

network: local-filesystems

и всё. init сам знает, как запускать и останавливать службы, а порядок их запуска и останова задан зависимостями. И прикинь... это уже есть в LSB init-скриптах.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

я тут ступил, конечно не нужно останавливать сеть при остановке апача, надо останавливать зависящие от него

И прикинь... это уже есть в LSB init-скриптах.

я уж догадался по началу инит-скриптов (и постил тут head /etc/init.d/hal)

там еще есть слабые зависимости, не знаю как насчет них в мейк-файлах

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

вот это:

apache-stop: network-stop

        /etc/init.d/apache stop



точно неправильно; мой вариант тоже неправильный; щас напишу правильный

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru
apache-start: local-fs-start network-start databases-start 
        ... 
        /etc/init.d/network start 
        /etc/init.d/apache start 
network-stop: apache-stop network-abort
network-abort:
        /etc/init.d/network stop 
databases-stop: apache-stop databases-abort
databases-abort:
        /etc/init.d/databases stop
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> network: local-filesystems

кхе-кхе... а это всегда так?

И прикинь... это уже есть в LSB init-скриптах.

мейкфайл приводился для того, чтобы:

1. показать, что и во времена system V можно было сделать неуродский инит;

2. выяснить, насколько язык мейкфайлов ограничен (кстати, я его очень поверхностно знаю) — как там насчет слабых зависимостей и *обращения* зависимостей, чтобы не писать boilerplate правила для стопорения сервисов/unmake?

3. я не знаю как реализована LSB инит-система, но юниксвейно было бы выкусывать зависимости из инит-скриптов, сливать их вместе и напускать на это *отдельную* командно-строчную утилиту (или libутилит-у, ладно) — т.е. я хочу иметь возможность юзать ее и отдельно.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

Можешь не стараться :)

тогда не о чем будет спорить, (а вдруг может случиться, что через мейкфайл это невозможно правильно?)

в файле /etc/init-make.d/apache:

apache-start: local-fs-start network-start databases-start  
        /etc/init.d/apache start
apache-stop: apache-abort
apache-abort:
        /etc/init.d/apache stop
network-stop: apache-stop network-abort 
databases-stop: apache-stop databases-abort

а в других файлах:

network-abort: 
        /etc/init.d/network stop
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

можно даже и сократить:

в файле /etc/init-make.d/apache:

apache-start: local-fs-start network-start databases-start   
        /etc/init.d/apache start 
apache-stop: apache-abort 
apache-abort: 
        /etc/init.d/apache stop
local-fs-stop: apache-stop 
network-stop: apache-stop  
databases-stop: apache-stop

в файле /etc/init-make.d/network:

network-stop: network-abort
network-abort:  
        /etc/init.d/network stop

и в принципе инит-скрипты из init.d вообще становятся не нужны, их можно целиком вписать в мейкфайл вместо строчек /etc/init.d/xxx yyy

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

возможно и тот вариант неправильный, т.к. /etc/init.d/network stop мог выполнится до /etc/init.d/apache stop, так что вот:

в файле /etc/init-make.d/apache:

apache-start: local-fs-start network-start databases-start    
        /etc/init.d/apache start  
apache-stop:  
        /etc/init.d/apache stop 
local-fs-stop: apache-stop  
network-stop: apache-stop   
databases-stop: apache-stop

в файле /etc/init-make.d/network:

network-start:   
        /etc/init.d/network start
network-stop:   
        /etc/init.d/network stop

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> тогда не о чем будет спорить, (а вдруг может случиться, что через мейкфайл это невозможно правильно?)

Интересная задачка. Ну что ж, раз вы так хотите сделать это через Makefile...

#/etc/init-make.d/Makefile
default: runlevel5
halt poweroff shutdown: runlevel0
single: runlevel1
reboot: runlevel6
runlevel0 runlevel1 runlevel2 runlevel3 runlevel4 runlevel5 runlevel6:
        @echo switched to $@
include *.mk
#/etc/init-make.d/network.mk
network_start:
        @echo starting network

network_stop:
        @echo stopping network

runlevel2 runlevel3 runlevel4 runlevel5: network_start
runlevel0 runlevel1 runlevel6: network_stop
#/etc/init-make.d/mysql.mk
mysql_start: network_start
        @echo starting mysql

mysql_stop:
        @echo stopping mysql

network_stop: mysql_stop
runlevel2 runlevel3 runlevel4 runlevel5: mysql_start
runlevel0 runlevel1 runlevel6: mysql_stop

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> 1. показать, что и во времена system V можно было сделать неуродский инит;

Через мейкфайлы он получается еще более уродским. :)

Технически систему костылей сделать можно. Но на практике работать она все равно будет криво.

Скажем, как писать такие файлы для случаев, когда не важно, что будет запущено - sendmail или exim, но как минимум кто-то один из них должен запуститься?

Или, например, в моем примере выше команда `make runlevel2` при активном runlevel5 не должна выполнить ничего. А вместо этого она позапускает все сервисы еще раз. Чтобы это предотвратить придется наворотить еще большую систему костылей.

Кто-то все еще думает что это - лучше, чем цифры? Уж не проще - это точно. ;-)

anonymous
()
Ответ на: комментарий от anonymous

> Кто-то все еще думает что это - лучше, чем цифры? Уж не проще - это точно. ;-)

Не, ну идея-то правильная - граф зависимостей. Но делать его через make - это, конечно, большая ошибка. Полагаю, отцы рассмотрели такой вариант и отказались от него.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Или, например, в моем примере выше команда `make runlevel2` при активном runlevel5 не должна выполнить ничего. А вместо этого она позапускает все сервисы еще раз.

(в результате я понял, каким должен быть полноценный make — он должен поддерживать мягкие зависимости, обращение зависимостей, un-make, re-make и жадные цели a.k.a. runlevels! вполне возможно что даже gnu make это поддерживает, только я это не знаю)

тем не менее даже имеющийся make лучше того init-а, что есть;

цифровые ранлевелы — тоже уродство;

если нам хочется перейти на 2 ранлевел с 5-го — это значит нам хочется стопорнуть иксы и все, что от них зависит:

make -f /etc/init-make.d/Makefile X-STOP

если нам хочется перейти на 1 ранлевел с 2-го — это значит нам хочется стопорнуть все не-сингл-юзерское

make -f /etc/init-make.d/Makefile MULTIUSER-STOP

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

MULTIUSER-START: apache-start
apache-start:  local-fs-start network-start databases-start    
        /etc/init.d/apache start  
apache-stop:  
        /etc/init.d/apache stop
MULTIUSER-STOP: apache-stop 
local-fs-stop: apache-stop  
network-stop: apache-stop   
databases-stop: apache-stop

______________________________________________________

ранлевелы — это тоже makefile target, только в отличие от допустим apache-start, которые запускает *только* необходимое ему, MULTIUSER-START запускает все по-максимуму

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Полагаю, отцы рассмотрели такой вариант и отказались от него.

Сильно сомневаюсь. Вообще софт мне представляется кучей хлама, однако вылизанной настолько сильно, что багов очень мало (впрочем, даже через 30 лет их находят, как недавно пробегала новость).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от anonymous

> Скажем, как писать такие файлы для случаев, когда не важно, что будет запущено - sendmail или exim, но как минимум кто-то один из них должен запуститься?

в дебиан есть debian diversions на эту тему, и с инитом это никак не связано; «минимум одно» — это кривой подход: админ должен четко определять, что конкретно запустится

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Но делать его через make - это, конечно, большая ошибка.

большая, гы-гы. ну так объясни в чем она.

пока что имеем:

1. мейк не требует перенумерации, а цифры требуют

2. мейк требует ручное обращение зависимостей, и цифры требуют ручное обращение зависимостей (As a rule of thumb, the sequence number of the stop link should be 100 minus the sequence number of the start link)

3. мейк требует дополнительный код для re-make и цифры требуют дополнительный (но правда уже написанный) код для оптимизации «при переходе на другой ранлевел не выполнять остановку а затем запуск общего для двух ранлевелов скрипта»;

и вообще п.3 не очень нужен, так как реально нужно что-то типа MULTIUSER-STOP, т.е. ранлевелы все сравнимы по включению (нет несравнимых)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

кстати чувак писавший ман вероятно ошибся, и там должно быть 99 вместо 100

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> 1. мейк не требует перенумерации, а цифры требуют

Цифры тоже не требуют перенумерации. Или можно хоть один пример, когда они ее требуют?

2. мейк требует ручное обращение зависимостей, и цифры требуют ручное обращение зависимостей

Цифры не требуют разбора зависимостей вообще. Это - задача пакетного менеджера. Это в мейках надо думать, например, как бы стартовать IMAP-сервер только после exim-а или sendmail-а, при этом не зная заранее, кто из них будет установлен. А в цифрах - вписал и забыл. :)

3. мейк требует дополнительный код для re-make и цифры требуют дополнительный

Ну да. Только в мейках этот код потребуется в каждом .mk-файле для каждого сервиса. В цифрах нужно указать только одну строчку с цифрами, а в мейках надо еще кучу сопроводительных строк с зависимостями писать. Плюс кучу для отлова текущего состояния сервисов (чтобы не запускать те, что уже запускались и не останавливать уже остановленное).

и вообще п.3 не очень нужен, так как реально нужно что-то типа MULTIUSER-STOP, т.е. ранлевелы все сравнимы по включению (нет несравнимых)

Не нужно. В runlevel-ах нет никаких runlevel-stop и runlevel-start. И не должно быть. Есть просто переход между runlevel-ами. И во время перехода некоторые сервисы запускаются, а некоторые - останавливаются. Например при переходе в runlevel6 останавливается network и запускается reboot.

Речь идет не о том, что через make-файлы это реализовать нельзя. Можно. Но это будет намного более громоздким и сложным, чем через обычные сервисы, а все ради чего?

anonymous
()
Ответ на: комментарий от anonymous

ты явно не понял что я написал — прочитай внимательно мой пост (в т.ч. английский) и придидущие 150 постов треда

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.