Bash Days | Linux | DevOps
Авторский блог от действующего девопса Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу. Автор: Роман Шубин Реклама: @maxgrue MAX: https://max.ru/bashdays Курс: @tormozilla_bot Блог: https://bashdays.ru
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Bash Days | Linux | DevOps
تُعد قناة Bash Days | Linux | DevOps (@bashdays) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 23 791 مشتركاً، محتلاً المرتبة 5 701 في فئة التكنولوجيات والتطبيقات والمرتبة 28 125 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 23 791 مشتركاً.
بحسب آخر البيانات بتاريخ 18 يونيو, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -216، وفي آخر 24 ساعة بمقدار -5، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 22.75%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 12.90% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 5 413 مشاهدة. وخلال اليوم الأول يجمع عادةً 3 068 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 21.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل bashdays, linux, bash, docker, скрипт.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Авторский блог от действующего девопса
Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.
Автор: Роман Шубин
Реклама: @maxgrue
MAX: https://max.ru/bashdays
Курс: @tormozilla_bot
Блог: https://bashdays.r...”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 19 يونيو, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
echo Shs | base64 -d
Jase64: invalid input
И наблюдаем аномалию в названии утилиты: Jase64.
Из команды понятно, что утилита base64 при декодировании обнаружила ошибку в данных. Ошибка — не корректная длина закодированного текста (invalid input).
Но чо за херня с Jase64? Новая попа-группа Юры Шильникова-Томатного? Должно же быть Base64?
Если что-то пошло попесде, нам поможет «страус». Расчехляем strace.Давай посмотрим что и куда пишет base64. Перенаправляем стандартные потоки вывода и ошибки в устройство
/dev/null. Дополнительно говорим «страусу», чтобы выводил системные вызовы write.
Запускаем кишку:
с запущенной кишкой, обычно к практологу
LC_ALL=C strace -Yqqqyfe write -P /dev/null --signal=none bash -c 'echo Shs | base64 -d &>/dev/null'
Кратенько по ключам:
LC_ALL = страхуемся
Y = чекаем вызовы ввода-вывода
qqq = меньше мусора
y = показываем пути к файлам
f = чекаем дочерние процессы
e = выбираем вызовы write
P = ограничение трассировки
signals = не следим за сигналами
После запуска получаем:
[<base64>] write(1</dev/null>, "J\33", 2) = 2
[<base64>] write(2</dev/null>, "base64: ", 8) = 8
[<base64>] write(2</dev/null>, "invalid input", 13) = 13
[<base64>] write(2</dev/null>, "\n", 1) = 1
Уже поинтереснее. Разбираем.
- В первой строке происходит запись части декодированного текста в стандартный вывод (дескриптор 1).
- В следующих двух строках, в стандартный поток ошибок пишется имя утилиты и ошибка (дескриптор 2).
- Ну и последняя строка, запись новой строки.
Теперь снова смотрим первую строку и видим что системный вызов write пишет букву «J» и какой-то магический символ 33.
✔️ «Страус» по умолчанию выводит числовые значения непечатных символов в восьмеричной системе счисления. То есть 033 будет соответствовать символу ESC в кодировке ASCII.
И чо? А то, что для драйвера терминала, этот символ означает начало управляемой последовательности. Вот это поворот!
Скучная теория
Драйвер терминала это код, который распознает управляющие последовательности и интерпретирует их в действия. Например, перемещает курсор.
В моем случае, драйвер это эмулятор терминала (Terminal). А еще есть код в пространстве ядра, который реализует специальные устройства. И этот код может модифицировать данные проходящие через эту линию связи.
Схема терминала:
Bash write stdout -> /dev/pts/number Kernel_Space <- /dev/ptmx Terminal read
Terminal write -> /dev/ptmx Kernel_Space <- /dev/pts/number Bash read
Bash read это чтение команды, или сочетания клавиш например для редактирования строки.
Возвращаемся к Jase64
Для начала исключаем пространство ядра (Kernel_Space) и проводим проверку данных, которые поступили на устройство читаемое эмулятором терминала.
Видим что на устройстве эмулятора Terminal, данные пришли без искажений. Подозреваемым остается драйвер терминала.
write(30</dev/ptmx>, "\33[200~echo Shs | base64 -d \33[201"..., 33) = 33
Как это 👆 получить, я рассказал утром в этом посте.И происходит следующее. Эмулятор терминала получив символ «J» отображает его, но потом натыкается на специальный символ ESC начало управляющей последовательности и слово base64. Символ «b» распознаётся как часть управляющей последовательности и этот символ не отображается. Многие терминалы не имеют никаких действий связанных с данной последовательностью «ESCb» и она просто отбрасывается. Ниже пару примеров, когда часть последующего ввода распознаётся как завершение управляющей последовательности.
echo -ne 'J\033' ; sleep 3 ; echo base64 >&2
echo -ne 'J\033[64' ; sleep 3 ; echo bashdays >&2
Вот такие вот приколы, вот такие вот кишочки. Нельзя просто так взять и насыпать в терминал всё что тебе захочется.
Если после каких-то действий, ты начал замечать аномалии, выполни команду reset и всё встанет на свои места.
Хорошая статья: The TTY demystified.
И да, всем отличных предстоящих выходных, берегите себя ❤️
Не забываем подписываться на пиздатые тулзы.tags: #linux #bash #debug — 🔔 @bashdays
readlink /proc/self/fd/0
Получаем нечто подобное: /dev/pts/0
Открываем второй терминал и запускаем от рута, получаем нужные пиды:
pgrep -xo konsole
pgrep -xo bash
24385
24401
Вместо konsole и bash можешь указать свой терминал и оболочку.
Подставляем пиды в команду и опять запускаем от рута:
strace -Yytttf -p 24385 -p 24401 -o bashdays.log
Возвращаемся в первый терминал, где запускали readlink и что-нибудь начинаем вводить, команды там, текст.
После того как наигрался, возвращайся во второй терминал с strace стопай и открывай на изучение лог bashdays.log.
В нем ты найдешь много интересного, если все сделал правильно — придёт озарение.
Штука низкоуровневая, но даёт базовое понимание как устроен эмулятор терминала.
Сегодня в 20:13 МСК залетит связанный с этой темой пост. Будут кишочки, strace и дебаг аномалии. Забегай.
Хорошего тебе дня, изучай!
tags: #linux #debug
—
🔔 @bashdays/etc/docker/daemon.json
{"registry-mirrors": ["https://mirror.gcr.io", "https://daocloud.io", "https://c.163.com/", "https://registry.docker-cn.com"]
}
#docker #proxyarr=('huy' 'pizdec')
echo "${arr[@]}"
echo "${arr[0]}"
echo "${arr[1]}"
Всё здесь правильно, прям как в книжках! Прочитал и понял, что выведется на экран.
Кто не знает, символ «собакена» выведет все элементы массива.✔️ А вот массив курильщика:
arr=('huy' 'pizdec')
echo "${arr[6%2]}"
Что думаешь эта херабора выплюнет? А тут «брат»... И выплюнет оно первое слово huy. Но почему?
Потому что гладиолус. Логично делим 6 на 2, получаем 3. Но у нас нет третьего элемента в массиве. WTF!!??
А мы тут как бы не делим! Не путай деление с «%».
Символ «%» означает — взять остаток от деления.После деления 6 на 2 у нас получился остаток 0. То есть это как бы нулевой индекс массива, получаем huy. Соответственно если сделать 7%2, то выведется слово - pizdec. Потому что после деления получился остаток 1. Ну а чтобы получить 3 элемент массива, надо подобрать циферки. Ну например 5%3, получим остаток 2. И так далее. Ну ты понял. Вот я вся математика. Хочешь запутать свои Bash скрипты и порадовать коллег? Нативная обфускация. Дерзай! tags: #bash — 🔔 @bashdays
У меня была история в начале карьеры, когда я бездумно удалил файлы на сервере и корпоративная 1С приказала долго жить. Удалил по причине — чистил место. Бэкапов естественно я не сделал. Лошара чо, так я получил новое достижение — седой волос на жопе.Сосо́чки это разделяемые библиотеки, то бишь shared libraries. Короче если ты немного программист, то знаешь, что эти библиотеки содержат набор неких функций. Допустим написал ты свой бинарник, а все функции для бинарника вынес в отдельный файл
bashdays.so. Теперь бинарник будет ходить в этот «сосочек» и читать от туда нужные ему функции.
Ранее я писал пост, как создавать свои «сосо́чки» и обращаться к ним из Bash скриптов.А зачем так усложнять? Всё просто, ты выносишь протестированные функции в отдельный файл. А потом можешь их использовать совершенно из другого бинарника. Грубо говоря, у тебя есть 10 софтин и один «сосо́чек». Все эти 10 софтин ходят в сосочек и забирают нужное. Оптимизация? Еще какая! Ну дак вот. К «сосо́чкам» применяется версионность. То есть у тебя может быть несколько таких библиотек с разными функциями:
libbashdays.so.1.0.0
libbashdays.so.1.1.0
libbashdays.so.1.1.1
Версионность нужна для совместимости. Она позволяет сохранить работоспособность программ при обновлениях.
Ну ты понял. Условный apache использует libbashdays.so.1.0.0, а условный nginx который был обновлен уже хочет версию 1.1.1. Чтобы не сломать apache, нужно иметь 2 версии «сосо́чка».
✔️ Разделяемая библиотека должна состоять из трёх имен:
- Имя библиотеки
- Метка soname
- Компоновочное имя
Имя библиотеки, в формате lib<name>.so.<major>.<minor>.<patch>
Major - правки приводят к несовместимости
Minor - добавлении функционала
Patch - багфиксы, оптимизации
Метка «Shared Object Name» или soname. Представляет идентификатор, который позволяет системе динамической загрузки (dynamic linker) определить, какая версия библиотеки должна быть загружена для выполнения программ.
Если софтина скомпилирована с использованием libbashdays.so.1.0.0, она будет искать libbashdays.so с soname 1 при запуске.
Это значит, что она может работать как с libbashdays.so.1.0.0, так и с libbashdays.so.1.1.0, поскольку у них одинаковый soname. Однако, она не будет работать с libbashdays.so.2.0.0, так как у этой версии другой soname.
Создаем libbashdays.so.1.0.0 с меткой libbashdays.so.1
gcc -shared -Wl,-soname=libbashdays.so.1 -o libbashdays.so.1.0.0 module.o
Компоновочное имя — связывает приложение и библиотеку.
gcc -g -Wall -o bashdays main.o libbashdays.so
В исполняемый файл bashdays будет записан soname, с привязкой к libbashdays.so.
Чтобы корректно подключать зависимости, создаётся пару символических ссылок.
libbashdays.so -> libbashdays.so.1 libbashdays.so.1 -> libbashdays.1.0.0 libbashdays.1.0.0Старайся чтобы компоновочное имя ссылалось на метку soname. На случай если пользователь-дебил удалит старую версию минорного обновления. И симлинка поломается. Так. После всех этих танцев с бубном, ссылка на soname должна указывать на самую последнюю её версию. Тогда приложение будет работать с самой актуальной версией библиотеки.
libbashdays.so.1 -> libbashdays.so.1.0.1
Ну и при обновлениях «Мажорных» версий, используя утилиту ldconfig, автоматически будет создана ссылка, которая свяжет имя библиотеки и метку soname. Приложение будет работать с последней совместимой версии.
ldconfig -v | grep libbashdays libbashdays.so.2 -> libbashdays.so.2.0.0 (changed) $ ldd bashdays libbashdays.so.1 => ./libbashdays.so.1 (0x0000ffff6f680000) libc.so.6 => /lib/libc.so.6 (0x0000ffff7ff50000)Пиздец муть? Аще! Если ты далёк от этих «сосо́чков», не забивай себе голову. Для общего развития пойдет, теперь ты знаешь как это говнище устроенно. Изучай. Увидимся! tags: #linux — 🔔 @bashdays
kexec -l /boot/vmlinuz-new-kernel --initrd=/boot/initrd-new-kernel --command-line="root=/dev/sda1" kexec -e
Дальше существует Live Patching. Эта технология позволяет применять обновления ядра без перезагрузки.
- kpatch от Red Hat
- kGraft от SUSE
- Kernel Live Patching (KLP) с версии ядра 4.0
Live Patching позволяет вносить изменения в ядро, такие как исправления безопасности, без необходимости перезагрузки. Однако, это не подходит для всех видов обновлений ядра, таких как смена версии или значительные изменения в функциональности.
Ну и KernelCare. Это коммерческое решение, которое предоставляет возможность обновлять ядро Linux без перезагрузки. Оно поддерживает различные дистрибутивы Linux и позволяет администраторам систем применять критические обновления безопасности на лету.
Таким образом, полностью избежать перезагрузки при обновлении ядра невозможно в случае, если требуется полная смена версии ядра.
Однако, для большинства критических обновлений безопасности можно использовать технологии Live Patching, что позволяет поддерживать высокую доступность системы.
Такие дела.
tags: #linux
—
🔔 @bashdaysТак же ты можешь принять участие, скинув свою полезняшку в бота «Онотоле».Рекомендую подписаться ➡️ @gitgate
sudo apt install build-essential
В 99% случаев ты бездумно ставишь этот пакет, раз написано, значит нужно. Но всяко не задумывался, а чо блядь это такое?
И правда, а что это такое?
build-essential это «метапакет», который устанавливает набор необходимых инструментов. Эти инструменты требуются для компиляции исходников.
✔️ В состав build-essential обычно входят:
gcc — основной компилятор для языков C и C++.
g++ — компилятор для языка C++.
make — утилита для автоматизации сборки программ.
libc6-dev — заголовочные файлы и библиотеки C стандартной библиотеки.
dpkg-dev — утилиты для работы с исходными пакетами Debian.
ну и другие…
Грубо говоря, build-essential это швейцарский нож, всё в одном.
Ну и чо?
Да ничо, либо ты руками будешь ставить 10 софтин для компиляции своих поделок, либо один раз установишь build-essential и у тебя под рукой уже есть все самое необходимое.
Короче build-essential создан для твоего удобства. Этакий билдер старт-пак. Но никак не отдельная утилита/программа.
Нужно всегда помнить, что это не серебреная пуля для установки рабочих окружений Golang, Python и т.п. Иногда придется все же что-то дополнительно поставить ручками.
Скучный высер из доков:
Мета-пакет - это удобный способ массовой установки групп приложений, их библиотек и документации. Многие дистрибутивы Linux используют их для различных целей, от создания образов дисков, которые впоследствии станут новыми выпусками, до создания программных «пакетов», которые пользователь может легко установить. Мета-пакет редко содержит что-либо, кроме журнала изменений и, возможно, информации об авторских правах, он не содержит внутри себя приложений или библиотек. Способ их работы заключается в наличии списка «зависимостей», который считывает менеджер пакетов. Затем менеджер пакетов обращается к репозиториям, находит зависимости и устанавливает их.Поздравляю, теперь ты и это знаешь! tags: #linux — 🔔 @bashdays
redirall.shДа, я знаю про алиасы и ssh_config. Скрипт предназначен для ИНТЕРАКТИВНОГО проброса TCP-портов через jump-серверы, средствами ssh. Позволяет пробрасывать порт с удаленной машины на 127.0.0.1 и коннектиться к службам компов, доступных из подсети jump-сервера (в скрипте gate сервер) за firewall. При небольшой модификации можно открывать порт для компов своей локальной подсети. Удобен для сопровождения небольших фирм. Кому это не интересно, рассматривайте скрипт, как учебный, потому как тут есть некоторые фишки, которые поясню ниже. В инете есть машина IP=1xx.2xx.2xx.54, у которой на порту 13527 висит ssh. После подключения у нас на машине по адресу 127.0.0.1:8080 будет висеть служба 192.168.1.10:443 из локальной сети шлюзовой машины. Кстати, dest_ip, dest_port, lo_port - значения по-умолчанию. При подключении их можно менять, не трогая конфиг. Если кто заинтересовался пробросом портов через ssh рекомендую смотреть ключи -L -R -D. ✔️ Теперь к скрипту. MULTICOLUMN=0 - список подключений в один столбец. Подходит, когда список до 20-30 строк. MULTICOLUMN=1 список в несколько столбцов. Некрасиво, но много... function ini() - список параметров, для тех, кто хранит данные в скрипте (можно еще heredoc).
Для тех, кто обожает конфиги - просто вставьте cat file.conf внутрь функции ini.awk !/^#/ && NF - выводит строки, НЕ начинающиеся с #, и с числом полей >0. (не пустые, без комментов) |eval $CMD - ПОЗВОЛЯЕТ МЕНЯТЬ ЛОГИКУ цепочки PIPE |cat - заглушка (nop в мире pipe) Дальше все просто. read -i позволяет указать значение по-умолчанию, которое, можно изменить. Скрипт можно приспособить для любого интерактива: выбор версии скачиваемой программы, монтирование/размонтирование FS, выполнение нужных, но редких скриптов, которые, блин, постоянно забываешь...
Советы приветствуются. Конфиг можно загружать и из сети, но перед объявлением ini.
#!/bin/bash
declare -i MULTICOLUMN=0
function ini(){ echo '
#name ssh_gate_ip gate_port ssh_user dest_ip dest_port lo_port
Filial1 1xx.2xx.2xx.54 13527 u232sr 192.168.1.10 80 8080
Filial2 9y.1yy.1yy.66 13531 u232sr 192.168.1.18 5432 5432
Firma2 1zz.2zz.2zz.53 22 p183975 192.168.1.100 3389 3388
'
}
declare -i COLS=$(echo "cols"|tput -S)
declare -i NUM=0
clear
[[ $MULTICOLUMN -eq 0 ]] && CMD='cat' || CMD='column -x -c$COLS'
#autonum & print list
ini |awk '!/^#/ && NF {print ++i, $1 }' |eval $CMD
#protection
declare -i MAX=$(ini |awk '!/^#/ && NF {++i}END{print i}')
while [[ $NUM -le 0 ]] || [[ $NUM -gt $MAX ]];do
read -p "select connection number = " NUM
done
#get default param for selected num
read -r NAME GATE_IP GATE_PORT USR DEST_IP DEST_PORT LO_PORT <<< \
$(ini | awk -v n="$NUM" '!/^#/ && NF {if(++i==n){print $0;exit}}') #'
clear
echo -e \\n"Connect to $NAME $GATE_IP"\\n
#modify param
read -e -p "DESTINATION_IP " -i "$DEST_IP" DEST_IP;echo
read -e -p "DESTINATION_PORT " -i "$DEST_PORT" DEST_PORT;echo
read -e -p "LOCAL PORT >1024 " -i "$LO_PORT" LO_PORT
#prompt
echo -e "127.0.0.1:$LO_PORT ~> $NAME" "$DEST_IP:$DEST_PORT"\\n\\n
#connect
ssh -L ${LO_PORT}:${DEST_IP}:${DEST_PORT} -p ${GATE_PORT} ${USR}@${GATE_IP}
tags: #bash
—
🔔 @bashdays
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
