Наиболее частые заблуждения про Systemd
Добавлено: Вс ноя 13, 2022 11:22 pm
На протяжении прошедшего года я видел множество часто используемых логически неверных аргументов за использование systemd. В этом блог-посте предполагается представить список общих и неправильных аргументов за использование systemd, которые мне и другим людям пришлось опровергать много раз. Предполагается, что это должен быть живой документ -- я буду пополнять его новыми заблуждениями по мере встречи с ними, и я буду направлять сюда людей, которыe совершают эти ошибки.
Имейте в виду, что этот пост не нацелен быть критикой systemd или его авторов. Примите к сведению, что лично я верю, что вопрос "хорош systemd или плох?" может быть разрешён только в условиях конкретных запросов конкретного пользователя -- systemd хорош для людей, которым он нужен, но возможно менее предпочтителен для остальных.
Заблуждение #1: "Systemd - это множество бинарей, следовательно он не монолитен." В своём блоге Леннарт Поттеринг утверждает, что systemd не монолитен, ссылаясь на то, что он содержит свыше 69 отдельных бинарей. Одно из другого не следует, потому что термины "модульный" и "монолитный" не являются взаимно исключающими. Программное обеспечение является модульным, если его можно разобрать на отдельные функциональные единицы таким образом, чтобы занимался своей задачай. Systemd, ядро Linux и X.org -- примеры модульных программ. Systemd решает свои задачи бинарями, ядро Linux -- загружаемыми модулями, а в X.org -- драйверами и расширениями.
Далее, программное обеспечение является монолитным, если его компоненты (если оно таковые имеет) жёстко связаны -- то есть логически зависят друг от друга до такой степени, что использование их в других окружениях требует повторения реализации зависимых компонентов. В качестве примера можно привести Linux и X.org: в случае с Lunix вы не можете использовать модуль ядра без ядра, ядро не может быть запущено без требуемых ядром модулей для взаимодействия с железом, и вы не можете использовать модуль ядра Linux с другими ядрами, или в качестве независимой программы; точно так же вы не можете использовать видео-драйвер X без X-сервера, вы не можете использовать X-сервер без хотя бы одного видео-драйвера, не можете использовать видео-драйверы X с другими графическими менеджерами, и использовать их в качестве отдельных программ.
Исходя из этих определений, systemd должен считаться одновременно и модульным, и монолитным. Вы не можете использовать journald без systemd. Вы не можете использовать systemd без journald (по крайней мере без потери логгирования в программах, управляемых systemd). Ни одна из *ctl-программ не будет работать без systemd, не будет работать и коллекция демонов systemd-*d. Раньше было возможно запустить logind отдельно, но это уже не так.
По словам разработчиков systemd, udev станет следующим компонентом, жёстко зависимым от systemd. Суть в том, что не смотря на то, что systemd включает в себя множество бинарей, иерархические логические связи между ними означают, что более правильно было бы думать о них, как о расширениях systemd-PID-1, который просто выполняет их в отдельных адресных пространствах. Они не являются по-настоящему независимыми, пригодными для компонования (объединения с другими) программами. Для контраста, примеры модульных не-монолитных программ -- это GNU coreutils, s6 supervisor system, DJB's daemontools, GNU compiler collection. Эти приложения не только разбиты на модули, вы можете использовать эти модули независимо друг от друга в различных окружениях, объединяя/компонуя их вместе для решения более сложных задач, нежели тех, что решают отдельные модули сами по себе.
Таким образом, "модульный - не модульный" и "монолитный - не монолитный" - это вопросы компромиссов. Systemd менее монолитный и более модульный, чем, к примеру, программа "ls". Но он куда более монолитный, нежели любой другой из не монолитных примеров выше из-за логических связей между бинарниками.
Заблуждение #1.1: "Компоненты Systemd имеют хорошо описанные интерфейсы, и поэтому вы можете просто заменить части, которые вам не нравятся" Это рассуждение ошибочно из-за одного упущения. Не все его интерфейсы стабильны, поэтому этот вариант невозможно поддерживать, если только вы не имеете возможности тратить на это всё время. Что особенно важно, так это интерфейс к основному сервисному демону, который не стабилен. Даже сами авторы признают, что некоторые части systemd не могут быть независимо реализованы.
Заблуждение #1.2: "Ядро Linux монолитное, поэтому это нормально, что systemd монолитен". Также вообще не связанные вещи. Следует ли systemd быть монолитным или нет - абсолютно никак не относится к ядру Linux.
Заблуждение #2: "Многие используют systemd, значит ты тоже должен" Классический пример ошибки "большинство не может ошибаться". Припомните, что многие люди и дистрибутивы использовали когда-то sysvinit, но тем не менее это не делало её самой лучшей системой инициализации.
Заблуждение #2.1: "Systemd широко распространился благодаря техническим достоинствам" Это пример бахвальства. Осталось посмотреть, как много людей использует systemd, потому что они явно этого хотят, и сколько людей используют его, потому что их любимые апстримные программы от него зависят, их дистрибутивы перешли на него, или им было предписано перевести на него своё рабочее место. В последних случаях -- установки systemd как средства для использования других программ -- не считается выбором за техническое достоинство.
Почему дистрибутивы принимают systemd, если не за технические достоинства? Большим мотивирующим фактором является то, что наборы других программ (например GNOME) всё более зависят от них в своей работе. Если цель дистрибутива - обеспечить поддержку этих наборов программ для конечных пользователей, тогда утягивание systemd как зависимости означает только одно: они принимают systemd не за техническое превосходство; они принимают его, потому что так будет проще, нежели поддерживать патчи, чтобы держать systemd отдельно.
Говоря о принятии, как мы можем измерить это самое "широкое распространение"? Андроид вероятно самая широко используемая ОС на основе Linux, и он не использует systemd. Возможно наиболее широко распространённый по продажам потребитель GNU/Linux - это ChromeOS, но ChromeOS использует Upstart, и это вероятно не изменится. Так что не понятно, действительно ли systemd -- самая распространённая система в среде Linux. Принятие в дистрибутивах GNU/Linux также не повсеместно.
Gentoo и Slackware -- дистрибутивы для технически подкованных пользователей -- не приняли его за систему инициализации по-умолчанию. Также посмотрите на цифры из Debian popcon для systemd-sysv и sysvinit-core. На время написания данной статьи инсталляций systemd-sysv (которая конфликтует с sysvinit-core) примерно в 3 раза больше, чем sysvinit-core, что примерно соответствует неравенству между мета-пакетами для Xfce 4 и GNOME 3 [1]. Таким образом, несмотря на доступность для всех основных дистрибутивов GNU/Linux, пока преждевременно говорить о всеобщем захвате systemd.
Заблуждение #3: "Людям, которым не нравится systemd, просто неприятны изменения" Ошибка ad hominem. То, что systemd сейчас популярен, вовсе не означает, что он решает проблемы всех людей лучше, чем статус-кво. Люди, которые не используют systemd, часто имеют хорошо обоснованные технические причины, чтобы избегать его, и существует изобилие альтернативных систем инициализации, которые более подходят для их задач. Приятно думать, что технических причин для сохранения существующей системы инициализации нет, потому что systemd обратно совместима с init-скриптами.
Однако такое рассуждение делает много неявных предположений о нуждах пользователя, которые могут быть и не верны. Например: Предполагается, что пользователю комфортно доверять всему коду systemd. Предполагается, что пользователь ещё не делает ничего продвинутого с пространствами имён и cgroups, которые systemd может сломать. Предполагается, что пользователь недоволен текущими настройками управления сервисами, которые systemd мог бы заменить. Предполагается, что у пользователя достаточно RAM, CPU, диска и мощности для того, чтобы добавить systemd на свой компьютер. И это не всегда случай маломощных встраиваемых Linux-систем, где "init" сам мог бы быть просто встраиваемым приложением (NB: я имею в виду действительно маломощные устройства, такие как это, не смартфоны или эквивалентное оборудование).
Предполагается, что пользователь использует относительно свежее ядро Linux. Это также бывает не всегда, в случае использования экзотического оборудования, где проприетарные модули ядра могут держать вас привязанными к старой версии. Предполагается, что у пользователя будет совершенно безпроблемный опыт использования systemd, и ему не придётся потратить неоправданно большое количество времени, чтобы настроить systemd в своём окружении. Предполагается, что пользователь сможет легко мигрировать обратно с systemd, если окажется, что он плохо подходит к задачам. Если пользователь настраивает компьютер, который он/она не сможет легко администрировать (например устройство Интернета Вещей), он должен быть без багов и причуд настолько, насколько это возможно, причём сразу.
Доказано-корректная система инициализации была бы идеальным вариантом, но испытанная и хорошо понятная система предпочтительней непроверенной. Закрывать глаза на требования других людей к системе инициализации, как на неправильные - это отличный способ прослыть троллем. Равно как пытаться рассказывать им, что они не правы в своих требованиях.
Заблуждение #4: "Unit-файлы лучше, чем shell-скрипты" Это ошибочное обобщение, которое игнорирует большинство современных реалий. Не думаю, что сейчас кто-то не согласится, что когда это возможно, чем меньше кода - тем лучше. Как бы то ни было, всё зло в деталях. И есть тонкие, но важные инженерные детали касающиеся управления службами, на которые часто смотрят сквозь пальцы, когда говорят об init-файлах.
Заблуждение #4.1: "Unit-файлы уменьшают сложность" Это пыль в глаза, и подмена одной проблемы на другую. Хотя unit-файлы действительно выглядят проще init-скриптов и могут уменьшить сложность определяемых сервисов, они ни уменьшают сложность системы инициализации, ни уменьшают сложность поиска ошибок в системе инициализации, когда она ведёт себя не правильно (см.
Заблуждение #4.2:. Фактически же, вся сложность, которая была с shell-скриптами в sysvinit (а также с несколькими демонами и инструментами), просто ушла в systemd, который сейчас насчитывает более 275,000 строк кода. Более того, если верить этому анализу, это 245,000 строк кода на C, среди которых 81,000 необходимы, чтобы иметь минимально работающую реализацию (это милосердно исключая systemd-udevd, который добавляет ещё 13,000 строк). К слову о сравнении, не модифицированные init-скрипты на моём ноутбуке с Debian весят чуть больше 10,000 строк (согласно sloccount(1)). Не ясно, как systemd делает загрузку и управление сервисами менее склонной к ошибкам, нежели другие системы, но общая сложность systemd определённо выше, чем у sysvinit.
Заблуждение #4.2: "Shell-скрипты забагованы" Этот отвлекающих манёвр часто используется в спорах против использования shell-скриптов. Но баги присущи не shell-скприптам. Это забагованное ПО забаговано, и нет никакой разницы, на каком языке оно написано. Для тех из вас, кто никогда не дебажил програмы на C (язык, на котором написан systemd), поверьте на слово, что для C это гораздо сложнее, чем для shell-скрипта, потому что куда больше вещей может пойти не так в C. Потому что программист должен не только иметь дело с переменными и контролем потока, но ещё и с управлением памятью, управлением тредами, синхронизацией тредов, управлением файловыми дескрипторами, низкоуровневым IPC, специфичными для CPU моделями памяти, неопределённым поведением C (см. Дополнение J), и ещё кучей других вещей, которые просто неприменимы к рассуждению о поведении shell-скриптов.
Более того, если что-то случается во время загрузки, нет гарантии, что инструменты для дебага C будут доступны -- они могут быть просто установлены на носителе, который монтируется позже процесса загрузки (таком, как /usr или /usr/local). Это проблема не существует при использовании shell-скриптов при загрузке системы. Хотя и правда, что программы, которые запускаются shell-скриптами (как правило) тоже написаны на C, это не умаляет значения вышеописанных претензий. На практике, если shell-скрипт отказывается выполняться, баг почти всегда в скрипте, а не в вышележащей оболочке или программе, которую он запускает. Если же systemd отказывается работать с валидными параметрами unit-файла, то пользователь должен дебажить код systemd, написанный на C, чтобы выяснить почему.
Заблуждение #4.3: "Systemd лучше, потому что она избавилась от shell-скриптов!" Это ещё один отвлекающий манёвр, и скорее мнение, нежели технический аргумент. Как бы то ни было, shell-скрипты никогда не были обязательными, чтобы осуществить начальную загрузку Вашей системы. Ядро и множество других систем инициализации (включая sysvinit) могут быть сконфигурированы, чтобы стартовать произвольную программу, написанную на произвольном языке. Например, система инициализации Pardus Linux использует программы на Python вместо shell-скриптов.
Заблуждение #4.4: "Systemd лучше, потому что он уменьшает дублирование кода shell-скриптов!" Это тоже отвлекающий манёвр. Он отвлекает от факта, что ничто не останавливает пользователя от объединения общего кода init-скриптов в файл, подгружаемый каждым отдельным скриптом. Взгляните на то, что BSD-системы делают с /etc/rc.subr, например -- определения сервисов с BSD-шным rc часто короче unit-файлов!
Заблуждение #5: "Systemd позволяет вам использовать $LINUX_SPECIFIC_FEATURE" И это ещё один отвлекающий манёвр. Ничто не останавливало пользователя взять на вооружение эти Linux-специфичные средства до systemd. Все эти средства по определению должны были предшествовать systemd, прежде чем systemd мог быть написан с их использованием.
Заблуждение #6: "Systemd имеет открытый исходный код, так что если он вам не нравится, вы можете сделать fork". Некоторые люди этим и занимаются, не смотря на то, что systemd -- это большая движущаяся цель. Тем не менее, это утверждение является примером чёрно-белого мышления, которое теряет суть. Пользователь не-systemd часто более заинтересован, чтобы systemd не вторгался в его/её системы. Этот ошибочный аргумент говорит им отфоркать systemd... чтобы им не надо было использовать systemd.
Заблуждение #6.1: "Тем, кто клевещет на systemd, следовало бы прекратить ныть и сделать собственную альтернативу!" Опять же теряем суть, и это смесь чёрно-белого мышления и ошибки ad hominem[g]. Большинство пользователей не-systemd были бы абсолютно счастливы оставить systemd в покое и дать ей делать, что ей надо, для других людей, которые хотят её использовать. Какую бы систему инициализации они сейчас ни использовали, она прекрасно удовлетворяет их потребности. Проблема в том, что проект systemd не хочет оставить их в покое.
Видение systemd Леннарта Поттеринга заключается в том, что он должен стать основой всей ОС. Также он защищал жёсткую зависимость GNOME от logind, и конечно же он ответственен за то, что logind имеет жёсткую зависимость от systemd-в-виде-PID-1. Существует куча систем инициализации, но похоже, только одна из них активно пытается исключить остальные, заставляя не относящееся к ней ПО требовать её для работы. Многие пользователи не-systemd не нуждаются в клоне systemd, потому что они счастливы тем, что они уже имеют. Поэтому нет смысла предлагать им идти работать над клонированием systemd.
Заблуждение #7: "Вам следует использовать systemd, потому что он позволяет вам использовать активацию через сокеты!" Это пропаганда. Systemd не нужен для активации через сокеты, потому что ядро уже дало вам это просто так. Для активации через Интернет-сокеты всё, что пользователь должен сделать - это запустить демона, связать его с портом и оставить его там висеть. Если ядру потребуется память, оно сбросит ненужные демоны на диск. Если ядро получит входящее соединение, оно поднимет демона обратно в RAM, чтобы он смог его обработать. Systemd здесь вообще нет, но она имеет тот же самый эффект. Как дополнительный бонус, подсистема виртуальной памяти ядра удостоверяется, что runtime-состояние демона сохранено между сбросом и восстановлением -- кое-что, чего systemd не позволяет с её видом сокетной активации.
Заблуждение #7.1: "Вам следует использовать systemd, поскольку она позволяет вам назначать, какие цели будут активированы при получении соединения!" Это тоже пропаганда. Xinetd делал это десятилетия. Он может быть настроен на запуск чего угодно, что могло бы вызываться unit-файлами или запуском "systemctl ... enable", с тем же результатом.
Заблуждение #7.2: "Вам следует использовать systemd, поскольку он поддерживает не только сетевые сокеты! Он также поддерживает пайпы и UNIX-сокеты!" Ещё больше пропаганды. Этот маленький скрипт достигает того же эффекта с пайпами: mkfifo /path/to/pipe sh -c 'while true; do cat /path/to/pipe >/dev/null; /path/to/program; done' & Когда программа пишет в /path/to/pipe (например echo "" > /path/to/pipe), будет запущена /path/to/program. Этот скрипт, конечно, может быть расширен для выполнения более сложных задач, наподобие заставить цикл "while" выполнять различные действия в зависимости от того, что вы записали в /path/to/pipe, но суть в том, что активация через пайпы -- это не очень сложно. Похожий скрипт может быть написан для UNIX-сокетов при помощи netcat и socat. Если имеет значение управление жизненным циклом -- например, чтобы убедиться, что пайп или UNIX-сокет всегда отсоединяются, как только программа завершена -- я советую вам взглянуть на runfs.
Заблуждение #7.3: "Вам надо использовать systemd для сокетной активации, поскольку в противном случае вы столкнётесь с условиями гонки при параллельном запуске!" Это уже поучительное запугивание. Во-первых, это не было проблемой десятилетия, и до сих пор ей не является в современных событийно-управляемых системах (например, Android прекрасно обходится без systemd). Во-вторых, параллельный запуск и гарантированное отсутствие условий гонки могут быть достигнуты при простом использовании информации из procfs. Проблема формулируется следующим образом. Предположим, что процесс B зависит от процессов A0, A1, ..., An, которые должны стартовать и слушать сокет, до того, как процесс B стартует. Мы хотим запустить B параллельно с A0...An, но удостовериться, что B не пытается соединиться с любым Ai, пока A0...An не будут слушать.
Решением до systemd было просто запустить A0, A1, ..., An и подождать несколько секунд, чтобы позволит им достигнуть состояния прослушивания перед стартом B. Интуиция подсказывает, что A0...An достигнут состояния прослушивания прежде, чем B подключится, поскольку одна секунда - это очень долго для процесса Ai, чтобы пройти демонизацию через двойной форк и начать слушать сокет. Хотя B может обогнать A0...An и попытаться соединиться до того, как один из них начал слушать, вероятность, что это случится, ничтожна, и это доказано десятилетиями. Теперь предположим для примера, что B всё-таки сумел обогнать какой-то процесс Ai. Что случится? Попытка соединения у B завершится с ошибкой "connection refused", не смотря на то, что A0...An слушают. B не сможет запуститься, если только он не запрограммирован обрабатывать этот случай (например, пытаться соединиться, пока не будут превышены количество попыток или таймаут).
В идеале, B достаточно умён, чтобы делать это самостоятельно. Если нет, то решение с сокетной активацией, предложенное systemd, заключается в модификации A0...An, чтобы они могли получать дескриптор сокета от systemd, который systemd использует, чтобы буферизовать сообщения от B для каждого запускаемого Ai ("socket activation", systemd). Это позволяет B запуститься параллельно с A0...An, в тоже время предотвращая его дальнейшую работу, пока A0...An не начнут слушать. Как бы там ни было, это решение обходится дорого -- оно требует модифицировать O(n) программ, оно будет работать только с systemd, и будет решать проблему, которая на практике редка. Более простая стратегия -- это перебросить информацию в procfs.
Мы можем написать скрипт, который сперва проверял бы дескрипторы сокетов в /proc/A0/fd/, /proc/A1/fd/, ..., /proc/An/fd/, чтобы проверить, находятся ли они в слушающем состоянии путём сверки их inode-чисел с открытыми сокетами в /proc/net/$PROTOCOL. Как только сокеты будут в состоянии прослушивания, скрипт запустит B. Нет необходимости вовлекать сюда systemd, нет необходимости модифицировать A0...An, и решение работает везде, где доступна procfs (а даже если её нет, то только скрипт -- не демоны -- нуждается в модификации, чтобы портировать функциональность "сокетной активации").
Заблуждение #8: "$PROGRAM не зависит от systemd, она просто зависит от чего-то, что реализует интерфейс к systemd" Когда мы говорим об одном из компонентов или интерфейсов, которые не могут быть реализованы независимо (такие, как systemd-logind или API сервисной шины), этот аргумент -- разделение без различий. Это всё равно, что сказать "Internet Explorer не зависит от Microsoft Windows, он просто зависит от чего-то, что реализует интерфейс к Microsoft Windows"! Хотя, конечно, возможно повторить реализацию требуемых частей API, но чтобы сделать это эффективно, надо также повторить реализацию большей части платформы. Так что, если $PROGRAM зависит от одного из этих компонентов или интерфейсов, $PROGRAM требует либо systemd, либо почти полную аналогичную реализацию, делающую её systemd во всём, кроме имени.
Заблуждение #9: "Systemd - это принцип KISS в действии" Это некомпетентность. Принцип KISS ("Keep It Simple, Stupid") относится к дизайну системы, не к интерфейсу пользователя. KISS - это принцип избежания необязательной сложности. Однако, как мы установили в Заблуждении #4.1, минимально-используемый systemd более сложен, чем sysvinit и пытается делать куда больше. Далее, разработчики systemd верят, что повышенная сложность даже в минимальной systemd необходима, чтобы удовлетворить их требованиям. Всё, что я пытаюсь сказать, это то, что эти требования не универсальны, и для многих сложность не оправдана.
Заблуждение #10: "Бинарные логи не являются проблемой на практике" Это может быть или ошибочным обобщением, или неправильным выводом, и часто приводится в контексте типа "Я использовал бинарные логи, следовательно они должны хорошо подойти всем". Вопрос же, на который мы заинтересованы получить ответ, таков: "Позволяют ли формат журнала и средства журналирования записывать множество событий и ошибок, требуемых пользователю, в порядке их появления"? Если ответ "да", то выбор форматирования произвольный, потому что реализация деталей не имеет значения.
В противном случае, если бывают случаи, когда средства журналирования могут вести себя непредсказуемо (например баг в журнале, паника ядра, ошибка железа -- вещи, которые случаются в некоторой степени регулярно), реализация деталей значение имеет, поскольку пользователю придётся вмешаться вручную, чтобы определить последовательность событий и ошибок, приведших к неверному поведению. В этом случае журналирование структурированных бинарных записей почти всегда худшее дизайнерское решение, нежели журналирование неструктурированного человеко-читаемого текста, потому что почти всегда восcтановить чисто-текстовый журнал после не подлежащих исправлению ошибок журналирования (в частности, повреждения) легче.
Повреждение журнала -- это, возможно, самая сложная проблема, с которой сталкиваются средства журналирования, потому что теряется информация. Не смотря на это, человеко-читаемый текст остаётся хотя бы частично читаем при повреждении, поскольку правила, грамматика и семантика письменного языка служит корректирующим ошибки целям, встречающимся в повседневной жизни. Например, пользователь с первого взгляда может сказать, обрезана строка или нет, или потеряны ли одно или несколько слов, или содержатся ли данные, которые не должны быть там (вроде непечатных символов), или что они не удовлетворяют любому ожидаемому формату сообщений журнала. И так далее, просто потому что журналирование только человеко-читаемого текста позволяет пользователю понять, что логгер намеревался записать.
Как бы то ни было, чем больше бинарных данных включается в журнальные записи, тем сложнее становится пользователю разобрать письменный язык, чтобы понять намерения логгера (к примеру, строка случайных символов -- это признак повреждения, или это часть записи, или понемногу и того, и того?). На момент написания этого текста, journald мог повредить журнал просто упав, приводя журнал в состояние, при котором невозможно сказать, повреждён ли он или искажён (разработчики знали об этом годами, и они не считают, что это баг). Сейчас же существует возможность вручную разобрать повреждённый журнал journald, если journalctl не помогает, но это требует больше усилий, чем разбор повреждённого чисто текстового журнала, так как пользователь обязан быть в курсе формата журнала journald, чтобы извлечь человеко-читаемые строки из бинарных записей.
Таким образом, когда приходится иметь дело с ошибками, которые включают в себя повреждение журнала (в случае journald, это все ошибки, которые могут привести к некорректному завершению -- а это именно те ошибки, которые средства журналирования должны отлавливать), чисто текстовый журнал будет почти всегда более удобен в использовании, чем журнал journald. Далее, журналирование journald могло бы быть более устойчивым. Оно могло бы улучшить восстанавливаемость при повреждении путём задействования помехоустойчивого кодирования, хранения бинарных данных в отдельном файле (или кодированием оных в человеко-читаемый текст), реализацией ACID-семантики для записей журнала. Тем не менее, он не делает ничего из этих вещей на момент написания этих строк, что делает его более хрупким в случае ошибки.
Заблуждение #10.1: "Бинарный формат journald позволяет произвести проверки подлинности и целостности" Это пропаганда. Последние реализации syslog тоже это делают, так что это не повод выбирать joutnald.
Заблуждение #10.2: "Бинарный формат journald позволяет ему иметь индекс, что делает доступ к журналу быстрее" Это тоже пропаганда. Хотя никто не спорит, что индексирование увеличит скорость доступа к журналу (по крайней мере в теории), нет также никаких технических причин, почему journald не может хранить индекс отдельно от журнального файла, или почему он не может писать индекс в журнал в виде человеко-читаемого текста.
Заблуждение #10.3: "Всех проблем с journald можно избежать, если заставить его просто перенаправлять всё в syslog" Это предполагает ошибочную предпосылку, что в этом случае в journald есть необходимость. Если всё, что нужно пользователю, это syslog, зачем вообще требовать journald?
Заблуждение #11: "Тем, кому не нравится systemd, на самом деле просто не нравится Леннарт Поттеринг, и это не оправдание, чтобы избегать systemd" Во-первых, тут говорят за пользователей не-systemd (ad hominem). Во-вторых, существует множество корректных не-технических причин, чтобы использовать или избегать программу. И отсутствие веры в то, что ведущий разработчик заботится о ваших интересах -- это одно из них. Экосистема GNU/Linux -- это базар, а не собор. Разработка программного обеспечения в этой области обязательно имеет социальную направленность, потому что дальновидные разработчики, работающие над одним делом, должны общаться, чтобы решать проблемы.
По существу, разработчики культивируют репутацию для их стиля управления, практик написания кода, ответственности за отчёты об ошибках, и так далее. И это справедливо влияет на степень, в которой другие разработчики доверяют друг другу делать хорошую работу в своих проектах (например, Debian когда-то перешёл с GNU libc на EGLIBC, ссылаясь на трения с мейнтейнром GNU libc как на основную причину). Сейчас в некоторых кругах Леннарт Поттеринг получил негативную репутацию за слишком частое нарушение совместимости и отклонение конструктивной критики своих проектов (включая отчёты об ошибках).
Это не нападение на его персону; это критика его стиля управления проектом. Тех пользователей, которых это негативно коснулось, это заставило серьёзно почувствовать, что systemd надо избегать, потому что они не увидели, что лидер проекта заботится об их интересах. Тут нет разницы даже между пользователем покидающим Windows ради Linux, потому что Microsoft, видимо, больше не заботится об их интересах. Неприязнь к тому, как Леннарт делает свою работу и управляет его проектами -- это не то же самое, что и неприязнь к Леннарту лично, но очень часто мне кажется, что и защитники, и ненавистники объединяют их обе. Со стороны сторонников проекта было бы благоразумно различать, что именно критикуется до того, как кидаться личными обвинениями, а для критиков предусмотрительно было бы выделять цель своих нападок.
Моя мысль заключается в том, что скептицизм по отношению к systemd, обусловленный стилем управления, основан не на ошибке ad hominem. И скептицизм в отношении любого программного обеспечения, обусловленный его стилем управления, весьма не лишён смысла.
Заблуждение #11.1: "Вам следует судить systemd только по его техническим качествам, иначе это пустая критика". Это довольно наивно. Программы существуют не в вакууме: за каждой строчкой кода существуют люди, организации, намерения и репутация. И есть стоимость покупки программ и перехода на них, даже если они бесплатные (хоть как пиво, хоть как свобода). Таким образом, весьма разумно использовать или избегать программы по причинам, отличным от технических.
Например, сторонники СПО не используют несвободное программное обеспечение, даже если существует технически превосходящие несвободные предложения, потому что несвободное ПО нарушает одну из Четырёх Свобод. Однако, предположим для примера, что systemd существует в вакууме, и мы хотим судить systemd исключительно по техническим качествам. Это означает, что мы не можем допустить предубеждений и пристрастий, которые мы можем испытывать как за, так и против systemd, его авторов, его пользователей и т.п., которые могут повлиять на нашу оценку. Мы можем только выяснить, удовлетворяет ли systemd запросам пользователя.
Чтобы судить только по техническим качествам, нам прежде всего нужно, чтобы была формальная спецификация, которая точно и недвусмысленно определяет, чем systemd занимается, а чем -- нет. Далее нужно, чтобы было формальное доказательство, что реализация systemd удовлетворяет этой спецификации. Оба, спецификация и доказательство, необходимы, чтобы оценить systemd исключительно по техническим качествам; в противном случае, не существует способа последовательно показать, что systemd удовлетворяет требованиям. К сожалению, сделать эти две вещи означает взять на себя огромную задачу, что не выполнимо на практике (это специфично для systemd; это применимо к большинству нетривиального программного обеспечения).
Так что на текущий момент мы остаёмся с менее идеальными эвристиками, такими как тестирование поведения, чтение исходного кода, принятие во внимание намерений и доверительности разработчиков. И это нормально, потому что зачастую эти методы всё ещё дают полезное понимание того, подходит ли программное обеспечение для ваших нужд. Существует простор для спора по части лучших эвристик, но моя мысль в том, что (1) технических качеств не всегда достаточно, чтобы решить, использовать программу или же нет, и (2) судить исключительно по техническим качествам всё равно практически невозможно.
Заблуждение #12: "Ядро Linux сложное, но вы его используете. Следовательно вас не должно смущать, что systemd тоже сложен" Это заключение непоследовательно, также, как в Заблуждении #1.2. То, что кто-то использует ядро Linux не означает, что он/она хочет ещё большей сложности, кроме предложенной. В противовес предлагается ошибочная дилемма: примите всю сложность Linux+systemd или обойдитесь без обоих.
Сложное против простого это не бинарный выбор, и толерантность к сложности программы зависит от большого количества факторов, включающих контекст их использования, степень отлаженности, которой она достигла, степени понимания процессов её работы изнутри, и т.д. Кроме этого, большая часть избыточной сложности Linux может быть обрублена во время сборки, что некоторые пользователи и делают.
Заблуждение #13: "У systemd по крайней мере 574 участника из множества мест, следовательно он не продавливается и не контролируется малой группой" Это в лучшем случае наивно, и крайне не последовательно в худшем. Хотя это правда, что у проекта systemd много участников, абсолютное большинство кода systemd пришло только от нескольких людей. Я проверил последнюю версию кода systemd, используя эти ссылки, и запустил gitstats на нём (я щедро включил udev в этот анализ, не смотря на то, что он существовал до systemd). И вот что я обнаружил: Проект systemd насчитывает всего 688,539 строк (1,468,444 вставок, 779,905 удалений). Замететь, что это всё, не только C-код, который компилируется в бинари systemd.
Проект systemd насчитывает 17,503 коммитов. Top10 участников по числу коммитов представляют 82.73% всех коммитов. Из Top10 участников по числу коммитов, восемь также попадают в Top10 по числу строк кода. Top10 участников участников написали 90.8% systemd. По числу добавленных строк кода, Top10 ответственен за вклад 625,711 строк. Таким образом, по факту было бы более точно сказать, что systemd контролируется горсткой людей. Факт, что несколько сотен людей послали им небольшое количество кода, не умаляет влияние этой группы.
Заключение Цель этой статьи -- составить собрание часто используемых, но ошибочных аргументов за использование systemd. Я продолжу добавлять заблуждения по мере встречи с ними, и обновлять текст выше для улучшения ясности. Также, не предполагается, чтобы этот пост был критикой systemd. Только опровержение общих и неправильных аргументов потворствующих его принятию. Политика комментирования Я не поклонник цензуры, так что я не буду удалять комментарии (но Blogger.com может осуществлять политики анти-спама. Тем не менее, я перемещу комментарии-оффтопики на отдельную веб-страницу для сохранения релевантности.
Вы вольны вести любые беседы за пределами темы, но в другом месте. Опубликовано 26-го сентября 2014 Jude C. Nelson От переводчика: Это мой первый публикуемый перевод англоязычной статьи. Уже в процессе перевода я осознал, что понять написанное гораздо легче, чем выразить ту же мысль на другом языке. Задача синтеза против задачи анализа, естественное воплощение. В связи с этим хочу сразу оговорить, что я сделал несколько допущений, касающихся корректности перевода.
Binary - это существительное, образованное от binary file, "бинарный файл". Я не знаю способа перевести это лучше, нежели жаргонное "бинарь" или "бинарник". Non sequitur - "нелогичное заключение", вместо этого могут быть вариации вида "не последовательно", "не логично", "не является следствием". Socket activation - "активация через сокеты", "сокетная активация". Термин "сокет" является устоявшимся в русском языке, и я категорически отказываюсь переводить его как "гнездо". Post - "сообщение", но я думаю, что жаргонное "пост" будет более уместно в контексте. Systemd - это система инициализации, и по правилам русского языка надо бы говорить о нём в женском роде, однако мужской род мне привычнее. К тому же, есть мнение, что это не система инициализации, а комбайн (прошу не принимать близко к сердцу). re-implement - повторение реализации context - окружение, ситуация, контекст ad hominem - предпочитаю оставить как есть. Но если коротко, то это аргумент, основанный на личности оппонента, а не на сути дискуссии.
Хотелось бы также заметить, что я не уверен, что хорошо владею языком (что русским, что английским), поэтому в случае обнаружения неточностей перевода, прошу, отправляйте мне на почту freehck@freehck.ru замеченные ошибки: все предложения и правки будут рассмотрены очень щепетильно, и включены в текст статьи.
Примечания переводчика:
[1] Надо сказать, что статья писалась в сентябре 2014 года, когда технический комитет Debian ещё не принял решение о переходе на systemd. Сейчас распределение уже сильно иное.
Оригинал перевода: freehck.ru/share/systemd-biggest-fallacies.ru.final.org (не доступен)
Оригинал на английском: http://judecnelson.blogspot.ru/2014/09/ ... acies.html
Имейте в виду, что этот пост не нацелен быть критикой systemd или его авторов. Примите к сведению, что лично я верю, что вопрос "хорош systemd или плох?" может быть разрешён только в условиях конкретных запросов конкретного пользователя -- systemd хорош для людей, которым он нужен, но возможно менее предпочтителен для остальных.
Заблуждение #1: "Systemd - это множество бинарей, следовательно он не монолитен." В своём блоге Леннарт Поттеринг утверждает, что systemd не монолитен, ссылаясь на то, что он содержит свыше 69 отдельных бинарей. Одно из другого не следует, потому что термины "модульный" и "монолитный" не являются взаимно исключающими. Программное обеспечение является модульным, если его можно разобрать на отдельные функциональные единицы таким образом, чтобы занимался своей задачай. Systemd, ядро Linux и X.org -- примеры модульных программ. Systemd решает свои задачи бинарями, ядро Linux -- загружаемыми модулями, а в X.org -- драйверами и расширениями.
Далее, программное обеспечение является монолитным, если его компоненты (если оно таковые имеет) жёстко связаны -- то есть логически зависят друг от друга до такой степени, что использование их в других окружениях требует повторения реализации зависимых компонентов. В качестве примера можно привести Linux и X.org: в случае с Lunix вы не можете использовать модуль ядра без ядра, ядро не может быть запущено без требуемых ядром модулей для взаимодействия с железом, и вы не можете использовать модуль ядра Linux с другими ядрами, или в качестве независимой программы; точно так же вы не можете использовать видео-драйвер X без X-сервера, вы не можете использовать X-сервер без хотя бы одного видео-драйвера, не можете использовать видео-драйверы X с другими графическими менеджерами, и использовать их в качестве отдельных программ.
Исходя из этих определений, systemd должен считаться одновременно и модульным, и монолитным. Вы не можете использовать journald без systemd. Вы не можете использовать systemd без journald (по крайней мере без потери логгирования в программах, управляемых systemd). Ни одна из *ctl-программ не будет работать без systemd, не будет работать и коллекция демонов systemd-*d. Раньше было возможно запустить logind отдельно, но это уже не так.
По словам разработчиков systemd, udev станет следующим компонентом, жёстко зависимым от systemd. Суть в том, что не смотря на то, что systemd включает в себя множество бинарей, иерархические логические связи между ними означают, что более правильно было бы думать о них, как о расширениях systemd-PID-1, который просто выполняет их в отдельных адресных пространствах. Они не являются по-настоящему независимыми, пригодными для компонования (объединения с другими) программами. Для контраста, примеры модульных не-монолитных программ -- это GNU coreutils, s6 supervisor system, DJB's daemontools, GNU compiler collection. Эти приложения не только разбиты на модули, вы можете использовать эти модули независимо друг от друга в различных окружениях, объединяя/компонуя их вместе для решения более сложных задач, нежели тех, что решают отдельные модули сами по себе.
Таким образом, "модульный - не модульный" и "монолитный - не монолитный" - это вопросы компромиссов. Systemd менее монолитный и более модульный, чем, к примеру, программа "ls". Но он куда более монолитный, нежели любой другой из не монолитных примеров выше из-за логических связей между бинарниками.
Заблуждение #1.1: "Компоненты Systemd имеют хорошо описанные интерфейсы, и поэтому вы можете просто заменить части, которые вам не нравятся" Это рассуждение ошибочно из-за одного упущения. Не все его интерфейсы стабильны, поэтому этот вариант невозможно поддерживать, если только вы не имеете возможности тратить на это всё время. Что особенно важно, так это интерфейс к основному сервисному демону, который не стабилен. Даже сами авторы признают, что некоторые части systemd не могут быть независимо реализованы.
Заблуждение #1.2: "Ядро Linux монолитное, поэтому это нормально, что systemd монолитен". Также вообще не связанные вещи. Следует ли systemd быть монолитным или нет - абсолютно никак не относится к ядру Linux.
Заблуждение #2: "Многие используют systemd, значит ты тоже должен" Классический пример ошибки "большинство не может ошибаться". Припомните, что многие люди и дистрибутивы использовали когда-то sysvinit, но тем не менее это не делало её самой лучшей системой инициализации.
Заблуждение #2.1: "Systemd широко распространился благодаря техническим достоинствам" Это пример бахвальства. Осталось посмотреть, как много людей использует systemd, потому что они явно этого хотят, и сколько людей используют его, потому что их любимые апстримные программы от него зависят, их дистрибутивы перешли на него, или им было предписано перевести на него своё рабочее место. В последних случаях -- установки systemd как средства для использования других программ -- не считается выбором за техническое достоинство.
Почему дистрибутивы принимают systemd, если не за технические достоинства? Большим мотивирующим фактором является то, что наборы других программ (например GNOME) всё более зависят от них в своей работе. Если цель дистрибутива - обеспечить поддержку этих наборов программ для конечных пользователей, тогда утягивание systemd как зависимости означает только одно: они принимают systemd не за техническое превосходство; они принимают его, потому что так будет проще, нежели поддерживать патчи, чтобы держать systemd отдельно.
Говоря о принятии, как мы можем измерить это самое "широкое распространение"? Андроид вероятно самая широко используемая ОС на основе Linux, и он не использует systemd. Возможно наиболее широко распространённый по продажам потребитель GNU/Linux - это ChromeOS, но ChromeOS использует Upstart, и это вероятно не изменится. Так что не понятно, действительно ли systemd -- самая распространённая система в среде Linux. Принятие в дистрибутивах GNU/Linux также не повсеместно.
Gentoo и Slackware -- дистрибутивы для технически подкованных пользователей -- не приняли его за систему инициализации по-умолчанию. Также посмотрите на цифры из Debian popcon для systemd-sysv и sysvinit-core. На время написания данной статьи инсталляций systemd-sysv (которая конфликтует с sysvinit-core) примерно в 3 раза больше, чем sysvinit-core, что примерно соответствует неравенству между мета-пакетами для Xfce 4 и GNOME 3 [1]. Таким образом, несмотря на доступность для всех основных дистрибутивов GNU/Linux, пока преждевременно говорить о всеобщем захвате systemd.
Заблуждение #3: "Людям, которым не нравится systemd, просто неприятны изменения" Ошибка ad hominem. То, что systemd сейчас популярен, вовсе не означает, что он решает проблемы всех людей лучше, чем статус-кво. Люди, которые не используют systemd, часто имеют хорошо обоснованные технические причины, чтобы избегать его, и существует изобилие альтернативных систем инициализации, которые более подходят для их задач. Приятно думать, что технических причин для сохранения существующей системы инициализации нет, потому что systemd обратно совместима с init-скриптами.
Однако такое рассуждение делает много неявных предположений о нуждах пользователя, которые могут быть и не верны. Например: Предполагается, что пользователю комфортно доверять всему коду systemd. Предполагается, что пользователь ещё не делает ничего продвинутого с пространствами имён и cgroups, которые systemd может сломать. Предполагается, что пользователь недоволен текущими настройками управления сервисами, которые systemd мог бы заменить. Предполагается, что у пользователя достаточно RAM, CPU, диска и мощности для того, чтобы добавить systemd на свой компьютер. И это не всегда случай маломощных встраиваемых Linux-систем, где "init" сам мог бы быть просто встраиваемым приложением (NB: я имею в виду действительно маломощные устройства, такие как это, не смартфоны или эквивалентное оборудование).
Предполагается, что пользователь использует относительно свежее ядро Linux. Это также бывает не всегда, в случае использования экзотического оборудования, где проприетарные модули ядра могут держать вас привязанными к старой версии. Предполагается, что у пользователя будет совершенно безпроблемный опыт использования systemd, и ему не придётся потратить неоправданно большое количество времени, чтобы настроить systemd в своём окружении. Предполагается, что пользователь сможет легко мигрировать обратно с systemd, если окажется, что он плохо подходит к задачам. Если пользователь настраивает компьютер, который он/она не сможет легко администрировать (например устройство Интернета Вещей), он должен быть без багов и причуд настолько, насколько это возможно, причём сразу.
Доказано-корректная система инициализации была бы идеальным вариантом, но испытанная и хорошо понятная система предпочтительней непроверенной. Закрывать глаза на требования других людей к системе инициализации, как на неправильные - это отличный способ прослыть троллем. Равно как пытаться рассказывать им, что они не правы в своих требованиях.
Заблуждение #4: "Unit-файлы лучше, чем shell-скрипты" Это ошибочное обобщение, которое игнорирует большинство современных реалий. Не думаю, что сейчас кто-то не согласится, что когда это возможно, чем меньше кода - тем лучше. Как бы то ни было, всё зло в деталях. И есть тонкие, но важные инженерные детали касающиеся управления службами, на которые часто смотрят сквозь пальцы, когда говорят об init-файлах.
Заблуждение #4.1: "Unit-файлы уменьшают сложность" Это пыль в глаза, и подмена одной проблемы на другую. Хотя unit-файлы действительно выглядят проще init-скриптов и могут уменьшить сложность определяемых сервисов, они ни уменьшают сложность системы инициализации, ни уменьшают сложность поиска ошибок в системе инициализации, когда она ведёт себя не правильно (см.
Заблуждение #4.2:. Фактически же, вся сложность, которая была с shell-скриптами в sysvinit (а также с несколькими демонами и инструментами), просто ушла в systemd, который сейчас насчитывает более 275,000 строк кода. Более того, если верить этому анализу, это 245,000 строк кода на C, среди которых 81,000 необходимы, чтобы иметь минимально работающую реализацию (это милосердно исключая systemd-udevd, который добавляет ещё 13,000 строк). К слову о сравнении, не модифицированные init-скрипты на моём ноутбуке с Debian весят чуть больше 10,000 строк (согласно sloccount(1)). Не ясно, как systemd делает загрузку и управление сервисами менее склонной к ошибкам, нежели другие системы, но общая сложность systemd определённо выше, чем у sysvinit.
Заблуждение #4.2: "Shell-скрипты забагованы" Этот отвлекающих манёвр часто используется в спорах против использования shell-скриптов. Но баги присущи не shell-скприптам. Это забагованное ПО забаговано, и нет никакой разницы, на каком языке оно написано. Для тех из вас, кто никогда не дебажил програмы на C (язык, на котором написан systemd), поверьте на слово, что для C это гораздо сложнее, чем для shell-скрипта, потому что куда больше вещей может пойти не так в C. Потому что программист должен не только иметь дело с переменными и контролем потока, но ещё и с управлением памятью, управлением тредами, синхронизацией тредов, управлением файловыми дескрипторами, низкоуровневым IPC, специфичными для CPU моделями памяти, неопределённым поведением C (см. Дополнение J), и ещё кучей других вещей, которые просто неприменимы к рассуждению о поведении shell-скриптов.
Более того, если что-то случается во время загрузки, нет гарантии, что инструменты для дебага C будут доступны -- они могут быть просто установлены на носителе, который монтируется позже процесса загрузки (таком, как /usr или /usr/local). Это проблема не существует при использовании shell-скриптов при загрузке системы. Хотя и правда, что программы, которые запускаются shell-скриптами (как правило) тоже написаны на C, это не умаляет значения вышеописанных претензий. На практике, если shell-скрипт отказывается выполняться, баг почти всегда в скрипте, а не в вышележащей оболочке или программе, которую он запускает. Если же systemd отказывается работать с валидными параметрами unit-файла, то пользователь должен дебажить код systemd, написанный на C, чтобы выяснить почему.
Заблуждение #4.3: "Systemd лучше, потому что она избавилась от shell-скриптов!" Это ещё один отвлекающий манёвр, и скорее мнение, нежели технический аргумент. Как бы то ни было, shell-скрипты никогда не были обязательными, чтобы осуществить начальную загрузку Вашей системы. Ядро и множество других систем инициализации (включая sysvinit) могут быть сконфигурированы, чтобы стартовать произвольную программу, написанную на произвольном языке. Например, система инициализации Pardus Linux использует программы на Python вместо shell-скриптов.
Заблуждение #4.4: "Systemd лучше, потому что он уменьшает дублирование кода shell-скриптов!" Это тоже отвлекающий манёвр. Он отвлекает от факта, что ничто не останавливает пользователя от объединения общего кода init-скриптов в файл, подгружаемый каждым отдельным скриптом. Взгляните на то, что BSD-системы делают с /etc/rc.subr, например -- определения сервисов с BSD-шным rc часто короче unit-файлов!
Заблуждение #5: "Systemd позволяет вам использовать $LINUX_SPECIFIC_FEATURE" И это ещё один отвлекающий манёвр. Ничто не останавливало пользователя взять на вооружение эти Linux-специфичные средства до systemd. Все эти средства по определению должны были предшествовать systemd, прежде чем systemd мог быть написан с их использованием.
Заблуждение #6: "Systemd имеет открытый исходный код, так что если он вам не нравится, вы можете сделать fork". Некоторые люди этим и занимаются, не смотря на то, что systemd -- это большая движущаяся цель. Тем не менее, это утверждение является примером чёрно-белого мышления, которое теряет суть. Пользователь не-systemd часто более заинтересован, чтобы systemd не вторгался в его/её системы. Этот ошибочный аргумент говорит им отфоркать systemd... чтобы им не надо было использовать systemd.
Заблуждение #6.1: "Тем, кто клевещет на systemd, следовало бы прекратить ныть и сделать собственную альтернативу!" Опять же теряем суть, и это смесь чёрно-белого мышления и ошибки ad hominem[g]. Большинство пользователей не-systemd были бы абсолютно счастливы оставить systemd в покое и дать ей делать, что ей надо, для других людей, которые хотят её использовать. Какую бы систему инициализации они сейчас ни использовали, она прекрасно удовлетворяет их потребности. Проблема в том, что проект systemd не хочет оставить их в покое.
Видение systemd Леннарта Поттеринга заключается в том, что он должен стать основой всей ОС. Также он защищал жёсткую зависимость GNOME от logind, и конечно же он ответственен за то, что logind имеет жёсткую зависимость от systemd-в-виде-PID-1. Существует куча систем инициализации, но похоже, только одна из них активно пытается исключить остальные, заставляя не относящееся к ней ПО требовать её для работы. Многие пользователи не-systemd не нуждаются в клоне systemd, потому что они счастливы тем, что они уже имеют. Поэтому нет смысла предлагать им идти работать над клонированием systemd.
Заблуждение #7: "Вам следует использовать systemd, потому что он позволяет вам использовать активацию через сокеты!" Это пропаганда. Systemd не нужен для активации через сокеты, потому что ядро уже дало вам это просто так. Для активации через Интернет-сокеты всё, что пользователь должен сделать - это запустить демона, связать его с портом и оставить его там висеть. Если ядру потребуется память, оно сбросит ненужные демоны на диск. Если ядро получит входящее соединение, оно поднимет демона обратно в RAM, чтобы он смог его обработать. Systemd здесь вообще нет, но она имеет тот же самый эффект. Как дополнительный бонус, подсистема виртуальной памяти ядра удостоверяется, что runtime-состояние демона сохранено между сбросом и восстановлением -- кое-что, чего systemd не позволяет с её видом сокетной активации.
Заблуждение #7.1: "Вам следует использовать systemd, поскольку она позволяет вам назначать, какие цели будут активированы при получении соединения!" Это тоже пропаганда. Xinetd делал это десятилетия. Он может быть настроен на запуск чего угодно, что могло бы вызываться unit-файлами или запуском "systemctl ... enable", с тем же результатом.
Заблуждение #7.2: "Вам следует использовать systemd, поскольку он поддерживает не только сетевые сокеты! Он также поддерживает пайпы и UNIX-сокеты!" Ещё больше пропаганды. Этот маленький скрипт достигает того же эффекта с пайпами: mkfifo /path/to/pipe sh -c 'while true; do cat /path/to/pipe >/dev/null; /path/to/program; done' & Когда программа пишет в /path/to/pipe (например echo "" > /path/to/pipe), будет запущена /path/to/program. Этот скрипт, конечно, может быть расширен для выполнения более сложных задач, наподобие заставить цикл "while" выполнять различные действия в зависимости от того, что вы записали в /path/to/pipe, но суть в том, что активация через пайпы -- это не очень сложно. Похожий скрипт может быть написан для UNIX-сокетов при помощи netcat и socat. Если имеет значение управление жизненным циклом -- например, чтобы убедиться, что пайп или UNIX-сокет всегда отсоединяются, как только программа завершена -- я советую вам взглянуть на runfs.
Заблуждение #7.3: "Вам надо использовать systemd для сокетной активации, поскольку в противном случае вы столкнётесь с условиями гонки при параллельном запуске!" Это уже поучительное запугивание. Во-первых, это не было проблемой десятилетия, и до сих пор ей не является в современных событийно-управляемых системах (например, Android прекрасно обходится без systemd). Во-вторых, параллельный запуск и гарантированное отсутствие условий гонки могут быть достигнуты при простом использовании информации из procfs. Проблема формулируется следующим образом. Предположим, что процесс B зависит от процессов A0, A1, ..., An, которые должны стартовать и слушать сокет, до того, как процесс B стартует. Мы хотим запустить B параллельно с A0...An, но удостовериться, что B не пытается соединиться с любым Ai, пока A0...An не будут слушать.
Решением до systemd было просто запустить A0, A1, ..., An и подождать несколько секунд, чтобы позволит им достигнуть состояния прослушивания перед стартом B. Интуиция подсказывает, что A0...An достигнут состояния прослушивания прежде, чем B подключится, поскольку одна секунда - это очень долго для процесса Ai, чтобы пройти демонизацию через двойной форк и начать слушать сокет. Хотя B может обогнать A0...An и попытаться соединиться до того, как один из них начал слушать, вероятность, что это случится, ничтожна, и это доказано десятилетиями. Теперь предположим для примера, что B всё-таки сумел обогнать какой-то процесс Ai. Что случится? Попытка соединения у B завершится с ошибкой "connection refused", не смотря на то, что A0...An слушают. B не сможет запуститься, если только он не запрограммирован обрабатывать этот случай (например, пытаться соединиться, пока не будут превышены количество попыток или таймаут).
В идеале, B достаточно умён, чтобы делать это самостоятельно. Если нет, то решение с сокетной активацией, предложенное systemd, заключается в модификации A0...An, чтобы они могли получать дескриптор сокета от systemd, который systemd использует, чтобы буферизовать сообщения от B для каждого запускаемого Ai ("socket activation", systemd). Это позволяет B запуститься параллельно с A0...An, в тоже время предотвращая его дальнейшую работу, пока A0...An не начнут слушать. Как бы там ни было, это решение обходится дорого -- оно требует модифицировать O(n) программ, оно будет работать только с systemd, и будет решать проблему, которая на практике редка. Более простая стратегия -- это перебросить информацию в procfs.
Мы можем написать скрипт, который сперва проверял бы дескрипторы сокетов в /proc/A0/fd/, /proc/A1/fd/, ..., /proc/An/fd/, чтобы проверить, находятся ли они в слушающем состоянии путём сверки их inode-чисел с открытыми сокетами в /proc/net/$PROTOCOL. Как только сокеты будут в состоянии прослушивания, скрипт запустит B. Нет необходимости вовлекать сюда systemd, нет необходимости модифицировать A0...An, и решение работает везде, где доступна procfs (а даже если её нет, то только скрипт -- не демоны -- нуждается в модификации, чтобы портировать функциональность "сокетной активации").
Заблуждение #8: "$PROGRAM не зависит от systemd, она просто зависит от чего-то, что реализует интерфейс к systemd" Когда мы говорим об одном из компонентов или интерфейсов, которые не могут быть реализованы независимо (такие, как systemd-logind или API сервисной шины), этот аргумент -- разделение без различий. Это всё равно, что сказать "Internet Explorer не зависит от Microsoft Windows, он просто зависит от чего-то, что реализует интерфейс к Microsoft Windows"! Хотя, конечно, возможно повторить реализацию требуемых частей API, но чтобы сделать это эффективно, надо также повторить реализацию большей части платформы. Так что, если $PROGRAM зависит от одного из этих компонентов или интерфейсов, $PROGRAM требует либо systemd, либо почти полную аналогичную реализацию, делающую её systemd во всём, кроме имени.
Заблуждение #9: "Systemd - это принцип KISS в действии" Это некомпетентность. Принцип KISS ("Keep It Simple, Stupid") относится к дизайну системы, не к интерфейсу пользователя. KISS - это принцип избежания необязательной сложности. Однако, как мы установили в Заблуждении #4.1, минимально-используемый systemd более сложен, чем sysvinit и пытается делать куда больше. Далее, разработчики systemd верят, что повышенная сложность даже в минимальной systemd необходима, чтобы удовлетворить их требованиям. Всё, что я пытаюсь сказать, это то, что эти требования не универсальны, и для многих сложность не оправдана.
Заблуждение #10: "Бинарные логи не являются проблемой на практике" Это может быть или ошибочным обобщением, или неправильным выводом, и часто приводится в контексте типа "Я использовал бинарные логи, следовательно они должны хорошо подойти всем". Вопрос же, на который мы заинтересованы получить ответ, таков: "Позволяют ли формат журнала и средства журналирования записывать множество событий и ошибок, требуемых пользователю, в порядке их появления"? Если ответ "да", то выбор форматирования произвольный, потому что реализация деталей не имеет значения.
В противном случае, если бывают случаи, когда средства журналирования могут вести себя непредсказуемо (например баг в журнале, паника ядра, ошибка железа -- вещи, которые случаются в некоторой степени регулярно), реализация деталей значение имеет, поскольку пользователю придётся вмешаться вручную, чтобы определить последовательность событий и ошибок, приведших к неверному поведению. В этом случае журналирование структурированных бинарных записей почти всегда худшее дизайнерское решение, нежели журналирование неструктурированного человеко-читаемого текста, потому что почти всегда восcтановить чисто-текстовый журнал после не подлежащих исправлению ошибок журналирования (в частности, повреждения) легче.
Повреждение журнала -- это, возможно, самая сложная проблема, с которой сталкиваются средства журналирования, потому что теряется информация. Не смотря на это, человеко-читаемый текст остаётся хотя бы частично читаем при повреждении, поскольку правила, грамматика и семантика письменного языка служит корректирующим ошибки целям, встречающимся в повседневной жизни. Например, пользователь с первого взгляда может сказать, обрезана строка или нет, или потеряны ли одно или несколько слов, или содержатся ли данные, которые не должны быть там (вроде непечатных символов), или что они не удовлетворяют любому ожидаемому формату сообщений журнала. И так далее, просто потому что журналирование только человеко-читаемого текста позволяет пользователю понять, что логгер намеревался записать.
Как бы то ни было, чем больше бинарных данных включается в журнальные записи, тем сложнее становится пользователю разобрать письменный язык, чтобы понять намерения логгера (к примеру, строка случайных символов -- это признак повреждения, или это часть записи, или понемногу и того, и того?). На момент написания этого текста, journald мог повредить журнал просто упав, приводя журнал в состояние, при котором невозможно сказать, повреждён ли он или искажён (разработчики знали об этом годами, и они не считают, что это баг). Сейчас же существует возможность вручную разобрать повреждённый журнал journald, если journalctl не помогает, но это требует больше усилий, чем разбор повреждённого чисто текстового журнала, так как пользователь обязан быть в курсе формата журнала journald, чтобы извлечь человеко-читаемые строки из бинарных записей.
Таким образом, когда приходится иметь дело с ошибками, которые включают в себя повреждение журнала (в случае journald, это все ошибки, которые могут привести к некорректному завершению -- а это именно те ошибки, которые средства журналирования должны отлавливать), чисто текстовый журнал будет почти всегда более удобен в использовании, чем журнал journald. Далее, журналирование journald могло бы быть более устойчивым. Оно могло бы улучшить восстанавливаемость при повреждении путём задействования помехоустойчивого кодирования, хранения бинарных данных в отдельном файле (или кодированием оных в человеко-читаемый текст), реализацией ACID-семантики для записей журнала. Тем не менее, он не делает ничего из этих вещей на момент написания этих строк, что делает его более хрупким в случае ошибки.
Заблуждение #10.1: "Бинарный формат journald позволяет произвести проверки подлинности и целостности" Это пропаганда. Последние реализации syslog тоже это делают, так что это не повод выбирать joutnald.
Заблуждение #10.2: "Бинарный формат journald позволяет ему иметь индекс, что делает доступ к журналу быстрее" Это тоже пропаганда. Хотя никто не спорит, что индексирование увеличит скорость доступа к журналу (по крайней мере в теории), нет также никаких технических причин, почему journald не может хранить индекс отдельно от журнального файла, или почему он не может писать индекс в журнал в виде человеко-читаемого текста.
Заблуждение #10.3: "Всех проблем с journald можно избежать, если заставить его просто перенаправлять всё в syslog" Это предполагает ошибочную предпосылку, что в этом случае в journald есть необходимость. Если всё, что нужно пользователю, это syslog, зачем вообще требовать journald?
Заблуждение #11: "Тем, кому не нравится systemd, на самом деле просто не нравится Леннарт Поттеринг, и это не оправдание, чтобы избегать systemd" Во-первых, тут говорят за пользователей не-systemd (ad hominem). Во-вторых, существует множество корректных не-технических причин, чтобы использовать или избегать программу. И отсутствие веры в то, что ведущий разработчик заботится о ваших интересах -- это одно из них. Экосистема GNU/Linux -- это базар, а не собор. Разработка программного обеспечения в этой области обязательно имеет социальную направленность, потому что дальновидные разработчики, работающие над одним делом, должны общаться, чтобы решать проблемы.
По существу, разработчики культивируют репутацию для их стиля управления, практик написания кода, ответственности за отчёты об ошибках, и так далее. И это справедливо влияет на степень, в которой другие разработчики доверяют друг другу делать хорошую работу в своих проектах (например, Debian когда-то перешёл с GNU libc на EGLIBC, ссылаясь на трения с мейнтейнром GNU libc как на основную причину). Сейчас в некоторых кругах Леннарт Поттеринг получил негативную репутацию за слишком частое нарушение совместимости и отклонение конструктивной критики своих проектов (включая отчёты об ошибках).
Это не нападение на его персону; это критика его стиля управления проектом. Тех пользователей, которых это негативно коснулось, это заставило серьёзно почувствовать, что systemd надо избегать, потому что они не увидели, что лидер проекта заботится об их интересах. Тут нет разницы даже между пользователем покидающим Windows ради Linux, потому что Microsoft, видимо, больше не заботится об их интересах. Неприязнь к тому, как Леннарт делает свою работу и управляет его проектами -- это не то же самое, что и неприязнь к Леннарту лично, но очень часто мне кажется, что и защитники, и ненавистники объединяют их обе. Со стороны сторонников проекта было бы благоразумно различать, что именно критикуется до того, как кидаться личными обвинениями, а для критиков предусмотрительно было бы выделять цель своих нападок.
Моя мысль заключается в том, что скептицизм по отношению к systemd, обусловленный стилем управления, основан не на ошибке ad hominem. И скептицизм в отношении любого программного обеспечения, обусловленный его стилем управления, весьма не лишён смысла.
Заблуждение #11.1: "Вам следует судить systemd только по его техническим качествам, иначе это пустая критика". Это довольно наивно. Программы существуют не в вакууме: за каждой строчкой кода существуют люди, организации, намерения и репутация. И есть стоимость покупки программ и перехода на них, даже если они бесплатные (хоть как пиво, хоть как свобода). Таким образом, весьма разумно использовать или избегать программы по причинам, отличным от технических.
Например, сторонники СПО не используют несвободное программное обеспечение, даже если существует технически превосходящие несвободные предложения, потому что несвободное ПО нарушает одну из Четырёх Свобод. Однако, предположим для примера, что systemd существует в вакууме, и мы хотим судить systemd исключительно по техническим качествам. Это означает, что мы не можем допустить предубеждений и пристрастий, которые мы можем испытывать как за, так и против systemd, его авторов, его пользователей и т.п., которые могут повлиять на нашу оценку. Мы можем только выяснить, удовлетворяет ли systemd запросам пользователя.
Чтобы судить только по техническим качествам, нам прежде всего нужно, чтобы была формальная спецификация, которая точно и недвусмысленно определяет, чем systemd занимается, а чем -- нет. Далее нужно, чтобы было формальное доказательство, что реализация systemd удовлетворяет этой спецификации. Оба, спецификация и доказательство, необходимы, чтобы оценить systemd исключительно по техническим качествам; в противном случае, не существует способа последовательно показать, что systemd удовлетворяет требованиям. К сожалению, сделать эти две вещи означает взять на себя огромную задачу, что не выполнимо на практике (это специфично для systemd; это применимо к большинству нетривиального программного обеспечения).
Так что на текущий момент мы остаёмся с менее идеальными эвристиками, такими как тестирование поведения, чтение исходного кода, принятие во внимание намерений и доверительности разработчиков. И это нормально, потому что зачастую эти методы всё ещё дают полезное понимание того, подходит ли программное обеспечение для ваших нужд. Существует простор для спора по части лучших эвристик, но моя мысль в том, что (1) технических качеств не всегда достаточно, чтобы решить, использовать программу или же нет, и (2) судить исключительно по техническим качествам всё равно практически невозможно.
Заблуждение #12: "Ядро Linux сложное, но вы его используете. Следовательно вас не должно смущать, что systemd тоже сложен" Это заключение непоследовательно, также, как в Заблуждении #1.2. То, что кто-то использует ядро Linux не означает, что он/она хочет ещё большей сложности, кроме предложенной. В противовес предлагается ошибочная дилемма: примите всю сложность Linux+systemd или обойдитесь без обоих.
Сложное против простого это не бинарный выбор, и толерантность к сложности программы зависит от большого количества факторов, включающих контекст их использования, степень отлаженности, которой она достигла, степени понимания процессов её работы изнутри, и т.д. Кроме этого, большая часть избыточной сложности Linux может быть обрублена во время сборки, что некоторые пользователи и делают.
Заблуждение #13: "У systemd по крайней мере 574 участника из множества мест, следовательно он не продавливается и не контролируется малой группой" Это в лучшем случае наивно, и крайне не последовательно в худшем. Хотя это правда, что у проекта systemd много участников, абсолютное большинство кода systemd пришло только от нескольких людей. Я проверил последнюю версию кода systemd, используя эти ссылки, и запустил gitstats на нём (я щедро включил udev в этот анализ, не смотря на то, что он существовал до systemd). И вот что я обнаружил: Проект systemd насчитывает всего 688,539 строк (1,468,444 вставок, 779,905 удалений). Замететь, что это всё, не только C-код, который компилируется в бинари systemd.
Проект systemd насчитывает 17,503 коммитов. Top10 участников по числу коммитов представляют 82.73% всех коммитов. Из Top10 участников по числу коммитов, восемь также попадают в Top10 по числу строк кода. Top10 участников участников написали 90.8% systemd. По числу добавленных строк кода, Top10 ответственен за вклад 625,711 строк. Таким образом, по факту было бы более точно сказать, что systemd контролируется горсткой людей. Факт, что несколько сотен людей послали им небольшое количество кода, не умаляет влияние этой группы.
Заключение Цель этой статьи -- составить собрание часто используемых, но ошибочных аргументов за использование systemd. Я продолжу добавлять заблуждения по мере встречи с ними, и обновлять текст выше для улучшения ясности. Также, не предполагается, чтобы этот пост был критикой systemd. Только опровержение общих и неправильных аргументов потворствующих его принятию. Политика комментирования Я не поклонник цензуры, так что я не буду удалять комментарии (но Blogger.com может осуществлять политики анти-спама. Тем не менее, я перемещу комментарии-оффтопики на отдельную веб-страницу для сохранения релевантности.
Вы вольны вести любые беседы за пределами темы, но в другом месте. Опубликовано 26-го сентября 2014 Jude C. Nelson От переводчика: Это мой первый публикуемый перевод англоязычной статьи. Уже в процессе перевода я осознал, что понять написанное гораздо легче, чем выразить ту же мысль на другом языке. Задача синтеза против задачи анализа, естественное воплощение. В связи с этим хочу сразу оговорить, что я сделал несколько допущений, касающихся корректности перевода.
Binary - это существительное, образованное от binary file, "бинарный файл". Я не знаю способа перевести это лучше, нежели жаргонное "бинарь" или "бинарник". Non sequitur - "нелогичное заключение", вместо этого могут быть вариации вида "не последовательно", "не логично", "не является следствием". Socket activation - "активация через сокеты", "сокетная активация". Термин "сокет" является устоявшимся в русском языке, и я категорически отказываюсь переводить его как "гнездо". Post - "сообщение", но я думаю, что жаргонное "пост" будет более уместно в контексте. Systemd - это система инициализации, и по правилам русского языка надо бы говорить о нём в женском роде, однако мужской род мне привычнее. К тому же, есть мнение, что это не система инициализации, а комбайн (прошу не принимать близко к сердцу). re-implement - повторение реализации context - окружение, ситуация, контекст ad hominem - предпочитаю оставить как есть. Но если коротко, то это аргумент, основанный на личности оппонента, а не на сути дискуссии.
Хотелось бы также заметить, что я не уверен, что хорошо владею языком (что русским, что английским), поэтому в случае обнаружения неточностей перевода, прошу, отправляйте мне на почту freehck@freehck.ru замеченные ошибки: все предложения и правки будут рассмотрены очень щепетильно, и включены в текст статьи.
Примечания переводчика:
[1] Надо сказать, что статья писалась в сентябре 2014 года, когда технический комитет Debian ещё не принял решение о переходе на systemd. Сейчас распределение уже сильно иное.
Оригинал перевода: freehck.ru/share/systemd-biggest-fallacies.ru.final.org (не доступен)
Оригинал на английском: http://judecnelson.blogspot.ru/2014/09/ ... acies.html