До последнего времени у меня не было weak зависимостей, потому что я нутром чую, что вот эти вот "provides xyz" - это одна из упячнейших упячек пакетных менеджеров.
Я долго думал, как эту фичу сделать так, чтобы оно было относительно привычным людям, но не казалось мне всратым по сути своей.
У меня есть механизм для "рихтовки напильником" получающихся #realm. Каждый пакет может положить в папочку ${out}/fix/ какой-нибудь sh-скрипт, который система дернет при построении realm, содержащего этот пакет. Для чего это нужно:
* Некоторые пути мы знаем только в момент формирования #realm - например, путь к WebProcess для webkit браузеров.
* xdg пути. Это набор путей для широкого круга задач - для поиска шрифтов, иконок, тем курсоров, и так далее. Они не известны на момент построения пакета, который будет использовать эти assets.
* glib xml schemas. Не спрашивайте.
В итоге, я пока сделал, что weak-зависимость - это тест на наличие того или иного файла в получающимся realm.
Ну вот, реально, кладем в fix/ файлик check-xdg-open.sh, в котором написано
Если при сборке нового realm такой пакет не будет указан, будет понятная ошибка сборки, с указанием, как это починить.
Дальше, конечно, Остапа понесло, потому что получился очень "широкий" механизм.
Например, как проверить, что пользователь установил нужный шрифт в realm?
Не нужно выдумывать новую иерархию фиктивных пакетов, достаточно просто дернуть fc-list, или что-то похожее, и посмотреть, есть ли подходящий ответ. В рамках вычислительной ноды, подготоваливающей этот realm.
Идею хуков в fix/ я подглядел в nixos, творчески ее переработав.
Выглядит это примерно так:
* это тест, как я люблю
* этот тест проверяет ровно то свойство, что нужно, не больше, и не меньше
* никаких "мамой клянусь, мой пакет реализует спецификацию xdg-open!"
* нового механизма нет, а нужная функция выполняется. Это особенно ценнО, стараюсь держать свой toolbox небольшим.
Я долго думал, как эту фичу сделать так, чтобы оно было относительно привычным людям, но не казалось мне всратым по сути своей.
У меня есть механизм для "рихтовки напильником" получающихся #realm. Каждый пакет может положить в папочку ${out}/fix/ какой-нибудь sh-скрипт, который система дернет при построении realm, содержащего этот пакет. Для чего это нужно:
* Некоторые пути мы знаем только в момент формирования #realm - например, путь к WebProcess для webkit браузеров.
* xdg пути. Это набор путей для широкого круга задач - для поиска шрифтов, иконок, тем курсоров, и так далее. Они не известны на момент построения пакета, который будет использовать эти assets.
* glib xml schemas. Не спрашивайте.
В итоге, я пока сделал, что weak-зависимость - это тест на наличие того или иного файла в получающимся realm.
Ну вот, реально, кладем в fix/ файлик check-xdg-open.sh, в котором написано
test -f bin/xdg-openА дельше уже задача пользователя выбрать ту или иную реалзиацию xdg-open, подходящую его нуждам.
Если при сборке нового realm такой пакет не будет указан, будет понятная ошибка сборки, с указанием, как это починить.
Дальше, конечно, Остапа понесло, потому что получился очень "широкий" механизм.
Например, как проверить, что пользователь установил нужный шрифт в realm?
Не нужно выдумывать новую иерархию фиктивных пакетов, достаточно просто дернуть fc-list, или что-то похожее, и посмотреть, есть ли подходящий ответ. В рамках вычислительной ноды, подготоваливающей этот realm.
Идею хуков в fix/ я подглядел в nixos, творчески ее переработав.
Выглядит это примерно так:
ENTER /mix/store/NObQBw2XIB4XeIFG-rlm-guiЧем больше я про это думаю, тем больше мне нравится моя реализация:
+ test -d fix
+ read l
+ find fix/ -name *.sh
+ sh fix/wrap-xdg-transmission-gtk.sh
+ read l
+ sh fix/check-bin-xdg-open.sh
can not find bin/xdg-open, install
providing package into realm
* это тест, как я люблю
* этот тест проверяет ровно то свойство, что нужно, не больше, и не меньше
* никаких "мамой клянусь, мой пакет реализует спецификацию xdg-open!"
* нового механизма нет, а нужная функция выполняется. Это особенно ценнО, стараюсь держать свой toolbox небольшим.
🔥10👍2
#allocator #tcmalloc #mimalloc
Давеча писал про свой дефолтный аллокатор, и про то, что это, во многом, эмоциональное решение.
Короче, я привел свои эмоции в соответствие реальности, и перешел на tcmalloc по дефолту.
* https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/c/alloc/ix.sh#L5 - по сути, это изменение 1 строчки кода, после чего весь репозиторий будет линковаться с tcmalloc, если не указано обратное
* конечно, реальное изменение было несколько больше, потому что, я напомню, цепочка #bootstrap у меня теперь строится автоматически, и теперь tcmalloc может использоваться раньше в этой цепочке, когда мой инструментарий был недостаточен, чтобы собрать его полную версию. Самое простое - не готов perl, для запуска GNU autohell скриптов. Поэтому я взял более свежую версию gperftools, где есть поддержка cmake. Сборка cmake там пока молодая, немного кривая, за ней приходится подрихтовывать сборочные артефакты руками - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/cmake/ix.sh#L52
(кстати, пользуясь случаем - полайкайте, чтоли, https://github.com/google/tcmalloc/issues/126 - прошу G-word company, чтобы они поддержали сборку каноничного tcmalloc без Bazel)
* Число пересборок библиотек стало меньше. Потому что раньше я принудительно собирал некоторые гуевые приложения с tcmalloc, а остальные - с mimalloc, а сейчас все получается с tcmalloc. Поэтому всякие mesa + gtk + qt раньше собирались по 2 раза, а теперь 1.
* у tcmalloc очень большой footprint - размер на диске 600Kb. 400Kb сам tcmalloc + 200Kb c++ runtime. Это довольно дофига, сильно вырос объем дискового пространства, занимаемого базовыми утилитами OS.
Я, наконец-то, нашел время это все подрихтовать, теперь базовые утилиты собираются с другим набором флагов - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/set/system/0/ix.sh#L4 :
* curses=netbsd говорит нам, что не нужно использовать ncurses для этих утилит. На минус куча лишних terminfo в базовом образе.
* intl_ver=no говорит нам, что не надо использовать gnu gettext для интернационализации, не нужно это в утилитах, которые не видит пользователь. Вообще, предполагается, что каждый пользователь сам, в своем #realm, решает, какие утилиты использовать
* purec=musl/unwrap говорит нам, что мы используем libc musl без переопределения аллокатора. Встроенный в musl аллокатор как раз хорош для такого рода использования.
Ну и, раз я уж этим занялся, то я аккуратно:
* почикал из системных пакетов неиспользуемые тулзы. Например, https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/dbus/sys/ix.sh#L5 - Действительно, зачем в системном пакете что-то, отличное от dbus-daemon? Клиента, если надо, пользователь поставит в свой #realm.
* Редко запускаемые, one-shot программы пожал с помощью upx. busybox не пожал, нефиг разжимать при каждом запуске cp/rm/mv/etc. Демоны тоже жать не стал, им нужен backing store за замапленной программой в памяти. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/iwd/sys/ix.sh#L12 Кстати, fun fact - upx почти не имеет смысла с динамической линковкой, но хорошо помогает в случае статической. В копилку примеров решений, которые по разному работают в разных мирах.
После всех этих действий объем базового #realm упал с 40 мегабайт до 17 - https://pastebin.com/raw/6b9Xtg5n (причем 7Mb из них - сжатая в 1 файл питонячка бинаря ix - graph executor моего пакетного менеджера, который надо переписать на С++/Rust).
Напомню, что мой базовый #realm позволяет поднять OS с настроенной сетью и серверной частью seat/input/sound/etc.
Давеча писал про свой дефолтный аллокатор, и про то, что это, во многом, эмоциональное решение.
Короче, я привел свои эмоции в соответствие реальности, и перешел на tcmalloc по дефолту.
* https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/c/alloc/ix.sh#L5 - по сути, это изменение 1 строчки кода, после чего весь репозиторий будет линковаться с tcmalloc, если не указано обратное
* конечно, реальное изменение было несколько больше, потому что, я напомню, цепочка #bootstrap у меня теперь строится автоматически, и теперь tcmalloc может использоваться раньше в этой цепочке, когда мой инструментарий был недостаточен, чтобы собрать его полную версию. Самое простое - не готов perl, для запуска GNU autohell скриптов. Поэтому я взял более свежую версию gperftools, где есть поддержка cmake. Сборка cmake там пока молодая, немного кривая, за ней приходится подрихтовывать сборочные артефакты руками - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/cmake/ix.sh#L52
(кстати, пользуясь случаем - полайкайте, чтоли, https://github.com/google/tcmalloc/issues/126 - прошу G-word company, чтобы они поддержали сборку каноничного tcmalloc без Bazel)
* Число пересборок библиотек стало меньше. Потому что раньше я принудительно собирал некоторые гуевые приложения с tcmalloc, а остальные - с mimalloc, а сейчас все получается с tcmalloc. Поэтому всякие mesa + gtk + qt раньше собирались по 2 раза, а теперь 1.
* у tcmalloc очень большой footprint - размер на диске 600Kb. 400Kb сам tcmalloc + 200Kb c++ runtime. Это довольно дофига, сильно вырос объем дискового пространства, занимаемого базовыми утилитами OS.
Я, наконец-то, нашел время это все подрихтовать, теперь базовые утилиты собираются с другим набором флагов - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/set/system/0/ix.sh#L4 :
* curses=netbsd говорит нам, что не нужно использовать ncurses для этих утилит. На минус куча лишних terminfo в базовом образе.
* intl_ver=no говорит нам, что не надо использовать gnu gettext для интернационализации, не нужно это в утилитах, которые не видит пользователь. Вообще, предполагается, что каждый пользователь сам, в своем #realm, решает, какие утилиты использовать
* purec=musl/unwrap говорит нам, что мы используем libc musl без переопределения аллокатора. Встроенный в musl аллокатор как раз хорош для такого рода использования.
Ну и, раз я уж этим занялся, то я аккуратно:
* почикал из системных пакетов неиспользуемые тулзы. Например, https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/dbus/sys/ix.sh#L5 - Действительно, зачем в системном пакете что-то, отличное от dbus-daemon? Клиента, если надо, пользователь поставит в свой #realm.
* Редко запускаемые, one-shot программы пожал с помощью upx. busybox не пожал, нефиг разжимать при каждом запуске cp/rm/mv/etc. Демоны тоже жать не стал, им нужен backing store за замапленной программой в памяти. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/iwd/sys/ix.sh#L12 Кстати, fun fact - upx почти не имеет смысла с динамической линковкой, но хорошо помогает в случае статической. В копилку примеров решений, которые по разному работают в разных мирах.
После всех этих действий объем базового #realm упал с 40 мегабайт до 17 - https://pastebin.com/raw/6b9Xtg5n (причем 7Mb из них - сжатая в 1 файл питонячка бинаря ix - graph executor моего пакетного менеджера, который надо переписать на С++/Rust).
Напомню, что мой базовый #realm позволяет поднять OS с настроенной сетью и серверной частью seat/input/sound/etc.
GitHub
support another build system · Issue #126 · google/tcmalloc
Please, please support anything but bazel. bazel is very uncommon, huge, and depends on java. Having java in build toolchain is not always possible. (this is off-topic, but I can not really underst...
👍8🤯2❤1
#alsa #gold
Победил проблему со звуком. Как? Что было?
Было 3 одновременных неприятных бага, которые устроены так, что, пока не заборешь все 3, звука не будет, и даже не будет понятно, есть у тебя прогресс, или нет.
* Как я уже рассказывал, система у меня определяла 2(на самом деле 3, но это неважно) аудиокарточки - hdmi выход в видеокарте, и встройку. alsa выбрала в качестве карты по умолчанию hdmi выход, поэтому звук, даже если и шел куда-то, то, явно, не туда.
* libalsa silently fail, если в системе нет группы audio. Конечно, нам в протокол общения с ядром обязательно надо указать эту информацию, даже если пользователю не нужен доступ к этой группе(у меня пользователи напрямую не ходят в alsa, а ходят в мультиплексор sndiod). Повторю - наличие пользователя в этой группе не нужно, важно наличие этой группы на машине. PZDS.
* В alsa все выходы по умолчанию mute. Это не было бы проблемой, если бы я знал/помнил, как это выглядит в "графическом" alsamixer. Выглядит оно... незаметно, скажем так. То, что каналы замучены, я нашел в полном большом выхлопе какой-то отладочной тулзы.
Наверное, стоит упомянуть, что, прежде чем чинить alsa, я попробовал вывести звук через alsa oss emulation, но у меня, с ходу, не получилось, потому что oss сейчас, конечно, уже так себе поддерживается в клиентах. Например, я нигде не смогу указать, что нужна именно вторая карта(к этому моменту я уже понимал, что звуковые карты перепутаны).
Все заработало? Нет!
Но сначала история из прошлого.
Я думаю, многие помнят, что в Я была попытка "завести" офис в Калифорнии. В этот момент времени в компании работало довольно много импортных разработчиков, на встречи с которыми я регулярно попадал.
Нужно сказать, что Я, к тому моменту, была компанией очень молодой, работала там вчерашняя школота и студентота, а новые разработчики были опытные и повидавшие всякое.
Помню замечательный момент, когда на одной из таких встреч наш молодой и задорный руководитель транспортного цеха начал рассказывать, какой и куда код нужно распихать по разным системам робота и поиска Яндекса, и употребил замечательное слово "протаскивание".
В этот момент один из импортных разработчиков, видимо, доведенный до отчаяния окружающей школотой, начал орать на нас отборным английским матом, выделяя два основных поинта:
* there is no such thing as "protaskivanie"! #protaskivanie
и
* what the hell code are your writing?
Короче, система должна быть устроена так, что не нужно заниматься протаскиванием данных ни в какую сторону.
Представляйте данные на верних уровнях в том же формате, как они используются на нижних, и не занимайтесь ручным преобразованием этих форматов.
К чему это я?
Авторы #sndiod решили позаниматься "protaskivanie" - они погрузили формат описания звукового устройства в какой-то свой формат, и мне понадобилось еще полчаса чтения кода, чтобы понять, что нужно запускать не "sndiod -f 1", а "sndiod -f rsnd/1". Что такое этот rsnd, и зачем он там нужен, я не понял.
С другой стороны, я пытаюсь делать так, чтобы "protaskivanie" не было нужно, поэтому я сделал так, что номер карты можно указать параметром ко всему #realm, и он попадет прямо в самый скрипт настройки sndiod:
Этот флажочек сам пробулькивается до конечного скрипта:
https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bin/sndio/runit/scripts/ix.sh#L8
После этого все заработало, звук появился сразу и везде, кроме epiphany, потому что там аццкий gstreamer, с которым я еще вообще не разбирался.
Победил проблему со звуком. Как? Что было?
Было 3 одновременных неприятных бага, которые устроены так, что, пока не заборешь все 3, звука не будет, и даже не будет понятно, есть у тебя прогресс, или нет.
* Как я уже рассказывал, система у меня определяла 2(на самом деле 3, но это неважно) аудиокарточки - hdmi выход в видеокарте, и встройку. alsa выбрала в качестве карты по умолчанию hdmi выход, поэтому звук, даже если и шел куда-то, то, явно, не туда.
* libalsa silently fail, если в системе нет группы audio. Конечно, нам в протокол общения с ядром обязательно надо указать эту информацию, даже если пользователю не нужен доступ к этой группе(у меня пользователи напрямую не ходят в alsa, а ходят в мультиплексор sndiod). Повторю - наличие пользователя в этой группе не нужно, важно наличие этой группы на машине. PZDS.
* В alsa все выходы по умолчанию mute. Это не было бы проблемой, если бы я знал/помнил, как это выглядит в "графическом" alsamixer. Выглядит оно... незаметно, скажем так. То, что каналы замучены, я нашел в полном большом выхлопе какой-то отладочной тулзы.
Наверное, стоит упомянуть, что, прежде чем чинить alsa, я попробовал вывести звук через alsa oss emulation, но у меня, с ходу, не получилось, потому что oss сейчас, конечно, уже так себе поддерживается в клиентах. Например, я нигде не смогу указать, что нужна именно вторая карта(к этому моменту я уже понимал, что звуковые карты перепутаны).
Все заработало? Нет!
Но сначала история из прошлого.
Я думаю, многие помнят, что в Я была попытка "завести" офис в Калифорнии. В этот момент времени в компании работало довольно много импортных разработчиков, на встречи с которыми я регулярно попадал.
Нужно сказать, что Я, к тому моменту, была компанией очень молодой, работала там вчерашняя школота и студентота, а новые разработчики были опытные и повидавшие всякое.
Помню замечательный момент, когда на одной из таких встреч наш молодой и задорный руководитель транспортного цеха начал рассказывать, какой и куда код нужно распихать по разным системам робота и поиска Яндекса, и употребил замечательное слово "протаскивание".
В этот момент один из импортных разработчиков, видимо, доведенный до отчаяния окружающей школотой, начал орать на нас отборным английским матом, выделяя два основных поинта:
* there is no such thing as "protaskivanie"! #protaskivanie
и
* what the hell code are your writing?
Короче, система должна быть устроена так, что не нужно заниматься протаскиванием данных ни в какую сторону.
Представляйте данные на верних уровнях в том же формате, как они используются на нижних, и не занимайтесь ручным преобразованием этих форматов.
К чему это я?
Авторы #sndiod решили позаниматься "protaskivanie" - они погрузили формат описания звукового устройства в какой-то свой формат, и мне понадобилось еще полчаса чтения кода, чтобы понять, что нужно запускать не "sndiod -f 1", а "sndiod -f rsnd/1". Что такое этот rsnd, и зачем он там нужен, я не понял.
С другой стороны, я пытаюсь делать так, чтобы "protaskivanie" не было нужно, поэтому я сделал так, что номер карты можно указать параметром ко всему #realm, и он попадет прямо в самый скрипт настройки sndiod:
pg-> ./ix list system
{'flags': {'alsa_device': '1', 'failsafe': '1'},
'name': 'set/system/0'}
Этот флажочек сам пробулькивается до конечного скрипта:
https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bin/sndio/runit/scripts/ix.sh#L8
После этого все заработало, звук появился сразу и везде, кроме epiphany, потому что там аццкий gstreamer, с которым я еще вообще не разбирался.
🔥10😁4👍1
#stal/IX, часть вторая, почему я делаю так, а не иначе. #gold
* Структура директорий.
Тут все довольно просто, я не понимаю, как сейчас можно пилить новый дистрибутив по LSB/FHS https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
Это какое-то жуткое legacy, оставшееся с времен начала Unix, с кучей слабо решаемых проблем(dll hell, атомарные обновления(ostree - это хак, и не уговаривайте в обратном)).
FS должна представлять из себя content adressable storage, по типу git/nix/guix.
Так мы получаем почти бесплатно, just to name a few:
- мультиверсионность
- быстрые накаты и откаты
- атомарные апдейты(переключение всей конфигурации - переключение 1 symlink)
- бесплатное кеширование сборочных артефактов в пакетной системе
- non-root/user package management. Это прямое следствие из content adressable storage.
* Функциональное управление конфигурацией.
Речь идет про то, что, фактически, содержимое etc/ определяется рядом настроек #realm, и описанием пакетной базы.
Руками в etc/ лезть нельзя, оно генерится скриптами подготовки #realm, и вообще, read-only.
Не буду тут много писать, кто знает, тот понимает, а остальным я за 2 предложеняи все равно не объясню.
* Static linking
https://gavinhoward.com/2021/10/static-linking-considered-harmful-considered-harmful/ - хороший текст с summary, почему основные предъявы к статической линковке не выдерживают серьезной критики.
https://lore.kernel.org/lkml/CAHk-=whs8QZf3YnifdLv57+FhBi5_WeNTG1B-suOES=RcUSmQg@mail.gmail.com/ - я думаю, что вы уже поняли, что я считаю Линуса еще тем упырем, но враг моего врага - мой друг.
- tooling для нее все еще лучше, потому что она простая, как 5 копеек
- судя по форумам, в Linux вечная проблема с динамически загружаемыми плагинами - что-то не нашлось в runtime, и из-за этого ничего не работает. У меня слинковалось - значит, заявленная функциональность будет доступна.
- получившиеся бинари, несмотря на некоторое дублирование объектного кода, быстрее.
- FS чище, нет лишнего мусора, я про каждый файл могу сказать, что он у меня делает. В том же nix/guix могут быть десятки вариантов одной и той же библиотеки, это ungrepable лапша.
- как следствие, эстетически проще иметь разные варианты одной и той же библиотеки, потому что они не мозолят глаза.
- личный фактор
Я последние лет 15 насаждаю статическую линковку в Я, и, в целом, преуспел в этом.
Я имею амбицию показать миру, что на основе этой модели можно получить полноценный, не игрушечный, дистрибутив. Игрушечные, типа stali, oasis, и так далее - это, простите, школьная поделка на фоне того, что уже сделал я.
* Здоровый минимализм. Я хочу иметь возможность обозреть всю систему.
No code bloat, no systemd, no pipewire(?), etc
In general, no vendor lock on RedHat/IBM software.
Красношляпые очень хотят залочить экосистему Linux на себя. На systemd, на gstreamer, как на часть pipewire, etc.
Не вижу в этом ничего хорошего, да и возможности понимать, как работает система, весь этот софт мешает.
Я тут совсем коротенько отмечу, что я не против, если кто-то сделает вариант stal/IX поверх systemd, я этому не мешаю, и даже готов помочь.
https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bin/dbus - поштырьте на эту папку, у меня даже runit скрипты не являются частью основного пакета, чтобы можно было параллельно иметь systemd/s6/etc юниты.
* Структура директорий.
Тут все довольно просто, я не понимаю, как сейчас можно пилить новый дистрибутив по LSB/FHS https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
Это какое-то жуткое legacy, оставшееся с времен начала Unix, с кучей слабо решаемых проблем(dll hell, атомарные обновления(ostree - это хак, и не уговаривайте в обратном)).
FS должна представлять из себя content adressable storage, по типу git/nix/guix.
Так мы получаем почти бесплатно, just to name a few:
- мультиверсионность
- быстрые накаты и откаты
- атомарные апдейты(переключение всей конфигурации - переключение 1 symlink)
- бесплатное кеширование сборочных артефактов в пакетной системе
- non-root/user package management. Это прямое следствие из content adressable storage.
* Функциональное управление конфигурацией.
Речь идет про то, что, фактически, содержимое etc/ определяется рядом настроек #realm, и описанием пакетной базы.
Руками в etc/ лезть нельзя, оно генерится скриптами подготовки #realm, и вообще, read-only.
Не буду тут много писать, кто знает, тот понимает, а остальным я за 2 предложеняи все равно не объясню.
* Static linking
https://gavinhoward.com/2021/10/static-linking-considered-harmful-considered-harmful/ - хороший текст с summary, почему основные предъявы к статической линковке не выдерживают серьезной критики.
https://lore.kernel.org/lkml/CAHk-=whs8QZf3YnifdLv57+FhBi5_WeNTG1B-suOES=RcUSmQg@mail.gmail.com/ - я думаю, что вы уже поняли, что я считаю Линуса еще тем упырем, но враг моего врага - мой друг.
- tooling для нее все еще лучше, потому что она простая, как 5 копеек
- судя по форумам, в Linux вечная проблема с динамически загружаемыми плагинами - что-то не нашлось в runtime, и из-за этого ничего не работает. У меня слинковалось - значит, заявленная функциональность будет доступна.
- получившиеся бинари, несмотря на некоторое дублирование объектного кода, быстрее.
- FS чище, нет лишнего мусора, я про каждый файл могу сказать, что он у меня делает. В том же nix/guix могут быть десятки вариантов одной и той же библиотеки, это ungrepable лапша.
- как следствие, эстетически проще иметь разные варианты одной и той же библиотеки, потому что они не мозолят глаза.
- личный фактор
Я последние лет 15 насаждаю статическую линковку в Я, и, в целом, преуспел в этом.
Я имею амбицию показать миру, что на основе этой модели можно получить полноценный, не игрушечный, дистрибутив. Игрушечные, типа stali, oasis, и так далее - это, простите, школьная поделка на фоне того, что уже сделал я.
* Здоровый минимализм. Я хочу иметь возможность обозреть всю систему.
No code bloat, no systemd, no pipewire(?), etc
In general, no vendor lock on RedHat/IBM software.
Красношляпые очень хотят залочить экосистему Linux на себя. На systemd, на gstreamer, как на часть pipewire, etc.
Не вижу в этом ничего хорошего, да и возможности понимать, как работает система, весь этот софт мешает.
Я тут совсем коротенько отмечу, что я не против, если кто-то сделает вариант stal/IX поверх systemd, я этому не мешаю, и даже готов помочь.
https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bin/dbus - поштырьте на эту папку, у меня даже runit скрипты не являются частью основного пакета, чтобы можно было параллельно иметь systemd/s6/etc юниты.
Wikipedia
Filesystem Hierarchy Standard
defines the directory structure and directory contents in Linux operating systems
👍18🔥2🥰1👏1
commit -m "better"
Попробовал использовать mold в качестве основого линкера. #bootstrap_science Я как-то уже писал, что у меня есть возможность собрать целое поддерево с уникальным набором флагов. Это прямо незаменимый механизм для bootstrap. Потому что весь bootstrap можно…
#bootstrap #bootstrap_science
У меня давно стояла задача - научиться прикапывать какое-то подмножество пакетов, чтобы, при очистке сборочного кеша, сборка не начиналась с 0.
Сейчас поясню на пальцах.
Допустим, вы, в процедуре bootstrap, собираете clang + coreutils, которые, потом, используются для сборки всего остального. Но для их сборки вам нужны промежуточные инструменты A, B, C.
Вы собрали себе нужный набор пакетов, сделали #ix gc, после чего A, B, C были удалены, так как они никому не нужны для работы.
А теперь, представьте себе, что какой-то конечный, user visible код случайно по сборке стал напрямую зависеть от A(или от B, или от C) Тогда, при попытке собрать этот таргет, нам придется воссоздать A, а значит, пройти всю цепочку bootstrap целиком.
Собственно, моя задача - найти такое множество пакетов, которе, если "заякорить"(то есть, сделать доступными после ya gc), то bootstrap никогда не будет происходить полностью(кроме как случаев, когда меняется сама цепочка bootstrap).
Я пробовал найти такое множество пакетов пару раз, но оно получалось вкривь и вкось.
До тех пор, пока я не переделал цепочку bootstrap, как в предыдущем посте, на который я ответил.
После этого задача стала тривиальной - надо взять все сборочные таргеты, у которых в качестве "мешка инструментов для сборки" указан набор от предыдущего шага bootstrap.
Понятно же, почему это правило порождает необходимый и достаточный набор инструментов?
Потому что если прикопать именно его, то вот этот самый N-1 набор инструментов больше не понадобится, и потому что этого набора заведомо достаточно, чтобы собрать все остальное.
Вот, я перечислил все такие инструменты в 1 таргете - https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bld/ix.sh
Это очень удобно, потому что теперь, чтобы прикопать эти инструменты, мне достаточно завести #realm с этим таргетом(realm задает множество корней для gc).
Все, как я люблю - нового механизма не случилось, а его функции исполняются старыми.
У меня давно стояла задача - научиться прикапывать какое-то подмножество пакетов, чтобы, при очистке сборочного кеша, сборка не начиналась с 0.
Сейчас поясню на пальцах.
Допустим, вы, в процедуре bootstrap, собираете clang + coreutils, которые, потом, используются для сборки всего остального. Но для их сборки вам нужны промежуточные инструменты A, B, C.
Вы собрали себе нужный набор пакетов, сделали #ix gc, после чего A, B, C были удалены, так как они никому не нужны для работы.
А теперь, представьте себе, что какой-то конечный, user visible код случайно по сборке стал напрямую зависеть от A(или от B, или от C) Тогда, при попытке собрать этот таргет, нам придется воссоздать A, а значит, пройти всю цепочку bootstrap целиком.
Собственно, моя задача - найти такое множество пакетов, которе, если "заякорить"(то есть, сделать доступными после ya gc), то bootstrap никогда не будет происходить полностью(кроме как случаев, когда меняется сама цепочка bootstrap).
Я пробовал найти такое множество пакетов пару раз, но оно получалось вкривь и вкось.
До тех пор, пока я не переделал цепочку bootstrap, как в предыдущем посте, на который я ответил.
После этого задача стала тривиальной - надо взять все сборочные таргеты, у которых в качестве "мешка инструментов для сборки" указан набор от предыдущего шага bootstrap.
Понятно же, почему это правило порождает необходимый и достаточный набор инструментов?
Потому что если прикопать именно его, то вот этот самый N-1 набор инструментов больше не понадобится, и потому что этого набора заведомо достаточно, чтобы собрать все остальное.
Вот, я перечислил все такие инструменты в 1 таргете - https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bld/ix.sh
Это очень удобно, потому что теперь, чтобы прикопать эти инструменты, мне достаточно завести #realm с этим таргетом(realm задает множество корней для gc).
Все, как я люблю - нового механизма не случилось, а его функции исполняются старыми.
🔥7👏2
Удивительно, но я, кажется, сделал.
За выходные закрыл 2 последних задачи, без которых отдать #stal/ix кому-то было просто невозможно:
* Возможность указывать графический стек, отличный от RADV + ZINK. Теперь у меня поддержаны различные комбинации графических стеков для AMD, Intel, ну и софтверный стек для всех остальных.
Немного в сторону - llvmpipe прямо хорош, он насытил все 16 ядер моего ноутбука, и выдал вполне приличные RPS в Q3 на 4к экране.
Сделано это с помощью указания флага —mesa=radv для #realm, в котором стоят программы пользователя.
Тут добавлю, что "сыграли" мои усилия по разделению движка mesa от драйверов, для того, чтобы переключиться с radv, на, скажем, llvmpipe, было пресобрано только несколько конечных программ.
* И, собственно, вторая задача - возможность указать глобальные флаги на #realm.
Ничего особенно сложного, просто весьма муторно, и пришлось переписать всю обработку command line. Не то, чтобы в старый код нельзя было вписать каким-то хаком, но я на этот код давно точил зубы, и, вот, появился повод.
Про новый разбор командной строки я напишу отдельно, КМК, получилось довольно занятно. Теперь можно за один запуск поменять все #realm-ы произвольным образом(добавить/удалить * realm/package/global_flag/package_flag).
Теперь только написать документацию, и заняться сайтом.
За выходные закрыл 2 последних задачи, без которых отдать #stal/ix кому-то было просто невозможно:
* Возможность указывать графический стек, отличный от RADV + ZINK. Теперь у меня поддержаны различные комбинации графических стеков для AMD, Intel, ну и софтверный стек для всех остальных.
Немного в сторону - llvmpipe прямо хорош, он насытил все 16 ядер моего ноутбука, и выдал вполне приличные RPS в Q3 на 4к экране.
Сделано это с помощью указания флага —mesa=radv для #realm, в котором стоят программы пользователя.
Тут добавлю, что "сыграли" мои усилия по разделению движка mesa от драйверов, для того, чтобы переключиться с radv, на, скажем, llvmpipe, было пресобрано только несколько конечных программ.
* И, собственно, вторая задача - возможность указать глобальные флаги на #realm.
Ничего особенно сложного, просто весьма муторно, и пришлось переписать всю обработку command line. Не то, чтобы в старый код нельзя было вписать каким-то хаком, но я на этот код давно точил зубы, и, вот, появился повод.
Про новый разбор командной строки я напишу отдельно, КМК, получилось довольно занятно. Теперь можно за один запуск поменять все #realm-ы произвольным образом(добавить/удалить * realm/package/global_flag/package_flag).
Теперь только написать документацию, и заняться сайтом.
🔥23👍4👏1🤔1
#busybox, #GNU
Не очень важная тема, но, знаете, backlog копится, иногда надо разбирать.
10 лет назад я считал, что это какая-то интересная игрушка, в стиле "засунь дистрибутив Linux на floppy", и что там невозможно "жить" всерьез.
3 года назад я сделал его переоценку, и решил, что busybox вполне себе годится для #realm system, для загрузки системы, ну, и... всё.
Сейчас я уже где-то полгода использую busybox, как основную реализацию posix утилит, да и, в общем-то, как замену grep/sed/find/etc, coreutils, util-linux(!!, набор linux-специфичных системных утилит), и так далее. Даже awk я использую из busybox, он там куцый, но чтобы выбрать строку по значению поля - вполне подходит.
Я даже какое-то время использовал shell из busybox(ash), но, в конце-концов, вернулся на bash(причем 3-ий, в районе четвертого они что-то сильно для меня поломали). По довольно странной причине - у ash плохо работает интеграция с mc. Если бы не это, так бы и использовал.
Ну, ладно, less у них кривой, но кому нужен less в наше время?
Короче, я так скажу - в настоящее время я не вижу смысла строить Linux систему на основе утилит от GNU(косое, кривое, совместимое только с собой, да и то, не всегда, нечто), потому что а зачем? Вам, правда, нужна одна из 1000 этих опций, длиной от 20 символов, которые невозможно запомнить?
Да, тут еще, конечно, важно за это поблагодарить сообщество alpine linux, которое, насколько я понимаю, следит, чтобы всякие говноскрипты были с busybox совместимы. Может, еще openwrt, но это не точно.
Не очень важная тема, но, знаете, backlog копится, иногда надо разбирать.
10 лет назад я считал, что это какая-то интересная игрушка, в стиле "засунь дистрибутив Linux на floppy", и что там невозможно "жить" всерьез.
3 года назад я сделал его переоценку, и решил, что busybox вполне себе годится для #realm system, для загрузки системы, ну, и... всё.
Сейчас я уже где-то полгода использую busybox, как основную реализацию posix утилит, да и, в общем-то, как замену grep/sed/find/etc, coreutils, util-linux(!!, набор linux-специфичных системных утилит), и так далее. Даже awk я использую из busybox, он там куцый, но чтобы выбрать строку по значению поля - вполне подходит.
Я даже какое-то время использовал shell из busybox(ash), но, в конце-концов, вернулся на bash(причем 3-ий, в районе четвертого они что-то сильно для меня поломали). По довольно странной причине - у ash плохо работает интеграция с mc. Если бы не это, так бы и использовал.
Ну, ладно, less у них кривой, но кому нужен less в наше время?
Короче, я так скажу - в настоящее время я не вижу смысла строить Linux систему на основе утилит от GNU(косое, кривое, совместимое только с собой, да и то, не всегда, нечто), потому что а зачем? Вам, правда, нужна одна из 1000 этих опций, длиной от 20 символов, которые невозможно запомнить?
Да, тут еще, конечно, важно за это поблагодарить сообщество alpine linux, которое, насколько я понимаю, следит, чтобы всякие говноскрипты были с busybox совместимы. Может, еще openwrt, но это не точно.
🤔7👍4👎2
commit -m "better"
#bs #vendor #ix_run #dev_shell #gold Меня удручает состояние современных OSS систем сборки. Расскажу сегодня про такой аспект: каждая уважающая себя современная система сборки хочет иметь в себе пакетный менеджер. То есть, обеспечивать не только выполнение…
Слушайте, ну мужик сказал - мужик сделал! #ix_run #dev_shell
Мне было норм, но людям такое, конечно, стыдно отдавать.
Реализовал обещанную фичу, про возможность запуска команды в произвольном #realm.
Стало удобно.
А еще хорошие новости - одному из наших радиослушателей удалось поставить ix, по последней версии инструкции!
Короче, нет причин не попробовать.
...До этого, чтобы запустить menuconfig для настроек ядра, я запускал сборку ядра через ix, нажмал ctrl-c, шел в оставшуюся сборочную папку, и там, в настроенном окружении, запускал make menuconfig.
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/mconf.o
HOSTCC scripts/kconfig/lxdialog/checklist.o
HOSTCC scripts/kconfig/lxdialog/inputbox.o
HOSTCC scripts/kconfig/lxdialog/menubox.o
HOSTCC scripts/kconfig/lxdialog/textbox.o
HOSTCC scripts/kconfig/lxdialog/util.o
HOSTCC scripts/kconfig/lxdialog/yesno.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
HOSTCC scripts/kconfig/lexer.lex.o
HOSTCC scripts/kconfig/menu.o
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTCC scripts/kconfig/util.o
HOSTLD scripts/kconfig/mconf
configuration written to .config
*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.
> ix run set/menuconfig -- make HOSTCC=cc menuconfig
Мне было норм, но людям такое, конечно, стыдно отдавать.
Реализовал обещанную фичу, про возможность запуска команды в произвольном #realm.
Стало удобно.
А еще хорошие новости - одному из наших радиослушателей удалось поставить ix, по последней версии инструкции!
Короче, нет причин не попробовать.
👍10
Недавно рассказывал, что соорудил рендеринг #svg иконок в png, через #inkscape.
Все же, мне этот процесс кажется не очень технологичным:
* Inkscape - overkill по зависимостям
* И, хотя я и сделал, что от пакета с иконками зависит только финальный #realm, все равно, inkscape пересобирается довольно часто, и приводит к пересборке иконок.
* Еще он срет в консоль сообщениями про то, что, мол, не может найти display.
Поэтому я решил найти что-то попроще!
Сначала гугл мне посоветовал https://github.com/cppfw/svgren
На первый взгляд, библиотека неплохая, много чего умеет. Но, к сожалению, ее автор сошел с ума (кстати, а вы уже поняли, что эта моя характеристика почти никогда не несет отрицательной коннотации? Мы тут сумасшедших любим, они делают все самое интересное!):
* Он распилил проект на очень много маленьких зависимостей, которые надо опакетить.
* Так-то оно, может, и неплохо, но он к ним запилил свою систему сборки, с классным названием prorab - https://github.com/cppfw/svgren/blob/master/makefile, и с не менее классным определением библиотек в системе, с чем я уже развлекаться не захотел.
Я решил, что, раз автор меня так не уважает, и не хочет, чтобы я пользовался его кодом - ну, так и быть! Мораль - не выебывайтесь при выборе системы сборки.
Вторым вариантом гугл мне предложил https://github.com/sammycage/lunasvg, на ней я и остановился.
У нее в комплекте поставки есть тулза svg2png, которой мне оказалось достаточно, чтобы поверх нагородить рендеринг иконок.
"Из коробки" мне не понравилось только сглаживание, поэтому я наладил такой вот процесс https://github.com/pg83/ix/blob/main/pkgs/bld/iconker/lunasvg/iconker.py:
* Рендерим иконку в большом разрешении
* Ресайзим через Imagemagic's convert во все нужные разрешения
Заодно оно стало быстрее работать, потому что рендеринг, все же, медленнее, чем resize.
Хорошая, годная, библиотека, подумываю написать поверх нее pixman loader, вместо librsvg-шного.
Все же, мне этот процесс кажется не очень технологичным:
* Inkscape - overkill по зависимостям
* И, хотя я и сделал, что от пакета с иконками зависит только финальный #realm, все равно, inkscape пересобирается довольно часто, и приводит к пересборке иконок.
* Еще он срет в консоль сообщениями про то, что, мол, не может найти display.
Поэтому я решил найти что-то попроще!
Сначала гугл мне посоветовал https://github.com/cppfw/svgren
На первый взгляд, библиотека неплохая, много чего умеет. Но, к сожалению, ее автор сошел с ума (кстати, а вы уже поняли, что эта моя характеристика почти никогда не несет отрицательной коннотации? Мы тут сумасшедших любим, они делают все самое интересное!):
* Он распилил проект на очень много маленьких зависимостей, которые надо опакетить.
* Так-то оно, может, и неплохо, но он к ним запилил свою систему сборки, с классным названием prorab - https://github.com/cppfw/svgren/blob/master/makefile, и с не менее классным определением библиотек в системе, с чем я уже развлекаться не захотел.
Я решил, что, раз автор меня так не уважает, и не хочет, чтобы я пользовался его кодом - ну, так и быть! Мораль - не выебывайтесь при выборе системы сборки.
Вторым вариантом гугл мне предложил https://github.com/sammycage/lunasvg, на ней я и остановился.
У нее в комплекте поставки есть тулза svg2png, которой мне оказалось достаточно, чтобы поверх нагородить рендеринг иконок.
"Из коробки" мне не понравилось только сглаживание, поэтому я наладил такой вот процесс https://github.com/pg83/ix/blob/main/pkgs/bld/iconker/lunasvg/iconker.py:
* Рендерим иконку в большом разрешении
* Ресайзим через Imagemagic's convert во все нужные разрешения
Заодно оно стало быстрее работать, потому что рендеринг, все же, медленнее, чем resize.
Хорошая, годная, библиотека, подумываю написать поверх нее pixman loader, вместо librsvg-шного.
GitHub
GitHub - cppfw/svgren: :camera: SVG rendering library in C++
:camera: SVG rendering library in C++. Contribute to cppfw/svgren development by creating an account on GitHub.
🔥8👍6😁3
Не помню, рассказывал про свое микросоревнование с самим собой, или нет, беглый поиск по каналу ничего такого не нашел, поэтому рассказываю, тем более, есть повод!
Просто писать код - скучно, это уже давно доведено до автоматизма.
Поэтому я, по крайней мере, для pet project, изобретаю какие-нибудь ограничения, которым дополнительно должен удовлетворять код.
В #ix такое ограничение - это размер ядра(интерпретация пакетов и подготовка графа) в байтах.
Причем жестить нельзя - например, нельзя для этого сокращать имена функций, методов, и так далее.
Нужно мне длинное название метода - значит, будет длинное название! https://github.com/pg83/ix/blob/main/core/package.py#L261
(Кстати, немного в сторону - я обнаружил, что, в разных языках, я соблюдайю разные принципы именования. Например, в python это "короткие имена переменных, длинные(очень) имена методов и функций". Потому что типов нет, и иначе грепать становится невозможно)
Основные источники профита:
* Вынос кода из ядра в шаблоны. Это, кстати, хорошо по многим причинам - чем больше информации в шаблонах, и меньше в ядре, тем точнее uid ноды меняется в зависимости от фактических изменений результата.
* Поиск дублирующегося "смысла" (например, в какой-то момент мне довольно сильно помогло сократить размер понимание, что #realm/env - это точно такая же нода, как и любой прочий пакет, и обрабатывать ее надо тем же кодом)
Довольно долго я держал планку в 40к, при этом добавляя новые фичи, потом, полгода, держался на 50к, но вот последние месяца 2 - 3 забрался за 51, и оно никак не ужималось.
Сегодня я отыграл до 49к, бесплатно добавил новую команду "let", и очень рад этому факту!
"let" - это такой аналог "mut", который не перемещает глобальную симлинку на свежеподготовленный realm/env. Эта команда полезна, когда хочется перед переключением системы на новый root, посмотреть, чего там в нем таки лежит.
(напомню, что, по сути, мой корень - это симлинка на вот такой read only realm)
Как я это ужал?
Я отрефакторил команды mut/let/run/build в фасады к одной простой функции, которая умеет подготовить набор realm для заданной командной строки:
* let - это просто вызов этой функции
* mut - это let + несколько вызовов os.symlink()
Дальше интереснее:
* build - это интерпретация заданного command line в контексте создания нового эфемерного realm.
* run - это build, в финале которого еще запускаем одну команду в свежесозданном окружении.
https://github.com/pg83/ix/blob/main/core/cmd_realm.py#L27 - собственно, вот эти 5 функций, которые позволили мне стереть 1.5k кода!
Просто писать код - скучно, это уже давно доведено до автоматизма.
Поэтому я, по крайней мере, для pet project, изобретаю какие-нибудь ограничения, которым дополнительно должен удовлетворять код.
В #ix такое ограничение - это размер ядра(интерпретация пакетов и подготовка графа) в байтах.
Причем жестить нельзя - например, нельзя для этого сокращать имена функций, методов, и так далее.
Нужно мне длинное название метода - значит, будет длинное название! https://github.com/pg83/ix/blob/main/core/package.py#L261
(Кстати, немного в сторону - я обнаружил, что, в разных языках, я соблюдайю разные принципы именования. Например, в python это "короткие имена переменных, длинные(очень) имена методов и функций". Потому что типов нет, и иначе грепать становится невозможно)
Основные источники профита:
* Вынос кода из ядра в шаблоны. Это, кстати, хорошо по многим причинам - чем больше информации в шаблонах, и меньше в ядре, тем точнее uid ноды меняется в зависимости от фактических изменений результата.
* Поиск дублирующегося "смысла" (например, в какой-то момент мне довольно сильно помогло сократить размер понимание, что #realm/env - это точно такая же нода, как и любой прочий пакет, и обрабатывать ее надо тем же кодом)
Довольно долго я держал планку в 40к, при этом добавляя новые фичи, потом, полгода, держался на 50к, но вот последние месяца 2 - 3 забрался за 51, и оно никак не ужималось.
Сегодня я отыграл до 49к, бесплатно добавил новую команду "let", и очень рад этому факту!
"let" - это такой аналог "mut", который не перемещает глобальную симлинку на свежеподготовленный realm/env. Эта команда полезна, когда хочется перед переключением системы на новый root, посмотреть, чего там в нем таки лежит.
(напомню, что, по сути, мой корень - это симлинка на вот такой read only realm)
Как я это ужал?
Я отрефакторил команды mut/let/run/build в фасады к одной простой функции, которая умеет подготовить набор realm для заданной командной строки:
* let - это просто вызов этой функции
* mut - это let + несколько вызовов os.symlink()
Дальше интереснее:
* build - это интерпретация заданного command line в контексте создания нового эфемерного realm.
* run - это build, в финале которого еще запускаем одну команду в свежесозданном окружении.
https://github.com/pg83/ix/blob/main/core/cmd_realm.py#L27 - собственно, вот эти 5 функций, которые позволили мне стереть 1.5k кода!
GitHub
ix/core/package.py at main · pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
🔥10😱6👍4😁1🤯1
https://www.openwall.com/lists/oss-security/2022/12/21/6
Оч. смешная бага в парсере procfs. Все ломается, когда в имени процесса есть пробел.
Как-то уже писал, повторюсь. Я принципиально оставил в разрешенных путях для корня IX, и для имен #realm'ов только a-zA-Z0-9_, потому что как ты не экранируй, все равно какой-то инструмент на других символах сломается.
А про взаимодействие ядра и userspace - там везде, конечно, нужен машинно-генерируемый json, без ручных printf.
Я себе клятвенно пообещал, что у меня, в моей личной OS, будет только один syscall, принимающий json, и возвращающий json, все остальное будет мультиплексироваться полями этого json.
Оч. смешная бага в парсере procfs. Все ломается, когда в имени процесса есть пробел.
Как-то уже писал, повторюсь. Я принципиально оставил в разрешенных путях для корня IX, и для имен #realm'ов только a-zA-Z0-9_, потому что как ты не экранируй, все равно какой-то инструмент на других символах сломается.
А про взаимодействие ядра и userspace - там везде, конечно, нужен машинно-генерируемый json, без ручных printf.
Я себе клятвенно пообещал, что у меня, в моей личной OS, будет только один syscall, принимающий json, и возвращающий json, все остальное будет мультиплексироваться полями этого json.
🔥8🤔8❤2👌2🥴2👍1
commit -m "better"
https://keunwoo.com/notes/rebooting/ #reboot Хороший, только очень длинный текст, в котором написаны 2 простых мысли: * В любой системе нарастает энтропия. По другому - в системе есть https://ru.wikipedia.org/wiki/Гейзенбаг. * Перезагрузка(VM, хоста, программы)…
В продолжении темы #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 shutdown process"
У меня, конечно, shutdown - моментальный процесс, даже процессы не убиваю.
Если каким-то сервисам нужно сохранять состояние, то это надо делать регулярно, во время работы, в момент изменения этого состояния. А откладывать это на стадию shutdown - так себе затея, потому что это будет кривой, косой, и неотлаженный кусок говнокода, реально срабатывающий один раз из 10.
Знаете, такой подход дает результаты. Например, я так нашел отсутствующий вызов sync в пакетном менеджере - иногда, после reboot, система просыпалась со старым system #realm, потому что переключение симлинки откатывалось файловой системой. А не нашел бы - был бы странный https://en.wikipedia.org/wiki/Heisenbug
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 shutdown process"
У меня, конечно, shutdown - моментальный процесс, даже процессы не убиваю.
Если каким-то сервисам нужно сохранять состояние, то это надо делать регулярно, во время работы, в момент изменения этого состояния. А откладывать это на стадию shutdown - так себе затея, потому что это будет кривой, косой, и неотлаженный кусок говнокода, реально срабатывающий один раз из 10.
Знаете, такой подход дает результаты. Например, я так нашел отсутствующий вызов sync в пакетном менеджере - иногда, после reboot, система просыпалась со старым system #realm, потому что переключение симлинки откатывалось файловой системой. А не нашел бы - был бы странный https://en.wikipedia.org/wiki/Heisenbug
Phoronix
Fedora 38 Change Approved To Mandate Quicker Reboots/Shutdowns
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 shutdown process
🔥14👍3🤔2👎1
commit -m "better"
Слушайте, ну мужик сказал - мужик сделал! #ix_run #dev_shell ... HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/mconf.o HOSTCC scripts/kconfig/lxdialog/checklist.o HOSTCC scripts/kconfig/lxdialog/inputbox.o HOSTCC scripts/kconfig/lxdialog/menubox.o…
"ix run" (или любая другая метапоисковая система), конечно, сильно меняет подход к разработке. #ix_run #dev_shell
Свой go-шный portal я собираю, например, вот так - https://github.com/pg83/portal/blob/main/build.sh
Хочется cgo, и зависимость от какий-то C-шной библиотеки?
Свой go-шный portal я собираю, например, вот так - https://github.com/pg83/portal/blob/main/build.sh
ix run set/dev/go -- go build"Где-то там" строится временный #realm, со всем нужным окружением, в котором запускается свежесобранный go build на мой проект. Оверхед - доли секунды.
Хочется cgo, и зависимость от какий-то C-шной библиотеки?
ix run set/dev/go --cgo lib/gtk/3 -- go build ...Мне кажется, в ближайшие годы какой-то другой способ разрабатываться в oss должен уйти в небытие, потому что, как я уже несколько раз писал, такие метапакетные системы постепенно идут в массы.
GitHub
portal/build.sh at main · pg83/portal
Contribute to pg83/portal development by creating an account on GitHub.
🔥15🤡3👍2🤔2✍1
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
commit -m "better"
Будни #bootstrap, #stal/ix Тут вот коллеги подкинули ссылку на смешной способ сделать Dockerfile исполняемым. https://gist.github.com/adtac/595b5823ef73b329167b815757bbce9f Ничего особо интересного, просто "волшебный" шебанг, который сделает всю работу:…
Подумал, что, на этом примере, могу рассказать про еще одно отличие моей пакетной базы от nix/guix (насколько я понимаю их внутреннее устройство).
Пакеты в nix/guix в своих шебангах имеют абсолютные пути, которые ведут в другие пакеты. То есть, питонячий скрипт в пакете A будет вести в абсолютный путь к питону из пакета B, и будет жесткая зависимость A -> B.
У меня это устроено иначе. Я перепахаю такой шебанг в виде
Я, кстати, не готов зарубаться, какой способ однозначно лучше - и у того, и у дргого, есть понятные плюсы и минусы:
* первый более надежно фиксирует окружение
* второй гибче, хотя может иногда подламываться
* второй мне было проще имплементировать (например, чтобы указать явный путь, нужно уметь делать зависимость на пакет B под определенный target, совпадающий с target A, но, чаще всего, все системы сборки пропишут зависимость на host B, потому что задетектят его при сборке)
В целом, я довольно часто пользуюсь тем, что build python/perl/sh != target python/perl/sh, и связывание происходит в моменте построения полного #realm, в рамках которого все и будет запускаться.
Так вот, когда я только запилил процедуру подмены шебангов с
Скажем,
Я заменил шебанги с добавлением
Пакеты в nix/guix в своих шебангах имеют абсолютные пути, которые ведут в другие пакеты. То есть, питонячий скрипт в пакете A будет вести в абсолютный путь к питону из пакета B, и будет жесткая зависимость A -> B.
У меня это устроено иначе. Я перепахаю такой шебанг в виде
#!/usr/bin/env python3
, и пакет будет зависеть от "какого-то" питона. Связывание с конкретным питоном случится в момент формирования #realm - какой питон ты туда поставишь, такой и будет использоваться.Я, кстати, не готов зарубаться, какой способ однозначно лучше - и у того, и у дргого, есть понятные плюсы и минусы:
* первый более надежно фиксирует окружение
* второй гибче, хотя может иногда подламываться
* второй мне было проще имплементировать (например, чтобы указать явный путь, нужно уметь делать зависимость на пакет B под определенный target, совпадающий с target A, но, чаще всего, все системы сборки пропишут зависимость на host B, потому что задетектят его при сборке)
В целом, я довольно часто пользуюсь тем, что build python/perl/sh != target python/perl/sh, и связывание происходит в моменте построения полного #realm, в рамках которого все и будет запускаться.
Так вот, когда я только запилил процедуру подмены шебангов с
#!/a/b/c/prog
-> #!/usr/bin/env prog
, то столкнулся с тем, что такая подмена не всегда работает. Скажем,
#/a/b/c/perl -w
нужно заменить на #!/usr/bin/env -S perl -w
, а не на #!/usr/bin/env perl -w
, потому что второй способ не будет работать по причинам, которые я излагал в предыдущем тексте.Я заменил шебанги с добавлением
-S
, увидел, что у меня попадала половина скриптов, полез разбираться, и нашел вот такую неприятную особенность в busybox.👍12❤4🔥3🥱1
А я, тем временем, занялся автоматизацией своей home #lab.
Моя home lab - это 3 сервера, в которых примерно 200 ядер, + 3 - 4 небольших нод, которые сделаны из всякого хлама, скопившегося за несколько лет.
Понятно дело, что все это и так крутится под #stal/ix, но, до сего момента, все это выглядело так - я руками ставил OS на машину, а дальше заходил на нее через ssh, и руками вводил какие-то команды, которые что-то делали с этой машиной.
Конечно, можно было бы взять что-то готовое, но:
* нужно есть свою собачью еду.
* https://en.wikipedia.org/wiki/Content-addressable_storage - очень хорошая основа для всякого там IaC, и мне хочется сделать еще один подход к этому снаряду.
Если совсем коротко:
* Ручная наливка хоста заканчивается тем, что мы удаляем set/stalix из system #realm, и ставим туда почти то же самое, но с автоапдейтом.
* Автоапдейт занимается тем, что "приводит систему к состоянию", которое указано в каком-то заранее определенном репозитории.
Состояние - это набор пакетов, заданное состояние - это набор пакетов, который описан в какой-то конкретной версии репозитория.
https://github.com/pg83/lab - вот код, который полностью описывает состояние моей home lab.
Он состоит:
* Fork stal/IX, который я периодически сливаю с upstream.
* Одна точка входа, тот самый пакет, который содержит ссылку на auto updater, и на пакеты, которые должны стоять в системе - https://github.com/pg83/lab/tree/master/pkgs/lab https://github.com/pg83/lab/blob/master/pkgs/lab/ix.sh#L7
Я его устанавливаю на каждый хост, он ставит:
* сам auto updater. https://github.com/pg83/lab/blob/master/pkgs/lab/services/autoupdate/scripts/ix.sh - простой скрипт, который в цикле забирает новое состояние с github, и приводит систему в соответствие этому состоянию.
* пакеты, которые должны быть на каждом хосте
* и диспетчер, который ведет на список пакетов, уникальный для хоста - https://github.com/pg83/lab/blob/master/pkgs/lab/ix.sh#L6
Вот, например, список пакетов для "host1" - https://github.com/pg83/lab/blob/master/pkgs/lab/hosts/host1/ix.sh. Видно, что он крутит мой ci, и какую-то ерунду, про которую расскажу в другой раз.
Так, я на вас вывалил некоторый "framework", в рамках которого потом буду рассказывать про свой home lab.
Моя home lab - это 3 сервера, в которых примерно 200 ядер, + 3 - 4 небольших нод, которые сделаны из всякого хлама, скопившегося за несколько лет.
Понятно дело, что все это и так крутится под #stal/ix, но, до сего момента, все это выглядело так - я руками ставил OS на машину, а дальше заходил на нее через ssh, и руками вводил какие-то команды, которые что-то делали с этой машиной.
Конечно, можно было бы взять что-то готовое, но:
* нужно есть свою собачью еду.
* https://en.wikipedia.org/wiki/Content-addressable_storage - очень хорошая основа для всякого там IaC, и мне хочется сделать еще один подход к этому снаряду.
Если совсем коротко:
* Ручная наливка хоста заканчивается тем, что мы удаляем set/stalix из system #realm, и ставим туда почти то же самое, но с автоапдейтом.
* Автоапдейт занимается тем, что "приводит систему к состоянию", которое указано в каком-то заранее определенном репозитории.
Состояние - это набор пакетов, заданное состояние - это набор пакетов, который описан в какой-то конкретной версии репозитория.
https://github.com/pg83/lab - вот код, который полностью описывает состояние моей home lab.
Он состоит:
* Fork stal/IX, который я периодически сливаю с upstream.
* Одна точка входа, тот самый пакет, который содержит ссылку на auto updater, и на пакеты, которые должны стоять в системе - https://github.com/pg83/lab/tree/master/pkgs/lab https://github.com/pg83/lab/blob/master/pkgs/lab/ix.sh#L7
Я его устанавливаю на каждый хост, он ставит:
* сам auto updater. https://github.com/pg83/lab/blob/master/pkgs/lab/services/autoupdate/scripts/ix.sh - простой скрипт, который в цикле забирает новое состояние с github, и приводит систему в соответствие этому состоянию.
* пакеты, которые должны быть на каждом хосте
* и диспетчер, который ведет на список пакетов, уникальный для хоста - https://github.com/pg83/lab/blob/master/pkgs/lab/ix.sh#L6
Вот, например, список пакетов для "host1" - https://github.com/pg83/lab/blob/master/pkgs/lab/hosts/host1/ix.sh. Видно, что он крутит мой ci, и какую-то ерунду, про которую расскажу в другой раз.
Так, я на вас вывалил некоторый "framework", в рамках которого потом буду рассказывать про свой home lab.
Wikipedia
Content-addressable storage
data storage mechanism
👍10❤5🔥3🤡3🆒2
Будни #bootstrap, #homelab, #lab короткая эволюция того, как я катаю код на свой флот.
Мой макетник (#ix) позволяет описать любую статическую комбинацию пакетов, с произвольными флагами для их настройки.
В принципе, этого достаточно, чтобы удобно описать конфигурацию одной машины. Собственно, так у меня и был описан мета-пакет, который и был установлен в мой #realm - https://github.com/pg83/ix/blob/main/pkgs/set/pg/ix.sh
В принципе, этого точно так же достаточно, чтобы описать конфигурацию небольшого кластера - вот, например, у меня по папочке с такими наборами на каждый хост - https://github.com/pg83/lab/tree/master/lab/hosts
Но это, конечно, неудобно.
Поэтому следующий шаг - это условный json, один на весь кластер, и по нему уже строится конечная конфигурация. Ну, то есть, есть один конфиг, он знает текущий хост, и, в зависимости от этого, настраивает пакеты:
https://github.com/pg83/lab/blob/master/lab/common/ix.sh#L23-L27
Вот, если наш текущий хост входит в определенную группу хостов, на нем поднимаем набор сервисов с определенными настройками.
Дальше - больше.
Дальше мы не хотим иметь этот json статическим, а хотим его генерировать на python. Вот, пример того, как такой json с описанием кластера может генерироваться на python:
https://github.com/pg83/lab/blob/5f6ebd3c236ba42793cfbf0a5ecbb148688dfda7/lab/ix.sh
А дальше Остапа понесло, он не смог остановиться, и применил свой любимый прием -
https://github.com/pg83/lab/blob/master/lab/cg.py#L9-L39
2 класса - сервиса, и производящая функция всего кластера, которая полностью описывает его структуру, имея на вход низкоуровневое описание кластера (сети, диски, и так далее).
Класс (а, точнее, объект класса) может описать работающий демон (в том числе, нужные пользователи, зависимости, данные), дальше случается магия, которая превращает это в набор сервисов для каждой машины, описанный в предыдущем шаге.
Этот код может работать в цикле, замкнутом на обратный фидбек от кластера, и от того, как там работает предыдущая конфигурация И, тем самым, реагировать на внешние события.
Мой макетник (#ix) позволяет описать любую статическую комбинацию пакетов, с произвольными флагами для их настройки.
В принципе, этого достаточно, чтобы удобно описать конфигурацию одной машины. Собственно, так у меня и был описан мета-пакет, который и был установлен в мой #realm - https://github.com/pg83/ix/blob/main/pkgs/set/pg/ix.sh
В принципе, этого точно так же достаточно, чтобы описать конфигурацию небольшого кластера - вот, например, у меня по папочке с такими наборами на каждый хост - https://github.com/pg83/lab/tree/master/lab/hosts
Но это, конечно, неудобно.
Поэтому следующий шаг - это условный json, один на весь кластер, и по нему уже строится конечная конфигурация. Ну, то есть, есть один конфиг, он знает текущий хост, и, в зависимости от этого, настраивает пакеты:
https://github.com/pg83/lab/blob/master/lab/common/ix.sh#L23-L27
Вот, если наш текущий хост входит в определенную группу хостов, на нем поднимаем набор сервисов с определенными настройками.
Дальше - больше.
Дальше мы не хотим иметь этот json статическим, а хотим его генерировать на python. Вот, пример того, как такой json с описанием кластера может генерироваться на python:
https://github.com/pg83/lab/blob/5f6ebd3c236ba42793cfbf0a5ecbb148688dfda7/lab/ix.sh
А дальше Остапа понесло, он не смог остановиться, и применил свой любимый прием -
eval(pickle.loads(base64.b64decode('...')))
(я сейчас явно слышу гомерический смех пяти человек). А, конкретно, давайте опишем состояние сервисов python объектами, сериазизуем их состояние, и будем использовать как описание кластера:https://github.com/pg83/lab/blob/master/lab/cg.py#L9-L39
2 класса - сервиса, и производящая функция всего кластера, которая полностью описывает его структуру, имея на вход низкоуровневое описание кластера (сети, диски, и так далее).
Класс (а, точнее, объект класса) может описать работающий демон (в том числе, нужные пользователи, зависимости, данные), дальше случается магия, которая превращает это в набор сервисов для каждой машины, описанный в предыдущем шаге.
Этот код может работать в цикле, замкнутом на обратный фидбек от кластера, и от того, как там работает предыдущая конфигурация И, тем самым, реагировать на внешние события.
GitHub
ix/pkgs/set/pg/ix.sh at main · pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
🐳8❤5🌚4🙈4👍2🌭1
Про развитие одного моего механизма настройки программ в /etc.
В /etc лежит довольно много конкатенативных файлов. Это значит, что любой пакет может захотеть завести себе "кусочек" какой-то общей конфигурации.
Например, пакет может захотеть, чтобы в системе был определенный пользователь.
Традиционные дистрибутивы решают эту проблему, требуя, чтобы сервисы умели в схему /etc/xxx.d/, то есть, чтобы они умели читать не 1 конфиг, а целую директорию, куда уже отдельные пакеты будут класть свою часть конфигурации.
У меня /etc приготавливается атомарно, вместе со всеми остальными запчастями system #realm. Поэтому я решил, что я могу не требовать от сервисов того, чтобы они читали директорию, а просто конкатенировать содержимое некоторых директорий в /etc в момент подготовки окружения.
Ну, то есть, сервис в своем install hook создает файл ${out}/etc/passwd.d/some_user, и потом есть hook, который конкатенирует все файлы из etc/passwd.d/* в 1 файл etc/passwd.
Потом я так начал обрабатывать группы.
Потом окружение, которое должно быть доступно всем на машине, для этого любой пакет может просто завести файл etc/env.d/xxx.
Потом публичные ключи для рутового доступа стали объединяться так в authorized_keys.
А потом Остапа понесло.
Я решил, что, вместо 10 копипастных хуков, я заведу 1, но какой!
https://github.com/pg83/ix/blob/main/pkgs/etc/core/concat.sh
Короче, я сказал, что я буду вообще все директории в etc/, которые оканчиваются на .d, превращать в конкатенацию их содержимого, в файле, который образыется из имени этой директории, но без .d:
Это совершенно потрясающий и мощный механизм, у меня теперь на нем сделано вообще все. Даже /etc/runit/{1, 2, 3} генерируются таким образом, то есть, любой пакет может подложить кусочек init скрипта, без всяких там systemd и прочей нечисти.
Поэтому мои startup скрипты, конечно, получились довольно интересные.
Потому что:
* если ты все настройки окружения задаешь декларативно
* у тебя есть вот такой механизм конкатенации
То зачем тебе пользоваться каким-то странными административными тулзами, когда ты просто можешь попросить систему явно сделать то, что тебе нужно?
https://gist.github.com/pg83/ccb23c7fc1dbc986b30d16f25f2b32f8 - вот произвольный init скрипт с одного из моих серверов.
При его чтении нужно понять, что я не пишу его руками, он создается из объединения маленьких кусочков, которые предоставляются пакетами.
Ну, то есть, я могу в систему установить пакет
И это превратится в прямой вызов вида
(на самом деле, я даже такой пакет не ставлю, а его вызов генерируется скриптом, который строит всю топологию моего кластера)
Потому что зачем использовать vendor specific настроечные скрипты того или иного *Manager, если можно сделать проще?
На вид мои стартовые скрипты похожи на какой-то embedded linux, когда вы полностью знаете конфигурацию железки, но они, конечно, мощнее на 2 порядка, потому что строятся из очень высокоуровневого описания.
Поэтому у меня, например, нет /etc/fstab, потому что порядок монтирования проще описать без него, из декларативного описания.
В /etc лежит довольно много конкатенативных файлов. Это значит, что любой пакет может захотеть завести себе "кусочек" какой-то общей конфигурации.
Например, пакет может захотеть, чтобы в системе был определенный пользователь.
Традиционные дистрибутивы решают эту проблему, требуя, чтобы сервисы умели в схему /etc/xxx.d/, то есть, чтобы они умели читать не 1 конфиг, а целую директорию, куда уже отдельные пакеты будут класть свою часть конфигурации.
У меня /etc приготавливается атомарно, вместе со всеми остальными запчастями system #realm. Поэтому я решил, что я могу не требовать от сервисов того, чтобы они читали директорию, а просто конкатенировать содержимое некоторых директорий в /etc в момент подготовки окружения.
Ну, то есть, сервис в своем install hook создает файл ${out}/etc/passwd.d/some_user, и потом есть hook, который конкатенирует все файлы из etc/passwd.d/* в 1 файл etc/passwd.
Потом я так начал обрабатывать группы.
Потом окружение, которое должно быть доступно всем на машине, для этого любой пакет может просто завести файл etc/env.d/xxx.
Потом публичные ключи для рутового доступа стали объединяться так в authorized_keys.
А потом Остапа понесло.
Я решил, что, вместо 10 копипастных хуков, я заведу 1, но какой!
https://github.com/pg83/ix/blob/main/pkgs/etc/core/concat.sh
Короче, я сказал, что я буду вообще все директории в etc/, которые оканчиваются на .d, превращать в конкатенацию их содержимого, в файле, который образыется из имени этой директории, но без .d:
cat etc/xyz.d/* -> etc/xyz
.Это совершенно потрясающий и мощный механизм, у меня теперь на нем сделано вообще все. Даже /etc/runit/{1, 2, 3} генерируются таким образом, то есть, любой пакет может подложить кусочек init скрипта, без всяких там systemd и прочей нечисти.
Поэтому мои startup скрипты, конечно, получились довольно интересные.
Потому что:
* если ты все настройки окружения задаешь декларативно
* у тебя есть вот такой механизм конкатенации
То зачем тебе пользоваться каким-то странными административными тулзами, когда ты просто можешь попросить систему явно сделать то, что тебе нужно?
https://gist.github.com/pg83/ccb23c7fc1dbc986b30d16f25f2b32f8 - вот произвольный init скрипт с одного из моих серверов.
При его чтении нужно понять, что я не пишу его руками, он создается из объединения маленьких кусочков, которые предоставляются пакетами.
Ну, то есть, я могу в систему установить пакет
ix mut system etc/static/ip \
--ip=10.0.0.64 \
--gateway=10.0.0.1 \
--mask=24 \
--iface=eth0
И это превратится в прямой вызов вида
ip addr add 10.0.0.64/24 dev eth0
ip link set eth0 up
route add default gw 10.0.0.1 eth0
resolvconf -u
(на самом деле, я даже такой пакет не ставлю, а его вызов генерируется скриптом, который строит всю топологию моего кластера)
Потому что зачем использовать vendor specific настроечные скрипты того или иного *Manager, если можно сделать проще?
На вид мои стартовые скрипты похожи на какой-то embedded linux, когда вы полностью знаете конфигурацию железки, но они, конечно, мощнее на 2 порядка, потому что строятся из очень высокоуровневого описания.
Поэтому у меня, например, нет /etc/fstab, потому что порядок монтирования проще описать без него, из декларативного описания.
👍13🔥7❤🔥3🤡2🤔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
Будни #bootstrap
Недавно запилил недостающий кусочек движка построения графа зависимостей.
Теперь я могу указывать runtime зависимости хуков, которые должны выполняться при формировании #realm.
Ничего особо сложного, просто ранее мне не требовалось ничего, кроме как компиляция glib схем.
Но, вот, случились две насущные проблемы:
* захотелось преобразовывать .svg иконки в .png не для каждого пакета по отдельности, а когда готов весь #realm
* захотелось уметь строить кеш иконок для gtk. Для этого тоже нужно, чтобы все иконки были доступны в #realm, потому что процедуры объединения нескольких кешей не существует.
Вот так выглядит хук с зависимостью:
https://github.com/pg83/ix/blob/main/pkgs/aux/hicolor/icon/fix/ix.sh
Прямо кусок json, потому что нужно редко, и делать "красиво" лень.
Зачем я вообще строю png для svg иконок?
* потому что а зачем рендерить их каждый раз?
* потому что я использую самый классный доступный рендер (skia), а какие там понапихают всратые nanosvg авторы тех или иных программ - это уже их дело.
Недавно запилил недостающий кусочек движка построения графа зависимостей.
Теперь я могу указывать runtime зависимости хуков, которые должны выполняться при формировании #realm.
Ничего особо сложного, просто ранее мне не требовалось ничего, кроме как компиляция glib схем.
Но, вот, случились две насущные проблемы:
* захотелось преобразовывать .svg иконки в .png не для каждого пакета по отдельности, а когда готов весь #realm
* захотелось уметь строить кеш иконок для gtk. Для этого тоже нужно, чтобы все иконки были доступны в #realm, потому что процедуры объединения нескольких кешей не существует.
Вот так выглядит хук с зависимостью:
https://github.com/pg83/ix/blob/main/pkgs/aux/hicolor/icon/fix/ix.sh
Прямо кусок json, потому что нужно редко, и делать "красиво" лень.
Зачем я вообще строю png для svg иконок?
* потому что а зачем рендерить их каждый раз?
* потому что я использую самый классный доступный рендер (skia), а какие там понапихают всратые nanosvg авторы тех или иных программ - это уже их дело.
GitHub
ix/pkgs/aux/hicolor/icon/fix/ix.sh at main · pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
👍6❤4🔥3🆒1