Bash Days | Linux | DevOps
23.3K subscribers
151 photos
25 videos
663 links
Авторский канал от действующего девопса

Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.

Автор: Роман Шубин
Реклама: @maxgrue

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Download Telegram
Из каждого чайника слышу про ZED, это такой новомодный IDE от авторов Atom. Славится своей скоростью и минимализмом, никаких тебе новогодних ёлок и перегруженных интерфейсов. Чем-то напоминает VIM.

Дошли руки потыкать. Но одного желания мало, под винду сука дистрибутив не завезли. Хочешь под винду? Скомпилируй из исходников!

😀😃😄😁😅😂🤣😊
😇🙂🙃😉😌😍🥰😘
😗😙😚😋😛😝😜🤪
🤨🧐🤓😎🤩🥳😏😒

Да легко! Спустя 4 часа ебатни и дебага — спасибо, идите нахуй!

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


Залил в себя пару пиалок до-хун-пао, словил дзен и нашел выход.

Пиздуем на сайт и ищем ZED. Ебала жаба гадюку! Всё уже придумано и собрано за нас. Верните мне 4 часа компиляции!

Открываем CMD и хуячим:

scoop bucket add extras
scoop install extras/zed


Всё!

Если не установлен scoop, ставим так:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex


Что по IDE?

Моё почтение, все нужные мне плагины по девопсовым делам — есть. Даже маркдаун и превью работает. Шикарно!

Из коробки есть подключение к удаленным серверам. То есть подключаешься к своему удаленному серверу разработки и пишешь код. В лучших традициях VSCode.

Чтобы по умолчанию в качестве терминала у тебя не открывался CMD, делаем финт ушами и дружим ZED с WSL.

  "terminal": {
"shell": {
"program": "C:\\Windows\\System32\\wsl.exe"
},
"font_family": "Hack Nerd Font Mono",
"font_size": 15,
"line_height": "standard"
}


Теперь открывается ZSH, или что там у тебя установлено в WSL.

Ааа, забыл, в ZED можно подключить ИИ агенты, причем можешь локально поднять дипсик или т.п. и использовать его прям в IDE.


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

🛠 #windows #ide #dev

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
149
Как не стремись к автоматизации, всегда найдется какой-нибудь легаси сервис, который требует ручного обслуживания.

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

Доступ к сервису имели многие, поэтому люди порой троили и запускали команды в каталоге сервиса от root. Сервису было на это поебать, но до момента его перезапуска.

Обычно это чинилось очень легко, через chown -R. Все это знали и никого это не смущало. Короче костыль ебаный.

Казалось бы, есть масса способов предотвратить такие ошибки: правильные права на файлы, ACL’ы, SELinux.

Но веселья в этом мало! Поэтому я решил заебенить свой собственный мониторинг файловой системы. Скиллов то предостаточно, хули нет.

Спойлер: Я залез в кроличью нору и знатно так хлебнул гавна.

Попытка намбер 1

В Linux есть API под названием fanotify, с его помощью можно получать события о действиях с файлами в юзерспейс.

Всё просто: инициализируем fanotify_init, указываем каталоги через fanotify_mark и читаем события из дескриптора.

Но тут же вылез огромный хуй:

- нельзя отслеживать каталоги рекурсивно (только целый маунт)
- anotify даёт только PID процесса, который что-то сделал. А чтобы узнать UID/GID — нужно лезть в /proc/<pid>/status. То есть на каждое событие приходится открывать и парсить файлы в /proc.

Решение вполне рабочее, но громоздкое. Я такие не люблю, этож думать надо, вайбкодингом не решается.

Попытка намбер 2

Вспоминаем что есть eBPF. Это штука позволяет запускать программы прямо в ядре Linux. Они компилируются в байткод, проходят проверку, а потом гоняются через JIT почти с нативной скоростью.

Что такое eBPF можешь почитать тут и тут.


В eBPF заебись то, что можно цепляться за разные функции ядра. Например, можно подцепиться к vfs_mkdir или vfs_create — это общий слой для работы с файлами.

То есть единая точка входа. Там можно отлавливать события и фильтровать их, не гоняя лишние переключения контекста.

Но и тут вылез хуй:

- kprobes на функции VFS нестабильны, в новых ядрах сигнатуры могут меняться или функции вообще исчезнуть.

- фильтрацию приходится писать прямо в eBPF, а там свои ограничения. Нет бесконечных циклов, стек всего ~512 байт.

Да блядь…

Как я победил рекурсивный обход

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

