commit -m "better"
2.96K subscribers
870 photos
105 videos
3 files
2.08K links
just random thoughts
Download Telegram
commit -m "better"
В продолжении темы #reboot #stal/ix https://www.phoronix.com/news/Fedora-38-Shutdown-Timer-45 "Last month a change proposal was filed for aiming to yield faster reboots and shutdowns of Fedora Linux by shortening the time window that services can block the…
Вкратце напомню, что у меня системными сервисами управляет #runit. Поэтому, когда у меня происходит обновление system #realm, происходит перезагрузка всего дерева сервисов. Ну просто потому что меняются inode путей в папке /etc/services, так как /etc - это симлинка на /ix/realm/system/etc.

ВНЕЗАПНО я понял, что это аналог "soft reboot" из systemd - https://www.opennet.ru/opennews/art.shtml?num=59512.

Даже не то чтобы аналог, а просто 1 в 1 - убивается все дерево процессов, кроме init (runit), и запускается заново.

Конечно, без извращений вида "Сохранение состояния работающего ядра при замене пользовательского окружения даёт возможность реализовать обновление некоторых сервисов в live-режиме (без остановки), организовав передачу файловых дескрипторов и слушающих сетевых сокетов для этих сервисов из старого окружения в новое" - много раз писал, и буду писать, что программам иногда нужно сбрасывать накопленный ошибочный state.
👍14🔥42🆒1
Полгода назад запилил свой великолепный CI скрипт, https://github.com/pg83/ix/commits/main/pkgs/die/scripts/ci.

По сути, он почти не менялся, кроме того, что я вынес внешний цикл в #runit, ну а так он работал себе и работал.

Но вот недавно я добавил туда ровно одну строку, которая призвана собирать все то же самое, но другим выполнителем графа - https://github.com/pg83/ix/blob/main/pkgs/die/scripts/ci#L8.

Напомню, у меня их два - один на go, он ставится в систему, и служит для оркестрации выполнения для #stalix, а второй написан на питоне, и служит для #bootstrap, ну и на macOS можно чего-нить пособирать. Так, простенький выполнитель, встроенный прямо в движок построения этого графа.

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

Махом починил все проблемы с локальным выполнителем, и добавил сборку всего репозитория пакетов им в свой импровизированный CI.

Интересно, сколько я его теперь смогу не трогать?
👍63🤔1
commit -m "better"
Вкратце напомню, что у меня системными сервисами управляет #runit. Поэтому, когда у меня происходит обновление system #realm, происходит перезагрузка всего дерева сервисов. Ну просто потому что меняются inode путей в папке /etc/services, так как /etc - это…
#runit, будни #bootstrap, #herobora #runsvdir.

У используемого и нежно любимого мной runit есть одна неприятная особенность (врочем, как и у остальных init-ов, унаследованных от daemontools).

Он хочет безусловно портить структуру директорий, в которых лежат сервисы.

Простыми словами - он создает директорию ./supervisor, рядом с каждым файликом run каждого сервиса. Там он хранит состояние управляемого сервиса, и прочую лабудень.

Контрольки сервисов (./run файлы) у меня лежат в /etc, которая есть ссылка на какую-то папку в content addressable store.

Из этого следует простой вывод - runit у меня "портил" (и продолжает портить) папки (и данные) в cas, чего допускать, конечно, нельзя.

Я обкатывал несколько разных решений этой проблемы, которые, так или иначе, сводились к "теневой" копии сервисов из /etc "куда-то", где можно писать. Например, регулярным копированием /etc/services куда-то в /var/run/, или, вот, с помощью rw overlay unionfs куда-то в tmpfs.

Короче, совершенно всратые решения, ошметки которых я даже не хочу показывать.

Смотрел на другие "простые" супервизоры, но нет.

В общем, после нескольких лет попыток придумать что-то не столь всратое, я плюнул, и переписал runsvdir - это часть runit, которая отвечает именно за управление деревом процессов.

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

Та-да-да-дам!

https://github.com/stal-ix/ix/blob/main/pkgs/bin/ix/runsvdir/run.py

Да, на python, потому что для прототипирования python подходит очень хорошо, и я уже смирился с тем, что он у меня есть в базовой системе (при этом я упаковал в один бинарь со всеми зависимостями, поэтому он не мозолит глаза своей россыпью файлов по всей fs).

Когда его семантика устаканится, перепишу на go, или даже на rust (не хочет кто-то взяться? там строк 50-100 идиоматичного rust-о кода должно быть).

Что я могу сказать?

* Мне кажется, это самый компактный супервизор процессов, который я когда-либо видел/делал, при этом, с приличным набором фич. Он умеет пасти структуру директорий, такую же, как у runit, но ничего не пишет на диск. Сервисы могут добавляться и убираться "на лету".

* Удивительно, но я вот написал этот скриптец, ребутнул машину, ожидая debug и recovery окирпиченного хоста, но ничего такого не случилось - все завелось сразу, с полпинка, потому что поверхность у runsvdir - очень простая и компактная.

* В принципе, теперь я могу там запилить недостающие фичи из runit, типа динамически создаваемых юнитов. Захочу ли - пока не знаю.
🔥26👍53🤔1
commit -m "better"
#runit, будни #bootstrap, #herobora #runsvdir. У используемого и нежно любимого мной runit есть одна неприятная особенность (врочем, как и у остальных init-ов, унаследованных от daemontools). Он хочет безусловно портить структуру директорий, в которых лежат…
Я, когда рассказывал про свою замену #runit, упустил один важный момент.

