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 622 مشتركاً، محتلاً المرتبة 5 603 في فئة التكنولوجيات والتطبيقات والمرتبة 27 700 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 23 622 مشتركاً.
بحسب آخر البيانات بتاريخ 02 نوفمبر, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -18، وفي آخر 24 ساعة بمقدار 2، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 19.83%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 10.78% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 4 683 مشاهدة. وخلال اليوم الأول يجمع عادةً 2 547 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 12.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل bashdays, linux, bash, docker, скрипт.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Авторский блог от действующего девопса
Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.
Автор: Роман Шубин
Реклама: @maxgrue
MAX: https://max.ru/bashdays
Курс: @tormozilla_bot
Блог: https://bashdays.r...”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 03 نوفمبر, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576Нет, не от злых черно-шляпных, смысла в этом мало, блокировка тут не решает. Собаку съели.Дело было так. Лет 10 назад я открыл
putty, подключился к проду и пошел навалить себе кофеёв с печенькой. Навалил. Вернулся. На клавиатуре мило устроился кот.
Кота тревожить не стал, уважительная причина не ходить на работу. Взял ноут и получил в аську 100500 алертов в nagios.
Да, в те времена в тренде были nagios и заббиск. Но заббикс всем казался пиздец сложным, поэтому халявили и втыкали нагиос.
Ну дак вот. Суть.
Когда кот устраивался, он первой лапой нажал на стрелочку вверх, потом еще раз нажал пузаном и на фаталити ёбнул яйцами по Enter.
Ему то чё, он хуй за мясо не считает.А в хистори с профилактических выходных оставалась команда
shutdown -h now, до которой добрался кот и успешно её исполнил.
В те времена мелкий бизнес особо за аптайм не переживал и ретроспективы только зарождались, в жопы не ебали.Но опыт был получен.
Звучит как сказка, но такие сказки со мной постоянно приключаются, коллеги соврать не дадут.Вот после этого, я всегда жму
WIN + L или CMD + Q.
Даже если кот и сын спят, все равно прожимаю эту комбинацию.
Но опять же если открыта консолька с продом, то заранее её еще и сворачиваю, впизду.
Видимо детская травма.
А ты прожимаешь WIN + L / CMD + Q если отходишь от своей рабочей лошадки?
Камон в комменты делиться своими факапами.
tags: #рабочиебудни
—
🔔 @bashdays➡️ @gitgateif [ false ]; then echo "HELP"; fi
Большинство думает, что [ — это часть команды if как скобки в других языках программирования. Но нихуя!
ㅤ
В Bash if просто запускает команду. Команда [ ... ] — это обычный бинарник, аналогично команде test, а не специальный синтаксис.
Скобка ] нужна только для красоты и завершения команды [.
Команда выше напечатает HELP, потому что строка "false" — непустая, а значит, условие считается истинным.
Теперь о главном
Если хочешь использовать grep в if, не надо писать скобки!
Плохая практика:
if [ grep -q "foo" myfile ]; then
echo "Найдено!"
fi
[... ] — ожидает условие, а не команду
grep — это команда, а не логическое выражение
Внутри [ запускать команды нельзя — это приведёт к ошибке
Хорошая практика:
if grep -q "foo" myfile; then
echo "Найдено!"
fi
if просто запускает grep
Если grep нашёл совпадение, он вернёт 0 (успех), и выполнится then
И Всё работает как надо, без лишних скобок!
[ — это как калькулятор, а grep — это поиск. В калькуляторе искать бесполезно!
Выводы
Никогда не пиши if [ grep ... ] — это ошибка!
Пиши просто if grep ..., чтобы проверить результат команды.
if работает с командами. [ — это тоже команда, но не синтаксис.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgateРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576grep foo bar.txt | while read -r; do ((count++)); done
Он считает, сколько строк в файле bar.txt содержат слово foo.
Здесь главная проблема — переменная count не изменится вне цикла while, потому что в Bash каждая команда в пайплайне (|) запускается в отдельной оболочке (subshell). То есть count++ происходит «внутри», и снаружи этого не видно.
Если простым языком: Каждая часть, разделённая |, запускается в отдельной «коробке» (subshell). То есть while работает внутри своей коробки. B всё что там происходит, не видно снаружи.
Некоторые оболочки ksh93 или Bash с включённой настройкой shopt -s lastpipe работают по-другому — цикл выполняется в той же оболочке, и тогда count изменится.
count=0
echo -e "one\ntwo\nthree" | while read line; do ((count++)); done
echo $count
Этот код вернет 0, несмотря на count++, а вот например в zsh вернется 3.
Как быть?
Первый вариант:
shopt -s lastpipe
Эта штука говорит интерпретатору — что последний элемент конвейера будет выполнен в окружении текущей оболочки.
Второй вариант:
Вообще избавиться от while и всё сделать через grep:
count=$(grep -c foo bar)
echo $count
Можно еще наколхозить и передавать значения через временный файл, но это прям пиздец шляпа и костыль.
Выводы
Нужно просто посчитать строки:
count=$(grep -c foo bar)
Нужно обрабатывать строки:
while read line; do ...; done < bar
Хочешь использовать pipe:
shopt -s lastpipe
Вот и вся наука.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgate[[ $foo > 7 ]], то далеко не факт что это правильно отработает.
ㅤ
Двойные скобки [[ ... ]] в Bash предназначен для проверки условий, но не для работы с числами. Для чисел лучше хуячить (( ... )).
➡️ Бест-практика
(( foo > 7 ))
А если хочется прям строго соответствовать POSIX, делай так:
[ "$foo" -gt 7 ]
Теперь давай разберемся почему с [[ $foo > 7 ]] словишь ошибку.
Символ > в [[ ... ]] сравнивает строки, а не числа. Например, "10" < "7", потому что 1 идёт раньше 7 в алфавите.
В [...] символ > вообще означает «перенаправление вывода», и создаст файл с именем 7 в текущей папке.
Еще пример:
case $foo in
("" | *[!0123456789]*) echo "Ошибка: foo не число!" && exit 1 ;;
*) [ "$foo" -gt 7 ] ;;
esac
Если $foo содержит что-то вроде $(rm -rf /), то при определённых условиях это может привести к пиздецу. Поэтому перед проверкой лучше убедиться, что $foo — это число.
Код выше проверяет, является ли переменная $foo числом, и если да, сравнивает её с 7.
case $foo in — конструкция для проверки значений переменной $foo по шаблонам. "" — пустая строка (если $foo пустое). ("" | *[!0123456789]*) — строка, содержащая хотя бы один символ, который не цифра (например, abc, 12a3). Если условие выполняется, выводится сообщение "Ошибка: foo не число!", и скрипт завершает работу с кодом 1 (exit 1). * — означает «всё остальное» (то есть, если $foo не попал под первый шаблон). [ "$foo" -gt 7 ] — проверяет, больше ли $foo чем 7.Выводы: для работы с числами используем
(( ... )) или [ "$foo" -gt 7 ], а переменные перед проверкой лучше очищать от лишних символов.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgate[ "хуи" = "коробка1" -a "пики" = "коробка2" ]
Тут -a (И) считается устаревшим и в некоторых случаях это работать не будет. Так что если такое видишь или пишешь, сразу сноси, это хуйня!
Одна из проблем с [ A = B -a C = D ] (или -o) в том, что POSIX не определяет, как должна работать команда [ ... ], если у неё больше 4 аргументов.Бест-практика: Разделяем на две проверки:
[ "коробка1" = "хуи" ] && [ "коробка2" = "пики" ]
Сначала проверяется первое условие, затем второе.
Если оба верны — команда выполнится.
Либо делаем конкретно под Bash:
[[ "коробка1" = "хуи" && "коробка2" = "пики" ]]
Здесь можно использовать &&, всё будет работать правильно.
Выводы:
Если используешь [ ... ], то делай две отдельные проверки.
Если [[ ... ]], то можно писать всё внутри.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgatef="My Documents/file.txt"
И в скрипте мы делаем так:
cd $(dirname "$f")
Это ошибочный вариант, бэд мать его практика.
Команда cd $(dirname "$f") должна вернуть путь к папке, где лежит файл.
ㅤ
НО! Результат этой команды разбивается на части, если в нём есть пробелы.
Например:
dirname "My Documents/file.txt"
Выдаст: My Documents
А если так:
cd My Documents
Логично, получаем ошибку:
cd: No such file or directory: My
Bash думает что это два отдельных слова, а не один путь.
➡️ Бест-практика
cd -P -- "$(dirname -- "$f")"
1. Кавычки защищают результат команды от разбиения.
2. И cd получит целый путь, даже если в нём есть пробелы.
Как работают кавычки
- Когда Bash видит $(...), он воспринимает это как отдельную область, некий «уровень».
- Кавычки внутри $(...) работают только внутри.
- Кавычки снаружи не объединяются с внутренними.
Наглядно, можно представить так:
cd "$( dirname "$f" )"
Внутренние кавычки "$f" защищают переменную f
Внешние кавычки "" защищают результат dirname "$f"
Теперь даже если переменная будет содержать пробелы команда не разобьётся на части.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgate[ $foo = "bar" ]
В этом примере если переменная $foo будет пустой, то по итогу ты попадешь в просак:
[ = "bar" ]
bash: [: =: unary operator expected
Логично вылезет ошибка, потому что «=» ожидает два значения. Чтобы избежать этой ситуации, на помощь приходят — кавычки.
[ "$foo" = "bar" ]
Теперь всё в поряде. Ошибки никакой нет.
Но Bash не пальцем деланный, поэтом сравнить две переменные можно иначе.
[[ $foo == bar ]]
Теперь кавычки нахуй не нужны. Но опять же если в переменной будут спецсимволы, то тебя ожидают грабли.
Есть еще легаси способ:
[ x"$foo" = x"bar" ]
В современном мире ты вряд ли с ним столкнешься, но в каких-то допотопных скриптах вполне можешь найти.
Если $foo пустая, то без x получится:
[ = bar ]
А с x будет:
[ x = xbar ]
В [[ ... ]] переменные не разделяются на слова, даже если содержат пробелы.
foo="hello bashdays"
[[ $foo = "hello bashdays" ]]
А если сделать так:
foo="hello bashdays"
[ $foo = "hello bashdays" ]
Получишь ошибку: bash: [: too many arguments
Все это справедливо для Bash. Если пишешь под sh, то твой путь это одинарные скобки [...].
ㅤ
А еще в двойных скобках можно использовать шаблоны:
foo="hello bashdays"
[[ $foo == h* ]]
Вернёт true, потому что foo начинается с «h».
Либо написать сложное условие:
[[ $foo = "bar" || $bar = "baz" ]]
В одинарных кавычках это выглядело бы так:
[ "$foo" = "bar" -o "$bar" = "baz" ]
Выводы:
Всё что тебе нужно знать это первые два способа:
[ "$foo" = "bar" ]
[[ $foo == bar ]]
Это трувей, бестпрактика и мастхев.
Изучай.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgateАлёша, ты чё блядь Супер Марио? Об грибок уебался?Что делать с упавшим продом? Естественно чинить самому! В этой ситуации ты можешь положиться только на себя. Ты тот самый Брюс Уиллис, который полетел в космос и выебал астероид. Тут уже никто не спрашивает — можешь ты это починить или нет. Ты обязан с этим разобраться и починить. А как? Вообще никого не ебет — предоставьте результат. Из помощников только гугол, твоя насмотренность и опыт. Больше положиться не на кого, ты гуглиш, экспериментируешь, по итогу чинишь всё это дерьмище и чилиш. Ну и надеешься чтобы на ретро тебя в жопу не выебали. Ситуация вторая Ты не единственный специалист в своей роле. Аналогично, ты что-то запушил в мастер и все уебалось. Что ты делаешь? Пытаешься починить, не выходит, еще раз пытаешься, гуглишь, используешь нейросети, становится только хуже… Следующий твой шаг — делегируешь свой факап своему коллеге (коллегам, тегаешь всех
@channel), у них опыта больше, наверное посоветуют, разберутся.
Это сразу провальный вариант!
➡️ Если что-то сломал — чини сам! Это аксиома!
Но опять же если это прод, не грех посоветоваться с коллегами, если такие есть. Всеобщими усилиями это поднять, а потом уже жопу свою на ретро отдать на экзекюцию, но не забыть заранее выписать бочку вазелина с Озона.
Короче вывод такой — никогда ни на кого не надейся!
Сразу в башке носи мысль — ты один и разбираться с этим тебе одному.
Такой подход неистово качает твой скиллз и ты никогда не будешь зависеть ни от кого. И это очень ценный навык в айти, кем бы ты ни был.
Как только ты станешь самостоятельным, тебе будет похер вообще на всё и на всех, ты будешь Альфа-Ктулху, который решит любую проблему!
Такие дела, нового ничего не сказал, рабочие будни.
tags: #рабочиебудни
—
🔔 @bashdays➡️ @gitgatemkdocs через gitea.
ㅤ
Чтобы всё это заработало, в проекте тебе нужно создать структуру:
.gitea/workflows/deploy.yml
Файл можешь обозвать как угодно.
name: Build and Deploy Bashdays Blog
on:
push:
branches:
- main
jobs:
build:
runs-on: super-runner
container:
image: catthehacker/ubuntu:act-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install dependencies and build
run: |
pip install -r requirements.txt
mkdocs build
- name: Deploy to Server
uses: https://gitea.com/aquelle1/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-rlgoDzvc -i --delete"
SOURCE: "site/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }}
TARGET: ${{ secrets.REMOTE_TARGET }}
Давай пробежимся:
Триггер on: push: запускается если что-то запушено в ветку main.
Почему в main а не в master? Читай тут.Следом запускается джоба
build на раннере super-runner, не забываем зарегать себе раннер, без него нихуя не получится.
Что такое раннеры и как с ними работать, можешь загуглить, там по сути ничего сложного. Поэтому этот этап пропущу. Чуть позже отдельным постом запилю про это.Дальше используем адаптированный контейнер с убунтой 22.04 специально адаптированный под тестирование GitHub Actions через
act.
Почему GitHub Actions? Потому что gitea унаследовало синтаксис и пайплайны в теории могут переносится между системами.
Пиздеть не буду, не переносил, но если у тебя есть опыт, то было бы интересно увидеть его в комментариях.
Потом идут шаги speps, клонируется репозиторий с проектом в контейнер, устанавливаются необходимые зависимости через «пипку», ну и билдится финальная статика.
После сборки идет секция с деплоем, я использую этот экшен. Основан он на rsync поверх ssh.
Забиваем нужные ключи и переменные, которые требуются для работы этого экшена. Переменные определяешь в настройках проекта в gitea в секции secrets.
SSH_PRIVATE_KEY = Приватный ssh ключ с которым раннер пойдет на твой сервер и подключиться по ssh к нему. Соответственно публичная часть ключа должна быть прописана у пользователя на сервере в файле ~/.ssh/authorized_keys.
Как работать с ssh ключами, читай по тегу #linuxfactoryARGS = Аргументы для
rsync, рекурсивное копирование, сохранение прав доступа, удаление файлов которые не в локальной версии.
SOURCE = Какой каталог со статикой отправляем. В Mkdocs статика генерится по умолчанию в папку site.
REMOTE_HOST & REMOTE_USER = Айпишник или домен продакшена на который деплоим + имя пользователя под которым подключаемся к серверу.
TARGET = В какую папку на проде скинуть содержимое папки site.
Параметров в экшене гораздо больше, у меня приведен необходимый минимум. Про все ключи и свистоперделки этого экшена можешь почитать тут.
Вот и всё. Теперь при пуше в main ветку, автоматически запустится пайплайн и на прод выкатятся изменения.
В моем случае выкатываются новые посты в markdown. Этот процесс хочу автоматизировать и продублировать все посты из этого канала в блог, сделать наконец нормальную навигацию и поиск. А то чёрт ногу сломит уже, хуй чё найдешь. Но это пока только мечты, мечты...
Короче хорошего тебе вечера, теперь уже до завтра!
tags: #devops #cicd
—
🔔 @bashdays➡️ @gitgate