tgindex
/home/oficsu/blog

/home/oficsu/blog

Статистика

Рандомный блог с утилитарными примерами кода/конфигов и репостами технических интересностей

Последний пост
29 июн.
Последнее чтение
21:35
Постов за неделю
0
Всего постов
20
Тип
открытый
Язык
русский
Категория
Блоги
В каталоге с
13 авг.
Подписчики
121
+1 за 4 дн.
Сутки
0
0,00%
Неделя
 
Месяц
 
Просмотров на пост
796
20 постов
Вовлечённость
657,9%
к подписчикам
Постов в день
0,0
всего 20
Упоминаний
1
каналов
Охват размещения
оценка
1/24сутки в ленте
1/48двое суток
1/72трое суток

Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.

Посты

  • Incident Report: CVE-2024-YIKES Status: Resolved (accidentally) Severity: Critical → Catastrophic → Somehow Fine Summary A compromised dependency in the JavaScript ecosystem led to credential theft, which enabled a supply chain attack on a Rust compression library, which was vendored into a Python build tool, which shipped malware to approximately 4 million developers before being inadvertently patched by an unrelated cryptocurrency mining worm

  • Это же нужно было так точно подметить! Метамодерн — единственное доступное словарное слово среди тех, что включают в себя суффикс -modern, определено как следующее за постмодерном, и для того было с намерением опущено на пикче – наравне с упоминанием C++20, недвусмысленно отсылая на качество и сроки имплементации модулей!

  • 10 июн.3458из jokespp

    без подписи

  • 29 окт.1 2301925

    Приватная предыстория разработки в публичном репозитории Задача: нужно заопенсорсить локально разрабатываемый проект Препятствие: локальная история содержит грязь, да и вообще потенциально опасные вещи вроде приватных ключей, которые затруднительно выискивать в истории, чтобы подчистить Очевидное решение? Сквошим все коммиты в один, например так: git reset "$(git commit-tree "HEAD^{tree}" -m "initial commit")". Затем пушим результат в новый публичный репозиторий, забываем старую историю как страшный сон, и продолжаем вести разработку, отсчитывая историю уже с нового коммита Проблема: а что если мы не хотим забывать старую историю? Что, если нам всё ещё полезна полная история разработки, и мы иногда хотим локально заглядывать в git blame или git log -p (но ни в коем случае не пушить)? Неужели придётся каждый раз обращаться к старой ветке явно, чтобы посмотреть, что было до нашего релиза в публичную репу? Или вообще ребейзить её? Куча скучной нудной унылой повторяющейся работы каждый раз? Менее очевидное решение. Внезапно, git имеет нативное решение проблемы, которое не требует никакой ручной работы и даже никакой автоматизации вроде автоматического ребейза скриптами по крону. Итак, вот полный план действий... 1. Создаём локальную ветку, которая будет ссылаться на нашу старую историю: git branch full-history 2. Сквошим все коммиты в один тем же способом, который был описан выше: git reset "$(git commit-tree "HEAD^{tree}" -m "initial commit")" 3. Подменяем локально наш "initial" коммит настоящей полной историей разработки: git replace -f HEAD full-history 4. Добавляем наш новый публичный репозиторий в качестве ремоута: git remote add origin <url-of-our-public-repo> 5. Убеждаемся, что история нашего репозитория полностью доступна локально, ни одно изменение не было потеряно по пути, и каждый коммит доступен для просмотра или для блейма: git log -p 6. Пушим наш open-source проект, как и было запланировано: git push 6.1. Открываем репозиторий в браузере (или ещё раз клонируем его) и убеждаемся, что мы успешно запушили наш "initial" коммит, который содержит только контент репозитория, но не его полную историю

  • (внезапный мем)

  • Гугл, реддит и автоматический перевод Реддит некоторое время назад научился автоматическому переводу своих страниц. Он даже позволяет настроить список языков пользователя, которые переводить не нужно А ещё он позволяет задать целевой язык прямо в url, что могло бы быть удобной фичей, если бы только не... Если бы не гугл, который у нас, как обычно, умнее всех. Эти гении начали приписывать tl=ru к случайным url реддита в поисковой выдаче, что полностью сломало его ux. И не только мне. Список языков, заданный в профиле, больше не играет роли — случайные странички теперь принудительно переведены на русский, потому что гугл Как чинить? Ну, аддоны, исправляющие эту проблему, есть уже под все браузеры. Однако, поскольку доверия к ним никакого, а вот блокировщик рекламы есть у всех, то и чинить будем самостоятельно через uBlock Origin Открываем его настройки -> My filters, добавляем новое правило... Если хотим отключить автоматический перевод вообще, независимо от целевого языка: ||reddit.com^$removeparam=/tl/ Если же хотим отключить перевод только на русский, оставив переводы на другие языки (не знаю, зачем вам это), то правило будет выглядеть вот так: ||reddit.com^$removeparam=/tl=ru/

  • *** Но запускать аккуратно, достоверно известно, что в такой конфигурации бывают проблемы с (очевидно) Secure Boot и BitLocker. И вы точно не хотите шифровать её с помощью VeraCrypt — три мои попытки (из четырёх, впрочем) оказались неудачными. Хотя я и делал отчаянный шаг, позволяя винде самой создать разделы, после чего копировал разметку обратно на оригинальный физический диск — мог и промахнуться несколькими секторами. А может быть и в утилите ошибка, и она не всегда правильно границы сч... В общем, напоминаю, что она не production-ready

  • ** Я не хотел добавлять "${ovmf[@]}" в качестве основного содержания статьи, но без него примеры были бы неполны и ничего бы просто не запускалось на практике, поэтому разъяснение здесь, в сноске. Запись выше просто раскрывает массив дополнительных аргументов для qemu, добавляя поддержку efi, отсутствие которой может оказаться неожиданностью для уже установленных систем во время запуска. Вот содержимое массива: ovmf=( # add efi firmware -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2-ovmf/x64/OVMF_CODE.4m.fd # take temp snapshot of default efi variables -drive if=pflash,format=raw,snapshot=on,file=/usr/share/edk2-ovmf/x64/OVMF_VARS.4m.fd )

  • * Это кастомная утилита, а не production-ready решение, абсолютную безопасность не гарантирую, как и отсутствие ошибок, способных приводить к повреждению данных. Для прода возьмите более зрелый продукт — VirtualBox это умеет, например, прямо из ui

  • Форвардим физический диск в qemu немного* безопаснее Если у вас дуал-бут, то бывает удобно запустить соседнюю операционную систему в виртуалке. С qemu это вроде бы очень просто — запустили qemu-system-x86_64 -drive format=raw,file=/dev/nvme0n1 "${ovmf[@]}"**, выбрали в загрузчике в виртуалке соседнюю систему и радуемся, всё отлично. Всё отлично до... первой ошибки... В соседнюю систему пошарен уже смонтированный на хосте раздел? Или вообще для запуска случайно выбрали саму хостовую систему? Ну, скорее всего, они уже повреждены; удачи в восстановлении; спасибо за внимание Как решать проблему? Ну, можно попробовать передать наш /dev/nvme0n1 в качестве read-only диска. Правда, в таком режиме у вас с этого диска мало какая система запустится даже, да ещё и опции для перевода в read-only с каждым релизом qemu всё меньше работают... Можно ещё передать -snapshot как глобальную опцию или как локальную для -drive, оно сработает и система, скорее всего, даже запустится Но... А если, всё же, хотим настоящую персистентную запись?.. Хотелось бы иметь магическую утилиту, с помощью которой можно было бы просто скрыть некоторые разделы диска, чтобы диск, состоящий только из оставшихся "безопасных" разделов, которые нам не жалко отдать под запись, передать в qemu И такая утилита у меня даже есть: reassemble-gpt-drive. Она умеет собирать виртуальный диск из перечисленных разделов исходного, из произвольных блочных устройств, из регулярных файлов или даже всего вместе взятого Как она нам поможет и как ею пользоваться? Запустить, подождать, она соберёт виртуальный диск из нужных разделов: ./reassemble-gpt-drive \ --name guest-vdrive \ --source /dev/nvme0n1 \ --ro /dev/nvme0n1p1 \ --rw /dev/nvme0n1p6 \ --rw 7 Что эти опции значат? --name guest-vdrive Имя блочного устройства для нашего диска, теперь наш диск — это /dev/mapper/guest-vdrive, а его разделами будут /dev/mapper/guest-vdrive1, /dev/mapper/guest-vdrive2 и /dev/mapper/guest-vdrive3 --source /dev/nvme0n1 Диск, свойства таблицы разделов которого мы хотим унаследовать. Например, PTUUID --ro /dev/nvme0n1p1 В качестве первого раздела берём блочное устройство /dev/nvme0n1p1, т.е. первый же раздел нашего исходного диска, он же efi-раздел в моём случае --rw /dev/nvme0n1p6 Следующим по счёту разделом берём блочное устройство /dev/nvme0n1p6, у меня это boot-раздел гостевой ОС, которую я хочу запустить. Он никуда у меня не смонтирован, поэтому его безопасно отдавать, в том числе и на запись --rw 7 Берём ещё один раздел. Мы окончательно поддались лени, и у нас не осталось сил даже полное имя блочного устройства написать, так что ограничимся просто номером раздела относительно устройства, указанного в --source; это тоже сработает. Это как раз и будет корень нашей операционной системы, которую мы хотим запускать Вот теперь мы, наконец, можем запустить виртуалку с нашим виртуальным прокси-диском: qemu-system-x86_64 -drive format=raw,file=/dev/mapper/guest-vdrive "${ovmf[@]}"**. Гостевая система увидит наш диск как единое целое, даже несмотря на то, что часть его регионов фактически будут read-only, а попытки записи в них будут приводить к ошибкам Зачем ещё эта утилита бывает полезной, кроме как для запуска операционных систем? Ну, например, установщик винды крайне капризный и может сыпать совершенно невнятными ошибками на попытку установить винду по соседству с операционками. Поэтому мы можем разметить наш диск под установку винды вручную. После этого, отдав ей efi, пару резервных разделов и ещё раздел под саму винду, можно собрать из этого виртуальный диск: ./reassemble-gpt-drive \ -n win \ -S /dev/nvme0n1 \ --rw 1 \ --rw 2 \ --rw 3 \ --rw 4 С таким диском, проброшенным в qemu, она уже не видит соседних разделов и внезапно не падает в процессе установки, считая себя единоличной хозяйкой системы (ну, до следующего запуска вне qemu, конечно). Она так даже не портит загрузочные записи в efi, ставя себя выше grub, ведь в виртуалке свои efi-переменные. Её потом можно даже (брезгливо) запускать***

  • без подписи

  • Напоминаю, кстати, про свой виджет, заменяющий ⌨️⌨️⌨️ в баше на более удобную альтернативу. Заодно он является и альтернативой для похожего виджета от fzf, обеспечивая в сравнении с ними... 🐚 Нечёткий поиск Можно опечататься, но команда всё равно будет найдена в отличие от баша, где даже исправление опечатки потребует сброса поиска 🔍 Мгновенное выполнение команды Нажав ⌨️⌨️⌨️, вы можете выполнить найденную команду мгновенно. В отличие от fzf-виджета, вам не нужно сначала вставлять команды в промпт одним нажатием, а потом выполнять её ещё одним отдельным нажатием кнопки 🔍 Вставку в промпт Если, всё же, команду нужно вставить в промпт для редактирования, то: * ⌨️⌨️⌨️ — вставит и переместит курсор в конец промпта; * ⌨️ и ⌨️ — вставят и переместят курсор рядом с искомым словом; 🐚🔍 Навигацию по истории обоими способами * Как и в fzf, ⌨️/⌨️ позволяют листать короткий список результатов поиска; * Как и в bash, ⌨️⌨️⌨️, нажатый повторно, переключится на следующую команду в истории 🐚🔍 Поддержку произвольных форматов времени Теперь можно установить произвольный HISTTIMEFORMAT — дата последнего выполнения будет отображаться рядом с каждой командой в истории в указанном формате 🔍 Поддержку огромной истории В отличие от fzf-виджета, читающего историю от самой старой к новой, мой сначала читает недавнюю. Это позволяет начать поиск мгновенно сразу после открытия виджета, не дожидаясь чтения всего файла. Наиболее свежие команды (они же и наиболее релевантные) будут доступны для поиска мгновенно 🐚🔍 Вставку самого поискового запроса ⌨️⌨️⌨️ вставит в промпт искомый текст в случае, когда вы начали печатать поисковый запрос и в середине осознали, что именно такой команды в истории никогда не было, но вот в запросе уже содержится большая часть нужной команды — просто вставьте запрос и продолжайте печать уже в промпте, а не в режиме поиска истории 🐚🔍 Предпросмотр длинных команд с подсветкой ⌨️⌨️⌨️ отобразит превью с синтаксической подсветкой для каждого из ваших десятистрочных однострочников в истории, облегчив поиск среди старых экспериментов Естественно, все перечисленные сочетания можно настроить, отключив их или заменив. А демонстрационный пример доступен на ютубе или гифкой ниже

  • [начало; продолжение этого поста] Ну, вроде как... да, работает. Только вот по сравнению с версией, использующий setxkbmap, имеет неприятную особенность. На локскрине видно неприятное дёрганье текущей раскладки в момент применения обновлённого конфига Хотелось бы научиться реагировать на локскрин быстрее. Вооружившись в очередной раз dbus-monitor, начинаем следить за событиями при блокировке экрана и обнаруживаем кое-что интересное: signal path=/ScreenSaver; interface=org.kde.screensaver; member=AboutToLock Это событие, которое... Скажем так... плохо документировано. Не самый надёжный вариант, если мы хотим гарантировать работоспособность кода в будущем. Однако, это же и одно из самых ранних событий среди возникающих. И оно подходит нам практически идеально. А чтобы решит проблему совместимости с будущими версиями, будем просто закладываться не только на это событие, но и на старое в качестве страховки, меняя раскладку при получении каждого из них. Ведь если мы первым делом отреагировали на AboutToLock, изменив список раскладок, то повторная реакция на ActiveChanged ни к каким визуальным багам уже не приведёт В идеале, можно было бы не обрабатывать ActiveChanged, если он возник сразу после AboutToLock, добавив несколько лишних условий... И я решу эту задачу с помощью ostrich algorithm, ведь поддержка сложных условий в баше выльется в куда больший объем проблем, чем лишняя перезагрузка раскладки на каждый вызов локскрина Так что вместо просто соберём накопленные решения в один цельный скрипт и подведём краткий итог: a) да, работает под X11; b) да, не имеет неприятных багов под X11; c) да, работает и под Wayland; d) да, не имеет неприятных глитчей при блокировке экрана; e) да и просто решает проблему, упрощая использование Плазмы, наконец ¯\_(ツ)_/¯ Ссылки на вопросы и решения, которые в процессе мне помогли: 1. Оригинальный скрипт: alexsorokin.ru/2019/01/plasma-lock-screen-kb-layout 2. Альтернативная реализация с пояснениями: superuser.com/a/820619 3. Ещё одна альтернативная реализация: unix.stackexchange.com/a/368632 4. Применяем изменения раскладок: discuss.kde.org/t/re-read-configuration-after-setting-change/15008 5. Применяем изменения раскладок: gist.github.com/bojidar-bg/5dd246cd3c442893a333b36955ae0753

  • [начало; продолжение этого поста] И ведь действительно работает... Под Wayland. Под X11... Тоже работает. Ну, иногда. Всё так же плохо, как и у старого решения. Ну, наверное, корень проблемы общий с setxkbmap Но делать-то что-то нужно? Дебажить неизвестную часть Плазмы или X11 представляется не самым увлекательным времяпрепровождением, поэтому поищем... костыли. Например, посмотрим как ведут себя проблемные окна, последив за событиями в dbus через dbus-monitor. И сразу же вываливаются тонны спама. Поскольку отлаживать что-то в таком режиме затруднительно, рискнём упростить себе задачу: dbus-monitor | grep -i layout -С10 Теперь попытаемся воспроизвести проблему и последим за событиями. Оказывается, и правда — переключение с проблемного окна, в котором зависла одна us раскладка, на нормальное окно (и обратно) приводит к генерации таких событий: string "type='signal',sender='org.kde.keyboard',path='/Layouts',interface='org.kde.KeyboardLayouts',member='layoutChanged'" Попробуем узнать, с чего и на что конкретно меняется наша раскладка в эти моменты. В оригинальном скрипте добавим к циклу, обрабатывающему события, ещё один фильтр с нашим событием об изменении раскладки: dbus-monitor interface=org.kde.KeyboardLayouts,member=layoutListChanged # ... И добавим функцию, запрашивающую список раскладок: request-layout-list() { dbus-send --print-reply --session --reply-timeout=500 \ --dest=org.kde.keyboard /Layouts \ org.kde.KeyboardLayouts.getLayoutsList } Позвав её, действительно убеждаемся, что при переключении фокуса на некоторые окна, список раскладок и правда меняется. Вот окна, с которыми всё хорошо: array [ struct { string "us" string "" string "English (US)" } struct { string "ru" string "" string "Russian" } ] А вот у окон, с которыми всё плохо, упоминание ru раскладки отсутствует... Попытаемся отследить проблемные окна, воспользовавшись наивным решением. Если список раскладок изменился и при запросе списка раскладок в ответ мы получили сообщение, в котором только одна строка со struct, а так же в котором есть хотя бы одна строка вида string "us", то мы можем с некоторой долей уверенности заключить, что мы поймали наш баг: has-us-layout() { local stdin="$1" echo "$stdin" | grep -q 'string "us"' } is-single-us-layout() { local stdin="$(cat)" local layout_count="$(echo "$stdin" | grep struct -c)" local is_us="$(echo "$stdin" | grep -q 'string "us"')" [ "$layout_count" == 1 ] \ && has-us-layout "$stdin" } И можно автоматически обработать такой баг, заставив Плазму обновить список раскладок повторно: if request-layout-list | is-single-us-layout; then apply-layouts fi Ну теперь-то работает?..

  • [продолжение поста про смену списка раскладок в локскрине] Было бы логично поискать решения в api самой Плазмы, а не полагаться на setxkbmap. Наивные попытки нагуглить такое api или почитать документацию провалились, а потому было решено идти более сложным путём Раз уж у нас есть меню в общесистемных настройках, которое способно изменить список раскладок на лету и сохранить его между перезагрузками, то вывод очевидный — у нас одновременно есть: а) некоторое хранилище или конфиг, хранящий список раскладок; б) механизм, позволяющий моментально применить обновлённый конфиг Поскольку проще всего найти первое, а второе искать, отталкиваясь от второго, включаем отслеживание изменений файлов в интересующих нас директориях и меняем в настройках список раскладок: inotifywait --monitor --recursive /home/oficsu/{.local,.config} И только один файл изменился в момент сохранения настроек с изменённым списком раскладок; целевой конфиг найден — ~/.config/kxkbrc. К счастью, его содержимое крайне простое и не требует инструментально сравнивать разные версии файла, чтобы найти отличия. Интересующий нас ключ виден сразу — LayoutList в группе Layout Отредактировать файл инструментально не сложно: kwriteconfig6 --file kxkbrc --group Layout --key LayoutList us kwriteconfig6 --file kxkbrc --group Layout --key LayoutList us,ru И можем даже сразу написать готовую функцию: update-layouts() { local list="$1" kwriteconfig --file kxkbrc --group Layout --key LayoutList "$list" } Отлично, менять конфиг мы умеем. Можем ли мы теперь заставить плазму перечитать конфиг? Можно пойти и почитать, как это сделано в systemsettings... А ещё можно... погуглить?.. И, естественно, я выбрал лёгкий путь. На моё счастье, по запросу "kxkbrc" reload гугл вполне себе выдаёт очень свежее решение с довольно простым и удобным dbus api. Тоже напишем готовую функцию: apply-layouts() ( dbus-send --session --type=signal --reply-timeout=1000 \ --dest=org.kde.keyboard /Layouts \ org.kde.keyboard.reloadConfig ) То, что нужно, осталось только адаптировать код из упомянутой статьи выше и всё заработает? И, если повезёт, то ещё и под Wayland?

  • Ввод пароля в локскрине Есть замечательная статья про установку английской раскладки в момент активации локскрина Однако, она несколько устарела и имеет проблемы — работает только под X11 и не работает под Wayland и где-то с KDE Plasma 5.25 переключение языка перестало работать. Только иногда и только для некоторых окон, что невероятно раздражает и требует нетривиальных действий, чтобы восстановить список раскладок Обе проблемы удалось решить, полный код лежит на моём gist, а все подробности — в следующих сообщениях

  • Учимся поднимать сервер автоматически при переходе из браузера Для начала самостоятельно написать пачку юнит файлов под systemd. Мне удобно, когда мои собственные конфиги не смешиваются с вендорскими, а потому в примере будем исходить из того, что они лежат…

  • Полезная новость для программистов: Если вы куда-то поедете, и вам нужна хорошая LLM-моделька которая бы работала оффлайн, пару дней назад Qwen Coder случайно обновили (это модели от китайского гиганта Алибаба) и в сеть утекла классная новая 7B моделька:…

  • 20 нояб. 2024 г.50417из denissexy

    Полезная новость для программистов: Если вы куда-то поедете, и вам нужна хорошая LLM-моделька которая бы работала оффлайн, пару дней назад Qwen Coder случайно обновили (это модели от китайского гиганта Алибаба) и в сеть утекла классная новая 7B моделька: По тестам новый Qwen2.5.1 Coder 7B теперь всего на пару процентов ниже, чем старенькая gpt-4-1106-preview — для модели такого размера, это невероятно клевые результаты; GGUF файлы качаем тут, в месте, где утечка случилась — уже все откатили обратно. Вторая полезная новость, это то что у llama.cpp появился нормальный веб-сервер, которым даже можно пользоваться. Инструкция как устанавливать на Mac M-процессоры (на Windows я только играю, сорри): 1) Открываем терминал, и делаем `git clone https://github.com/ggerganov/llama.cpp.git`в нужную папку; 2) Заходим в папку и делаем `LLAMA_METAL=1 make -j` 3) Ждем 4) Запускаем веб сервер этой командой `./llama-server -m «./models/Qwen2.5.1-Coder-7B-Instruct-Q5_K_M.gguf» -t 8 —mlock -v —alias totally-not-an-AGI -fa —temp 0.4 —repeat-penalty 1.10 —repeat-last-n −1 —top-k 40 —top-p 0.90 —min-p 0.10 -c 16000`, что означает каждый параметр можно почитать тут 5) Открываем в браузере http://127.0.0.1:8080/ 6) Поздравлю, вы папина гордость и нейронный хакер! На видео, как раз пример, как модель пишет код в "у нас есть чатгпт дома" P.S. Да – все вкладки мне нужны и совсем нет лишних ☕️ ⚡️ Update: Новые модели выложили официально, вот их GGUF: https://huggingface.co/bartowski/Qwen2.5-Coder-32B-Instruct-GGUF https://huggingface.co/bartowski/Qwen2.5-Coder-14B-Instruct-GGUF https://huggingface.co/bartowski/Qwen2.5-Coder-3B-Instruct-GGUF https://huggingface.co/bartowski/Qwen2.5-Coder-0.5B-Instruct-GGUF https://huggingface.co/lmstudio-community?search_models=2.5-coder

  • Channel photo updated