Но так как в eBPF нельзя сделать «бесконечный» цикл, я ограничил глубину с помощью MAX_DEPTH.

На практике этого вполне достаточно. Глубина каталогов мне известна. Ну и конечно, пришлось аккуратно работать с RCU-локами, чтобы дерево не поменялось в момент обхода.

➡️ Кусок кода в первом комментарии, сюда не влез.


Как можно улучшить

В идеале использовать не VFS-хуки, а LSM hooks (Linux Security Module).

Они стабильнее, понятнее и позволяют сразу работать с путями. Там можно красиво получить path и сразу преобразовать его в строку, а потом делать поиск подстроки.

Но в моём ядре этих хуков не было, хуй знает почему, видимо дистрибутив слишком древний. Надо попробовать на новых, чем черт не шутит.

Итоги

Эта поделка как и предполагалась, погрузила меня в печаль, душевные страдания, НО стала отличным тренажером для прокачки:

- Внутренностей Linux ядра
- Работы с eBPF
- И кучу другого с kernel-space

eBPF — мощнейший инструмент, но очень тонкий. Ошибёшься — будешь выебан в жопу.


Информации по нему много, но вся она разбросана. Собрать всё это в кучу было отдельным квестом.

Мораль?

Иногда самое простое решение — это chown -R. Но куда интереснее — написать свой велосипед и заглянуть в кроличью нору Linux ядра.

🛠 #linux #debug #dev

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
947
Настройка core dump в Docker

Цель этого поста — дать тебе общее руководство по включению и сбору core dumps для приложений, работающих в docker контейнере.

Настраиваем хост для сохранения дампов

Для начала надо сконфигурировать хостовую машину, чтобы сохранять такие дампы в нужное место. Нет, не в жопу.

Универсальный способ — задать шаблон core pattern. Шаблон определяет путь и информацию о процессе который наебнулся.

echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern


Кратенько:

%e — имя процесса
%p — pid процесса

Более подробно о конфигурации core pattern можешь почитать в man-странице ядра Linux.


Как вариант, можно настроить host изнутри контейнера через CMD или ENTRYPOINT. Но контейнер в этом случае должен запускаться в privileged mode, что хуева с точки зрения безопасности.

Пример хуёвого приложения

#include <cstdlib>
void foo() {
std::abort();
}

int main() {
foo();
return 0;
}


После компиляции и запуска, приложение наебнется с ошибкой.

Пишем Dockerfile для этого приложения

FROM ubuntu:22.04

