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.
ВНЕЗАПНО я понял, что это аналог "soft reboot" из systemd - https://www.opennet.ru/opennews/art.shtml?num=59512.
Даже не то чтобы аналог, а просто 1 в 1 - убивается все дерево процессов, кроме init (runit), и запускается заново.
Конечно, без извращений вида "Сохранение состояния работающего ядра при замене пользовательского окружения даёт возможность реализовать обновление некоторых сервисов в live-режиме (без остановки), организовав передачу файловых дескрипторов и слушающих сетевых сокетов для этих сервисов из старого окружения в новое" - много раз писал, и буду писать, что программам иногда нужно сбрасывать накопленный ошибочный state.
www.opennet.ru
Выпуск системного менеджера systemd 254 с поддержкой мягкой перезагрузки
После пяти месяцев разработки представлен релиз системного менеджера systemd 254. Наиболее заметным изменением в новой версии стала поддержка режима мягкой перезагрузки (команда "systemctl soft-reboot"), который приводит к перезапуску только компонентов пространства…
👍14🔥4❤2🆒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.
Интересно, сколько я его теперь смогу не трогать?
По сути, он почти не менялся, кроме того, что я вынес внешний цикл в #runit, ну а так он работал себе и работал.
Но вот недавно я добавил туда ровно одну строку, которая призвана собирать все то же самое, но другим выполнителем графа - https://github.com/pg83/ix/blob/main/pkgs/die/scripts/ci#L8.
Напомню, у меня их два - один на go, он ставится в систему, и служит для оркестрации выполнения для #stalix, а второй написан на питоне, и служит для #bootstrap, ну и на macOS можно чего-нить пособирать. Так, простенький выполнитель, встроенный прямо в движок построения этого графа.
Вот сборка питонячим выполнителем у меня была постоянно разломана, потому что, все же, выполнители немного разные, но этого было достаточно, чтобы часть проектов всегда была подломана.
Махом починил все проблемы с локальным выполнителем, и добавил сборку всего репозитория пакетов им в свой импровизированный CI.
Интересно, сколько я его теперь смогу не трогать?
GitHub
History for pkgs/die/scripts/ci - pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
👍6❤3🤔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.
Короче, совершенно всратые решения, ошметки которых я даже не хочу показывать.
Смотрел на другие "простые" супервизоры, но нет.
В общем, после нескольких лет попыток придумать что-то не столь всратое, я плюнул, и переписал
Эдакий сплав (она же херобора) из обычного 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 окирпиченного хоста, но ничего такого не случилось - все завелось сразу, с полпинка, потому что поверхность у
* В принципе, теперь я могу там запилить недостающие фичи из runit, типа динамически создаваемых юнитов. Захочу ли - пока не знаю.
У используемого и нежно любимого мной 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👍5❤3🤔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=...), в котором лежит список всех зависимостей для этого скрипта.
С одной стороны, какое-то странное, неестественное, действие, с другой - теперь можно не рестартовать сервисы, когда что-то поменялось, но не очень хочется (например, пользовательские сессии)
Если до того, как я заменил #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=...), в котором лежит список всех зависимостей для этого скрипта.
С одной стороны, какое-то странное, неестественное, действие, с другой - теперь можно не рестартовать сервисы, когда что-то поменялось, но не очень хочется (например, пользовательские сессии)
GitHub
ix/pkgs/etc/services/runit/script/ix.sh at main · pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
🤔10👍6❤3🔥1
commit -m "better"
#runit, будни #bootstrap, #herobora #runsvdir. У используемого и нежно любимого мной runit есть одна неприятная особенность (врочем, как и у остальных init-ов, унаследованных от daemontools). Он хочет безусловно портить структуру директорий, в которых лежат…
Будни #bootstrap, #runit, хозяйке на заметку.
Уменьшил число процессов, которые "следят" за сервисами.
Раньше у меня была цепочка "cgroup manager" (он прибивал все дерево процессов, если основной процесс выходил) -> "flock" (обеспечиваем, что запущено не больше одного инстанса сервиса) -> "tinylog" (штука, которая пишет stdout/err процесса в виде нашинкованных файлов).
Оказалось, что flock можно убрать!
Раньше было
Стало
Вы знали, что flock так умеет? Я не знал!
Чтобы это работало, нужно гарантировать, что мы убьем все дерево процессов, которые унаследовали
Уменьшил число процессов, которые "следят" за сервисами.
Раньше у меня была цепочка "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!
С точки зрения скриптов инициализации ничего не поменялось, ага.
В итоге, мой #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 - мусор" перестал работать.
Так что теперь у меня официально полностью
С точки зрения скриптов инициализации ничего не поменялось, ага.
GitHub
ix/pkgs/bin/ix/init/ewontfix/main.c at main · pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
👍11🔥7❤4🆒3