Если до того, как я заменил #runsvdir, у меня рестартовало вообще все дерево процессов после модификации system #realm (ну потому, что папка с симлинками на сервисы появлялась новая, inode у этих симлинок новый, и runit рестартовал вообще все), то после перестало рестартовать вообще все, даже в тех ситуациях, когда сервис поменялся, и рестарт был нужен.

Потому что мой скрипт смотрит не на inode, а на контент + путь до скрипта, и вот эта вот пара, на самом деле, меняется очень редко.

А меняется она редко, потому что у меня, чаще всего, runit скрипты не являются частью пакета с программой, а идут отдельным пакетом, чтобы программу можно было использовать и без runit скриптов.

Вот и получается, что программа поменялась, а скрипт запуска - нет, и ничего не рестартует.

Самый очевидный способ это починить - сделать так, чтобы runit скрипт зависел (по сборке) от программы, которую он запускает, но это приводит к некоторым проблемам:

* build зависимость всегда host, а нужна зависимость от target.

* может оказаться так, что программа собирается с каким-то пользовательским флагом, тогда, по сути, одна и та же программа соберется два раза (под host, без флага, и под target, с флагом)

В общем, я протащил из графогенерирующего ядра возможность получить uid любого пакета, как если бы мы проинтерпретировали графогенерацию для этого пакета в нашем текущем контексте с флагами, о как.

Ну и записал этот uid в тело runit скрипта - https://github.com/pg83/ix/blob/main/pkgs/etc/services/runit/script/ix.sh#L32

Использование выглядит вот так - https://github.com/pg83/ix/blob/main/pkgs/bin/chrony/runit/ix.sh#L4-L5 По сути, просто передаем в пакет с runit скриптом флаг (srv_deps=...), в котором лежит список всех зависимостей для этого скрипта.

С одной стороны, какое-то странное, неестественное, действие, с другой - теперь можно не рестартовать сервисы, когда что-то поменялось, но не очень хочется (например, пользовательские сессии)
🤔10👍63🔥1
commit -m "better"
#runit, будни #bootstrap, #herobora #runsvdir. У используемого и нежно любимого мной runit есть одна неприятная особенность (врочем, как и у остальных init-ов, унаследованных от daemontools). Он хочет безусловно портить структуру директорий, в которых лежат…
Будни #bootstrap, #runit, хозяйке на заметку.

Уменьшил число процессов, которые "следят" за сервисами.

Раньше у меня была цепочка "cgroup manager" (он прибивал все дерево процессов, если основной процесс выходил) -> "flock" (обеспечиваем, что запущено не больше одного инстанса сервиса) -> "tinylog" (штука, которая пишет stdout/err процесса в виде нашинкованных файлов).

Оказалось, что flock можно убрать!

Раньше было

# вот тут flock ожидает выхода
# команды
flock lock cmd args...


Стало

# shell создает fd == 200
# связанный с файлом lock
exec 200>lock
# flock умеет принимать на вход fd!
flock 200
exec cmd args ...


Вы знали, что flock так умеет? Я не знал!

Чтобы это работало, нужно гарантировать, что мы убьем все дерево процессов, которые унаследовали flock 200, и это у меня обеспечивается (выше писал, как)!
🔥15👍4❤‍🔥2🆒1
commit -m "better"
В общем, после нескольких лет попыток придумать что-то не столь всратое, я плюнул, и переписал runsvdir - это часть runit, которая отвечает именно за управление деревом процессов.
#herobora

В итоге, мой #runsvdir у меня прижился, и, как понятное следствие, я окончательно отказался от ошметков #runit:

* https://github.com/pg83/ix/blob/main/pkgs/bin/ix/init/ewontfix/main.c - свой элементарный init.

* https://github.com/pg83/ix/blob/main/pkgs/bin/ix/init/rc/ix.sh#L9-L11 - клей между моим init, и схемой загрузки "как в runit", чтобы можно было заменять туда-сюда.

* https://github.com/pg83/ix/blob/main/pkgs/bin/ix/init/halt/main.c https://github.com/pg83/ix/blob/main/pkgs/bin/ix/init/reboot/main.c - реализации halt/reboot, они, как ни странно, тоже часть init. Если такой способ (без graceful shutdown) кажется странным - читаем мои заметки про #reboot, https://t.iss.one/itpgchannel/1572.

* https://github.com/pg83/ix/blob/main/pkgs/bin/ix/pid1/m.cpp#L157-L175 - пришлось перенести в runsvdir код, который убивает orphane процессы, в runit у меня это был cron job на shell (https://github.com/pg83/ix/blob/main/pkgs/bin/sched/stale/procs/scripts/staleprocs.sh), но в новой схеме так не получается, потому что сервисы сразу начинают наследоваться от pid 1, а не от pid > 1, поэтому инвариант "все, что подвисло к pid 1, но не runsvdir - мусор" перестал работать.

Так что теперь у меня официально полностью велосипедный in house init!

С точки зрения скриптов инициализации ничего не поменялось, ага.
👍11🔥74🆒3