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 788 مشترک است و جایگاه 5 702 را در دسته فناوری و برنامهها و رتبه 28 099 را در منطقه روسيا دارد.
📊 شاخصهای مخاطب و پویایی
از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 23 788 مشترک جذب کرده است.
بر اساس آخرین دادهها در تاریخ 19 ژوئن, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -226 و در ۲۴ ساعت گذشته برابر 1 بوده و همچنان دسترسی گستردهای حفظ شده است.
- وضعیت تأیید: تأیید نشده
- نرخ تعامل (ER): میانگین تعامل مخاطب 23.40% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 13.11% واکنش نسبت به کل مشترکان کسب میکند.
- دسترسی پستها: هر پست به طور میانگین 5 567 بازدید دریافت میکند. در اولین روز معمولاً 3 119 بازدید جمعآوری میشود.
- واکنشها و تعامل: مخاطبان بهطور فعال حمایت میکنند؛ میانگین واکنش به هر پست 22 است.
- علایق موضوعی: محتوا بر موضوعات کلیدی مانند bashdays, linux, bash, docker, скрипт تمرکز دارد.
📝 توضیح و سیاست محتوایی
نویسنده این فضا را محل بیان دیدگاههای شخصی توصیف میکند:
“Авторский блог от действующего девопса
Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.
Автор: Роман Шубин
Реклама: @maxgrue
MAX: https://max.ru/bashdays
Курс: @tormozilla_bot
Блог: https://bashdays.r...”
به لطف بهروزرسانیهای پرتکرار (آخرین داده در تاریخ 20 ژوئن, 2026)، کانال همواره بهروز و دارای دسترسی بالاست. تحلیلها نشان میدهد مخاطبان بهطور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامهها تبدیل کردهاند.
vim bashdays.tape
И пишем код:
Output bashdays.gif
Require echo
Set Shell "bash"
Set FontSize 32
Set Width 1920
Set Height 1080
Type "echo 'Hello this is BashDays'" Sleep 500ms Enter
Type "apt install -f nginx" Sleep 500ms Enter
Sleep 5s
Думаю тут все интуитивно понятно, откроется оболочка bash, настроятся шрифты, высота, длиннота и сообщение которое будет напечатано. Либо команда, которая будет выполнена. Настроек там дофига, но как обычно 90% никем не используются.
После того как сценарий готов, запускаем:
docker run --rm -v $PWD:/vhs ghcr.io/charmbracelet/vhs bashdays.tape
Наблюдаем за процессом создания и на выходе получаем файл bashdays.gif. В котором будет вывод строки через echo и процесс установки nginx.
Получившийся gif файл можно не отходя от кассы сразу зашарить на какой-то расшаренный сервер.
Вот такой командой:
docker run --rm -v $PWD:/vhs ghcr.io/charmbracelet/vhs publish bashdays.gif
По итогу получишь прямую ссылку вида: https://vhs.charm.sh/vhs-62gl16v.gif
Ну а дальше уже втыкай свои гифки в корпоративные wiki, или куда там ты их втыкаешь. Короче штука ОФИГИТЕЛЬНАЯ. Всем рекомендую!
🐱 Сраница проекта на github
Всех с пятницей, хороших предстоящий выходных и береги себя! 🤩
tags: #linux #utilites
—
💩 @bashdaysmount -o remount,rw,nosuid,nodev,noexec,relatime,hidepid=2 /proc
Теперь снова запускаем от обычного пользователя htop и наблюдаем интересную картину маслом. Портянка из процессов пропала, у меня осталось лишь 2 штуки, bash и htop. Красота!
Естественно после ребута сервера, вся эта красота сгинет. А чтобы этого не произошло, зафигач монтирование /proc в fstab.
Вставляем в /etc/fstab
proc /proc proc defaults,nosuid, nodev, noexec,relatime,hidepid=2 0 0
Вот и всё. Но есть одно НО. Встречаются приложения которые могут отвалиться. Для этого нужно захотфиксить маунт с опцией gid=VALUE.
Значением gid параметра может быть имя группы в системе, членам которой доступ к процессам будет разрешён. И затем маунтить /proc таким образом:
proc /proc proc defaults, hidepid=2, gid=bashdays 0 0
Добавляем пользователя от имени которого будет работать приложение/демон в эту группу и проверяем — если всё сделано верно, то зафакапленное приложение заработает как обычно.
Такие дела. Изучай. На связи!
tags: #linux #utilites
—
💩 @bashdaysУ меня вообще с этим отлично реализовано в iTerm. Консолька открывается в Drop-down режиме по нажатию F1. То есть сверху вниз, поверх всех окон выезжает мой основной рабочий инструмент. Ну и также закрывается. Привык, ОЧЕНЬ удобно! Под линуксы и винду такое тоже реализуемо и есть из коробки. Отдельный пост про это надо будет запилить.Давай создадим в TW первую таску:
task add "Написать пост про taskwarrior"
Всё! Задачка в бэклоге и про нее уже не забудешь, можно смело выкидывать из головы и торжествовать.
Конечно же предварительно taskwarrior нужно установить, есть под все операционки и дистрибутивы. Дока по установке тут. Ставится на уровне пакетных менеджеров, но можно и через исходники скомпилировать если ты любитель прекрасного.
Как говорится на этом можно и закончить. Но хотелось бы еще посмотреть список всех задачек, которые мы создали. Для этого фигачим:
task ls
И получаем желаемый список Ну а чтобы пометить таску как выполненную, делаем:
task done 1/2/3/4/5
Подставляем индекс таски, которую нужно закрыть. Всё! Это основное. Простота и удобство! Не думай что TW на столько ущербен, там из коробки просто нереальный функционал. Но я использую наверное процента два от всего возможного.
Дополнительно у меня создано 2 проекта, home и work. По ним раскидываю задачи, которые относятся к домашним делам и рабочим. Чтобы было проще ориентироваться и выводить нужные на экран.
Чтобы синхронизировать заметки и задачи между устройствами, нужно поднять свой ламповый сервер. Будет единая точка входа с базой данных. А там уже цепляйся к нему хоть с писюка хоть с андроида/ios, и крути педали. Удобнее конечно через docker-compose все поднимать.
Для удобства я сделал себе несколько алиасов, теперь мне не нужно каждый раз писать task и название проекта.
alias th="task project:home add "
alias tw="task project:work add "
alias tlh="task project:home ls "
alias tlw="task project:work ls "
В общем в TW полный минимализм и отличная кастомизация для всех любителей консольных штук. Еще можно настроить цвета, приоритеты, поглядеть отчеты и многое другое. Но мне хватает коробочного варианта. В общем всем советую потыкать.
💩страница проекта
🐱 страница на гитхабе
💩 клиент для андроида и тут
💩 клиент для айфона
Как это выглядит визуально, можешь глянуть тут, подзалил нативно картичночки. А тут крутой sheets по tw.
Ладно, убежал. Если бухгалтерию разгребу, вечерком чего-нибудь забашим или обсудим!
tags: #linux #utilites #рабочиебудни
—
💩 @bashdays#!/bin/bash
coproc read
read -t 0.10 -u "${COPROC[0]}"
echo 'new velosiped'
read -t 11 -u "${COPROC[0]}"
exit
1. Создаем фоновый со-процесс read
2. Спим 0.10 секунды
3. Выводим на экран new velosiped
4. Опять спим, но уже 11 секунд
5. Выходим
За указания задержки, как раз отвечает параметр -t. А параметр -u говорит что чтение данных нужно осуществлять с файлового дескриптора запущенного в фоне со-процесса. Белиберда? Еще какая!
В sleep, кстати тоже можно указывать миллисекунды: sleep 0.10
Со-процессинг это одновременное выполнение двух процедур, одна из которых считывает вывод другой.
Чтобы запустить со-процесс, используется зарезервированное слово coproc. Доступ к этому со-процессу осуществляется посредствам массива COPROC.
${COPROC[0]} - для записи
${COPROC[1]} - для чтения
В реализации такого таймера есть и подводные камни. Таймер может отставать как механические часы, это зависит от загруженности самой системы.
Если запустить одну команду coproc read, на экран выведется PID запущенного в фоне процесса [1] 126594. Чтобы посмотреть список запущенных в фоне команд, выполняем jobs и видим список:
[1] Running coproc COPROC read &
[2] Running coproc COPROC read &
[3] Running coproc COPROC read &
То есть получается ты запускаешь в фоне какую-то программу, а в другой программе, подключаешься через массив COPROC записываешь либо считываешь нужные тебе данные.
Еще пример:
coproc awk '{print $2;fflush();}'
echo bom bim bom >&${COPROC[1]}
read -ru ${COPROC[0]} var
echo $var
По итогу получаем вывод на экран, слово: bim
Давай попробуем попроще:
coproc (echo $(whoami))
read -r user <&"${COPROC[0]}"
echo $user
1. Создаем со-процесс, который в фоне выполнит whoami
2. Прочитаем в переменную user, то что вывел со-процесс
3. Выводим на экран, у меня отобразилось root
Фуф, тут вроде более понятно получилось объяснить. Ну а если не понял, значит оно нахер тебе и не нужно.
Короче без бутылки тут не разобраться, это из оперы «высший пилотаж» и брейнфак.
Зачем это нужно и где применять? Понятия не имею. Я обычно не лезу в со-процессы, это усложняет скрипт, а коллеги которые не в теме, вообще не смогут его поддерживать.
Ну и на закуску, совсем уж упороться:
Несколько команд, которые помогут понять, как вся эта шляпа реализована.
coproc read
echo "${COPROC[@]}"
ls -l /proc/$$/fd | grep 'pipe'
ls -l /proc/$COPROC_PID/fd | grep 'pipe'
1. Создаем со-процесс
2. Выводим содержимое массива COPROC
3. Выводим каналы текущей оболочки.
4. Выводим каналы со-процесса.
Смотрим на имена, биты разрешений (r/w) ссылок и на что они указывают.
Как сказал один западный эксперт:
Пока я не могу придумать никаких задач для со-процессов, по крайней мере не являющихся надуманными.Вот такие пироги, изучай. tags: #linux #bash — 💩 @bashdays
[[ -r ~/.bashrc ]] && . ~/.bashrc
Другие оболочки ведут себя по-другому. Например, в zsh, файл .zshrc всегда читается для интерактивной оболочки, независимо от того, является ли она login или нет.
А файл .profile, это просто сценарий входа в систему. И изначально использовался в /bin/sh. Оболочка Bash, будучи обратно совместимым с sh, будет читать .profile, если он конечно же существует.
Пример файла .profile
if [ "$BASH" ]; then
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
fi
Как видим, при login’е заинклудится файл .bashrc.
Классически ~/.profile используется в Bourne Shell. И вероятно, поддерживается Bash как устаревшая мера. Опять же ~/.login и ~/.cshrc использовались оболочкой CShell (csh).
В дистрибутивах семейства Debian сначала выполняется .profile, а потом уже .bash_profile. А вот в дистрибах производных от RHEL, сначала выполняется .bash_profile, а уже потом .profile. Ну вот прям каша!
Короче как обычно развели зоопарк, одно читает другое, чтобы заработало третье. Масло-масляное. А есть же еще всякие .environment, у которого ноги растут из Korn Shell (ksh).
Вот по этой причине никто особо и не вникает, почему все манипуляции обычно производятся в файле .bashrc. Этот файл обычно есть везде и всегда, а большего и не нужно.
В документации bash хорошо объясняется, при каких обстоятельствах читается каждый файл. И поведение на разных машинах в целом одинаково.
Выжимка из man bash:
/bin/bash - The bash executable
/etc/profile - The systemwide initialization file, executed for login shells
/etc/bash.bashrc - The systemwide per-interactive-shell startup file
/etc/bash.bash.logout - The systemwide login shell cleanup file, executed when a login shell exits
~/.bash_profile - The personal initialization file, executed for login shells
~/.bashrc - The individual per-interactive-shell startup file
~/.bash_logout - The individual login shell cleanup file, executed when a login shell exits
~/.inputrc - Individual readline initialization file
Если есть чего добавить, велком в комментарии. Ладно, вечерком затроним какую-нибудь техническую часть, а может быть и подебажим. На связи!
tags: #linux #bash
—
💩 @bashdayscommand1 || command2
Если первая команда вывалит ошибку, то отработает вторая команда. Ну чем не try/catch, Даже лучше! Правда концепция работы не такая как в других языках.
На практике это выглядит так:
false || echo "error, returned false"
Сейчас сработает catch и выведет «error, returned false», так как команда false всегда возвращает ошибку. Статус: exit 1.
А если false заменить на true, но сработает try и в терминале ничего не отобразится. Бесподобно.
Итоговая конструкция будет такой:
#!/bin/bash
{ # try
echo "hello bashdays"
false
} || { # catch
echo "error, returned false"
}
Для catch можно сделать отдельную функцию. Которая будет автоматически включать режим дебага (sex -x) либо какие-то другие свистоперделки для отладки.
Вообще это больше относится к костылям и подобное можно реализовать с таким же успехом на IF’ах. А можно банально проверять статус выхода, если > 0 то кирдык.
Я такие конструкции не использую, максимум втыкаю в начала скрипта set -e. Если статус команды будет > 0, то немедленно всё выпадет в осадок.
Тут нет правильных и неправильных решений. Как говорится если работает, то уже хорошо. Остальное детали.
Если есть чего добавить, велком в комментарии. Возможно у тебя есть секретный модуль для bash с try/catch.
tags: #linux #bash
—
💩 @bashdays#!/bin/bash
for i in {1..10000}
do
echo $i >> /tmp/log.txt
sleep 2
done
Запускаем, ага. Теперь открываем второй терминал и пишем:
tail -f /tmp/log.txt
Видим как файл log.txt постепенно наполняется циферками.
Всё прекрасно. Что нужно сделать дальше. А дальше жми сочетание клавиш ctrl+z в первом терминале, где ты запустил скрипт.
Комбинация клавиш Ctrl + Z посылает процессу сигнал, который приказывает ему остановиться. Это значит, что процесс остается в системе, но как бы замораживается.
Ловим такое:
[1]+ Stopped ./script.sh
Видим что скрипт остановил свою работу. А во втором терминале с tail, цифры перестали заполнять файл log.txt. Ключевое слово - остановил, но не прекратил. Окей, мы на верном пути.
А теперь в первом терминале запускай команду bg, в ответ ты увидишь такое:
[1] + ./script.sh &
Видишь в конце закорючку &, наталкивает на мысли? 🤒
Команда bg предназначена для возобновления исполнения остановленной задачи в фоновом режиме в командных оболочках.
Скрипт продолжил работу в фоне, с того момента где ты его приостановил. Идем во второй терминал с tail и видим, что цифры продолжили заполнять файл.
Круто! Но это пока еще не все, если закрыть первый терминал, скрипт прекратит свою работу, нужно его как-то отвязать от текущей сессии и демонизировать.
Запускаем финалочку:
disown %1
Команда disown блокирует отправку системного сигнала SIGHUP с помощью командной оболочки и исполняющемуся в фоновом режиме процессу при завершении работы командной оболочки.
Теперь в первом терминале пишем exit либо просто закрываем его нахрен. Ха! А во втором терминале работа скрипта продолжается. Магия!
Вот таким образом ты можешь легко отвязать уже запущенный скрипт от терминальной сессии и уйти по своим делам, пощелкать впн и т.п. Кстати работает не только со скриптами.
Наверное есть еще варианты провернуть подобное. Я показал способ которым пользуюсь сам.
Ключевые слова для самостоятельного гугления: bg, fg, jobs, disown, nohup.
Да, после того как нажал ctrl+z, можно все откатить назад, запускаешь команду fg и ловишь флешбек.
Такие вот дела. Хорошего тебе вторника и не болей!
tags: #linux #bash
—
💩 @bashdaysscript.sh |& tee -a /var/log/script.log
Все что script.sh выведет в потоки stdout и stderr, будет перенаправлено в файл script.log.
В официальной документации этот момент хорошо расписан, но я расписал тебе еще проще.
Как говорится — мы из рощи, мы попроще! Всё, не смею тебя больше отвлекать, спасибо за внимание. Увидимся скорее всего в понедельник или вторник. Если чо пиши в чатик, мы там завсегда тебе рады!
tags: #linux #bash
—
💩 @bashdays#!/bin/bash
deploy() {
# здесь хочу получить "deploy"
}
Для получения имени функции из самой функции, можно воспользоваться переменной ${FUNCNAME[*]}.
Элемент с индексом 0 это имя любой выполняемой функции в данный момент. Ну а тот что имеет самый большой индекс, в моем случае это 1 (так как функция у меня одна) будет называться main.
deploy() {
echo ${FUNCNAME[0]}
}
Выведет название функции: deploy
Переменная FUNCNAME существует только во время выполнения скрипта. Если самостоятельно задать переменную FUNCNAME, это ничего не даст и все равно выведется эталонное имя функции.
При обращении к массиву без индекса, будет возвращен первый элемент массива текущий функции. Но так же будет содержать все остальные функции в стеке вызова.
Например:
exp1() {
echo ${FUNCNAME}
}
exp2() {
echo ${FUNCNAME[*]}
}
Первая функция выведет: exp1, а вторая выведет весь массив функции: exp2 main.
Вообще не обязательно указывать индекс, оно будет корректно работать и так. Это больше как кодстайл. Как в конце строки ставишь точку с запятой, которая не влияет на функционал программы и вообще никак не интерпретируется.
Ну а в zsh это штука называется funcstack, это тот же массив всех функций скрипта.
deploy() {
echo $funcstack[1]
}
Еще переменная FUNCNAME используется с BASH_LINENO и BASH_SOURCE, но про это уже можешь глянуть в официальной документации, как там вся эта магия происходит.
BASH_SOURCE - переменная, содержит путь к исходному файлу оболочки, полезна при отладке и анализе ошибок.
BASH_LINENO - переменная, содержит номер строки на которой произошла ошибка в текущем скрипте.
Вечером подвезу еще ништяков. Пойду маркировать интеграции, разгребать бухгалтерию, да готовить закупы на следующую неделю. Еще единомышленников немного сюда приведем. Давай пять, увидимся!
tags: #linux #bash #debug
—
💩 @bashdays#!/bin/bash -xve
set -xve
<script body>
Ключики команды set:
x = Выводим команды и их аргументы по мере их выполнения.
v = Выводить строки ввода командной строки по мере их считывания.
e = Немедленный выход, если команда завершается с ненулевым статусом.
Окей. Как-то дебажил один большой и сложный скрипт на овердофига строк. В какой-то момент скрипт завершался с ошибкой. В режиме отладки set -xve я видел, где он упал. Но мне хотелось знать — а на какой строке это произошло? Номера строк увы не выводятся, а по поиску и визуально искать - ну такое себе.
Эхх, одна задача превратилась в другую. В общем решил разок упороться и проресерчить этот вопрос, на будущее так сказать. По итогу получилось так:
Изменяем PS4 и добавляем вывод номера строки во включенный дебаг режим:
#!/bin/bash -xve
PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
bar=10
echo ${bar}
echo $((6 + 6))
После выполнения скрипта, получаем нумерацию строк:
bar=10
+(./script.sh:6): foo=10
echo ${bar}
+(./script.sh:7): echo 10
10
echo $((6 + 6))
+(./script.sh:8): echo 12
4
Теперь если скрипт где-то вылетает с плохим статусом (либо происходит что-то другое), всегда можно узнать в какой строке это приключилось, не бегая по огромному куску кода.
Ну а чтобы добавить визуального оргазма, экспортируем PS4 так:
PS4='\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Происходит подкрашивание запускаемых строчек.
С помощью PS4 мы можем отладить shell-скрипт, задав при его выполнении set -x, что позволяет выводить каждую команду, а затем ее результаты. Перед каждой командой ставится знак +, эту строку подсказки "+" можно изменить, определив переменную PS4.
Берите на вооружение. Хорошего дебага и с пятницей. Берегите себя!
tags: #linux #bash #debug
—
💩 @bashdayssudo apt install gettext man-db procps psmisc nano tree bsdmainutils x11-apps wget $ wget https://github.com/phyver/GameShell/releases/download/latest/gameshell.sh $ bash gameshell.shВот и все. Цель игры: Выполнять миссии, продвигаться вперед и сохранить рассудок. Если соберешь все яйца, в конце покажут мультик, но это не точно. 🐱 Страница проекта на github tags: #linux #games — 💩 @bashdays
command > file.txtПоток вывода перенаправлен в файл, в терминале его не видно. Если файл существует, он будет перезаписан.
command >> file.txtПоток вывода перенаправлен в файл, в терминале его не видно. Если файл существует, то новые данные добавятся в конец файла.
command 2> file.txtПоток ошибок перенаправлен в файл, в терминале его видно. Если файл существует, он будет перезаписан.
command 2>> file.txtПоток ошибок перенаправлен в файл, в терминале его не видно. Если файл существует, то новые данные будут добавлены в конец файла.
command &> file.txtПоток вывода и поток ошибок перенаправлены в файл, в терминале их не видно. Если файл уже существует, то он будет перезаписан.
command &>> file.txtПоток вывода и поток ошибок перенаправлены в файл, в терминале их не видно. Если файл уже существует, то новые данные будут добавлены в конец файла.
command | tee file.txtПоток вывода скопирован в файл, он виден в терминале. Если файл уже существует, то он перезапишется. Команда tee в Linux считывает стандартный ввод и записывает его одновременно в стандартный вывод и в один или несколько подготовленных файлов.
command | tee -a file.txtПоток вывода скопирован в файл, он виден в терминале. Если файл уже существует, то новые данные будут добавлены в конец файла.
(*)В Bash нет сокращенного синтаксиса, позволяющего передавать только StdErr второй команде, что было бы необходимо в данном случае в сочетании с tee для завершения операции.
command |& tee file.txtВ файл скопированы потоки вывода и ошибки, они видны в терминале. Если файл уже существует, то он перезапишется.
command |& tee -a fileПотоки вывода и ошибки скопированы в файл, в терминале их не видно. Если файл уже существует, то новые данные будут добавлены в конец файла. Вот такие пироги. Подробнее стандартные потоки разберем в следующих постах, многие их не понимают. Изучай. tags: #linux #sheets #bash — 💩 @bashdays
اکنون در دسترس! پژوهش تلگرام ۲۰۲۵ — مهمترین بینشهای سال 