# Install tools
RUN apt update \
&& apt -y install \
build-essential \
gdb \
&& rm -rf /var/lib/apt/lists/*

# Build the application
COPY ./ /src/
WORKDIR /src/
RUN g++ main.cpp -o app

CMD ["/src/app"]


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


Запускаем контейнер с нужными опциями:

docker run \
--init \
--ulimit core=-1 \
--mount type=bind,source=/tmp/,target=/tmp/ \
application:latest


Разбираем опции:

--init — гарантирует корректную обработку сигналов внутри контейнера

--ulimit — устанавливает неограниченный размер core dump для процессов внутри контейнера

--mount — монтирует /tmp из хоста в контейнер, чтобы дампы, создаваемые внутри контейнера, были доступны после его остановки или удаления

Здесь важно: путь source на хосте должен совпадать с тем, который задан в шаблоне core pattern.

После того как приложение наебнется, core dump будет сохранён на хостовой машине в директории /tmp.

ls /tmp/core*
# /tmp/core.app.5


Анализируем дамп с помощью gdb

Такс, мы получили core dump и он у нас лежит на хостовой машине, но рекомендуется открыть его внутри контейнера. Контейнер должен быть из того же образа, в котором компилилось приложение.

Это поможет убедиться, что все зависимости (библиотеки и прочая хуитень) доступны.

docker run \
-it \
--mount type=bind,source=/tmp/,target=/tmp/ \
application:latest \
bash


Если в образе нет исходного кода, можно допом смаунтить исходники:

docker run \
-it \
--mount type=bind,source=/tmp/,target=/tmp/ \
--mount type=bind,source=<путь_к_исходникам_на_хосте>,target=/src/ \
application:latest \
bash


Теперь внутри контейнера запускаем:

gdb app /tmp/core.app.5


После загрузки дампа можно выполнить команду bt (backtrace), чтобы увидеть трассировку стека:

(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007f263f378921 in __GI_abort () at abort.c:79
#2 0x000055f9a9d16653 in foo() ()
#3 0x000055f9a9d1665c in main ()


Команда поможет определить, где именно произошел факап.

Давай быстренько разберем ошибку.

#0 и #1 показывают, что процесс получил сигнал 6 (SIGABRT) и завершился через abort()

#2 — вызов произошёл внутри функции foo()

#3main() вызвал foo()

В исходнике было:

void foo() {
std::abort();
}


То есть ошибка здесь не баг компиляции или рантайма, а намеренно вставленный вызов std::abort(), который и приводит к аварийному завершению и генерации core dump.

Если у тебя docker-compose, то все флаги (--init, --ulimit, --mount и т.д.) применимы и для него. То есть отладку можно легко адаптировать.

Хуй знает чё еще написать, завтра тему дебага продолжим, чет в конце года много траблшутинга навалило разнообразного.

🛠 #linux #debug #dev

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
545
Сегодня коллега, который проводит дохрена технический собесов поделился инсайдом. Мол кандидаты из Южной Америки часто называют временные переменные aux, а вот кандидаты из Восточной Европы - temp. Такая вот этнография.

Прикольно. Для меня aux это дырка в которую можно что-то вставить.

А в чем дело-то?

Причины могут быть в языке и в традициях обучения.

Южная Америка и «aux»

Во многих странах Латинской Америки (а также в Испании и Португалии) обучение программированию ведётся на родном языке.

Слово auxiliar (испанское) или auxiliar/auxiliaridade (португальское) переводится как «вспомогательный».

Поэтому сокращение aux — это естественный выбор для временной переменной. Многие учебники и преподаватели прямо используют aux в примерах.

Восточная Европа и «temp»

В странах Восточной Европы (Россия, Польша и др.) учебные материалы часто брались с английских источников или напрямую переводились, но при этом терминология частично сохранялась.

В англоязычных книгах традиционное имя временной переменной — temp (от temporary). В итоге это закрепилось как привычка.

Ещё один фактор — русскоязычные (и в целом восточноевропейские) программисты исторически чаще учились по книгам на английском, чем по локализованным методичкам. Хотя и методичек особо таких и не было.

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

Такие мелочи могут «маркировать» культурный бэкграунд разработчика не хуже акцента в речи.


Давай разберем другие страны

Китай

- В учебниках и коде часто встречается tmp (это короче чем temp).
- arr почти всегда вместо array.
- Булевые переменные часто называются flag.
- Комментарии «中英混合» — смесь китайских и английских терминов:

// 计算 sum
total = total + arr[i];


- В олимпиадном коде часто встречается ans и vis (visited).

Западная Европа / США

- Стандартные учебные названия: temp, foo, bar, baz.
- В учебниках на джава и питоне для временных значений часто используют value или val.
- В научном и численном коде — переменные x, y, z, dx, dy (от физики и математики).

Ну тут классика, аналогично Мистер и Миссис Стоговы из учебников по инглишу.

Восточная Европа / Россия

- temp как временная переменная (от англ. temporary).
- buf вместо buffer (сильно закрепилось ещё с ассемблеров и C-шных примеров).
- cnt для счётчиков (counter) — иногда даже вместо i/j/k.

Переменные res (result) и ans (answer) очень популярны в олимпиадном программировании.

Комментарии часто начинаются с // !!! или // FIXME: на смеси русского и английского.

Ближний Восток

- В арабоязычных странах иногда встречается mosa3ed (مساعد = помощник), но чаще используют англоязычные temp/aux.
- Комментарии миксуют латиницу и арабицу, например:

// calculate المجموع
// check if الشرط
// temp متغير


Индия

- temp тоже стандарт, но часто встречается flag для булевых переменных (очень широко).
- В комментариях любят писать // logic или // main logic, даже если код очевиден.

Названия переменных иногда из «хинди-английского микса» в учебных проектах: num1, chotu (маленький), bada (большой).

В целом получаем:


- Испаноязычные/португалоязычные — aux.
- Восточная Европа — temp/buf/cnt/res.
- Англоязычные — temp/foo/bar.
- Китай/Индия — tmp/flag/arr/ans.

Короче вся это тема — маленькие «акценты» кода. Про 1Сников писать уж не буду, сами все знаете как они переменные называют.

Не смею больше отвлекать, хороших тебе выходных!

🛠 #рабочиебудни #dev

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
875
Привет друзья, Масим Братковский запилил для нас техническую статейку.

Сюда по классике не влезло, опубликовал в блоге. Идем читать.

Что делать если postman достал, а надо тестировать SOAP API.

Комментарий автора: Если вам интересно, давайте обратную связь, буду рад продолжить серию статей.

🛠 #dev #qa

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
16