TGViewer
Channel Public Channel
Bash Days | Linux | DevOps

Bash Days | Linux | DevOps

@bashdays

Авторский блог от действующего девопса

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

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

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Subscribers
23.6K
Photos
225
Videos
26
Links
778

Showing posts older than #495 · Back to latest

Older Posts 17 shown
Post #494 13.3K
Тут персонаж один пристал, говорит что у него в Java есть какой-то «мусожор», а вот в Bash такого нет и поэтому от наших скриптов одни проблемы.

Термин «Мусожор» видимо профессиональный и является пресловутым «Garbage Collector».
ㅤ
К Java я отношусь ровно, оно меня не трогает и я его тоже.

Как говорится — Одно гавно другому не равно. Поэтому хуисосить не буду.

Давай проведем эксперимент:

1. ps -o rss -p $$
2. var=$(printf "%s\n" {1..100000})
3. ps -o rss -p $$
4. var="bashdays"
5. ps -o rss -p $$


В первой строчке выводится количество физической памяти в килобайтах, используемой текущим процессом оболочки. У меня выдало 4348.

Во второй строчке записываем в переменную var содержимое от 1-100000 с переносом на новую строку.

В третьей строчке снова выводим количество физической памяти, у меня 5276.

Ага, оно стало больше. Было 4348 стало 5276.

В четвертой строчке, перезаписываем var на строку «bashdays» и снова проверяем память.

На этот раз пятая строчка вновь показывает: 4348.

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

Все манипуляции с памятью выполняются на уровне Linux ядра. И нет никакой необходимости рвать жопу и греть голову.

Bash не работает с памятью и объектами, так же как обычные языки программирования.

tags: #bash
—
🔔 @bashdays
Post #492 11.8K
Про интересный факап и траблшутинг.

Обратился клиент — у нас mysql реплика не работает. Вернее работает, но отстала всего лишь на 3 месяца.

На вопрос — а хули вы 3 месяца сидели, у вас же мониторинг есть?

Очевидный ответ — да, есть, но оно молчит.

Ладно, полез разбираться. SHOW SLAVE STATUS\G;

А там ошибки брынчат, как хуи в бидоне.

Error 'Cannot delete or update a parent row: a foreign key constraint fails'


Ну это ладно, ошибка и ошибка, тут понятно что делать — НИЧЕГО.

Так как реплика используется чисто аналитиками на потыкать, игнорим эту ошибку через my.cfg. Быстрофикс.

✔ Для продуктовой реплики такое делать - НЕЛЬЗЯ!

Самый важный вопрос — какого хера мониторинг 3 месяца молчал?

Тут уже интереснее. Реплика заведена в prometheus, экспортеры есть, все дела.

Но из графаны сервер пропал, хотя год назад я ее точно там видел.

Думаем… Думаем… Смотрю графану, мониторится поле: replica_seconds_behind

Хм, лезу обратно на реплику, а там сроду нет mysql_exporter. Что же это тогда такое?

Копаем вглубь и видим, что node_exporter мониторит папку /tmp на наличие файликов .prom.

Ага… То есть метрики с mysql реплики собирает какой-то bash скрипт по крону, генерит текстовичок и отдает в prometheus.

Типа такого:

replica_slave_io_running{host="replica"} 1
replica_seconds_behind{host="replica"} 1234567


Да, оно прекрасно работало, до момента пока не вылезла ошибка: Cannot delete or update a parent row

Соответственно текстовый файл replica.prom получился в таком формате:

replica_slave_io_running{host="replica"} 1
replica_seconds_behind{host="replica"} Null


Ну а дальше prometheus такое распарсить не смог (он хочет циферки, а не буковки) и тихонечко вывел эту ноду из графаны и вообще отовсюду. Ну и аллерты в придачу. На что им тригериться если ноды нет нигде?

Прикол в том, что во время возникновения ошибки, поле Seconds_Behind_Master в mysql принимает значение Null, а не продолжает дальше считать на сколько отстала реплика.
ㅤ
А вот и bash скрипт, который собирал метрики:

#!/bin/bash

MAINDIR=/tmp
METRICS=rstatus.prom
HOST="replica"

SLAVE_IO_RUNNING=$(mysql -e 'SHOW SLAVE STATUS \G' | grep 'Slave_IO_Running'| awk '{print $2}')
SLAVE_SECONDS_BEHIND=$(mysql -e 'SHOW SLAVE STATUS \G' | grep 'Seconds_Behind_Master'| awk '{print $2}')

if [[ "$SLAVE_IO_RUNNING" == "Yes" ]]; then
J=1
echo 'replica_slave_io_running{host="'$HOST'"}' $J > $MAINDIR/$METRICS
else
J=0
echo 'replica_slave_io_running{host="'$HOST'"}' $J > $MAINDIR/$METRICS
fi

echo 'replica_seconds_behind{host="'$HOST'"}' $SLAVE_SECONDS_BEHIND >> $MAINDIR/$METRICS


Работа над ошибками проведена, инцидент разобран. Ни одна жопа на ретроспективе пока не пострадала, но возможно дело времени.

Как писать подобные экспортеры я накидывал в этом посте.


И всегда помни — если изобретаешь велосипед, всегда обрабатывай эксепшены!

tags: #devops #debug #bash #monitoring
—
🔔 @bashdays
Post #490 11.6K
Такс. Вопрос из зала — как через bash скрипт запросить у пользователя пароль, но чтобы при вводе пароля отображались звездочки?

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

Кишка первая.

a=''; while read -n 1 -s c; do [ "$c" = '' ] && break; echo -n '*'; a="$a$c"; done


Согласен, выглядит хуёва, но вторая на визуал еще хуёвие.

В этой кишке есть нюанс, она НЕ работает с кнопкой Backspace, то есть ты не сможешь отредактировать, то что уже ввел.

Кишка вторая.

a=''; while read -n 1 -s c; do [ "$c" = '' ] && break; if [ "$c" = $'\x7f' ]; then [ "$a" != "" ] && { a=${a:0:-1}; printf "\b \b"; }; else echo -n '*'; a="$a$c"; fi; done;


А тут уже более совершенный вариант, с рабочей кнопкой Backspace.
ㅤ
Чо делать дальше? Ну логично же, в переменную «a» записывается введенный пароль, а дальше делай с ним все что захочешь.

Вот такие пироги!

tags: #bash
—
🔔 @bashdays
Post #488 12.2K
Здрасти. Существуют самописные скрипты, которые при запуске устанавливают необходимый набор программ. Этакая автоматизация на коленке, быстро, удобно, никаких ансиблов и паппетов.

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

Добавить в скрипт reboot на каждую команду? Да не, хуйня какая-то. Тут на помощь приходит reboot-required.

Ща покажу. Есть однострочник:

apt update && apt -fy upgrade && [ -f /var/run/reboot-required ] && shutdown -r now


Первая часть понятна, обновили, апгрейднули, а дальше идет магия.
ㅤ
В квадратных скобках конструкция, которая проверяет наличие файла /var/run/reboot-required и если он есть, то выполняется перезагрузка.

Файл reboot-required создается, если система считает, что после обновления требуется перезагрузка. Если файл существует, возвращается true. А если true, то запускается -r = reboot.

Вот и вся наука. Изучай…

tags: #bash #linux
—
🔔 @bashdays
Post #487 14.3K
Выходные заебись!

Сумма значений со стандартного ввода, или из файла.

➡️ Datamash

seq 1000 | datamash sum 1  
datamash sum 1 < <(seq 1000)


➡️ Awk

seq 1000 | awk '{sum += $1}END{print sum}'  
awk '{sum += $1}END{print sum}' <(seq 1000)


➡️ Dc

seq 1000 | dc -e '0d[?+2z>a]salaxp'  
dc -e '0d[?+2z>a]salaxp' < <(seq 1000)


Последнее решение самое занимательное. И самое небезопасное, потому что данные управляют программой.

Вообще во всех трёх случаях очень желательно очищать входные данные.

Почитать:

man datamash  
man seq
man awk
man dc


Да будет так!

tags: #bash
—
🔔 @bashdays
Post #486 12.9K
Так, пора закончить с этими картами.

Короче, представляем ситуацию, что тебя нахуй уволили или не заплатили, а ты еще тот злой гений.

Задача — нужно применить все свои навыки заподлостроения в инфраструктуре и знатно усложнить жизнь этим гадам. У тебя есть root доступ ко всему и ты отрабатываешь две недели.

Условия — на тебя не должны подумать и взять за жопу.

Пиши в комментарии свой гениальный план. Чей коммент наберет больше реакций, тому и карты в руки.

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

Итоги подведем в следующую пятницу. Доставка по РФ и Беларусь.

Пару колод отдадим вторым и третьим местам, но нужно будет подождать, на руках у меня их щас нет. Там ченить придумаем.

Но если прям чешется, можешь заказать у Кати через Авито.

Погнали сочинять! Может в будущем кто-то и воспользуется твоим гениальным планом 🥳
Post #485 11.8K
🚜 Синий трактор едет к нам

Этот пост изобилует грубыми выражениями и, в силу своего содержания, вообще не предназначен для просмотра лицам с хрупким душевным миром.


✔ Про Gitlab!

Заебали блядь, мне чо каждый день это гавно обновлять? Ладно бы там нажал кнопку как в wordpress и забыл. А нет, надо хуеву гору телодвижений сделать.

И в 100% эта залупа с первого раза никогда не заводится, то миграции ручками надо запускать, то еще 10 версий предыдущих накатить и молиться.

В прошлый раз вообще пришлось пайплайны переписывать, поломали совместимость.

Либо хуй пополам, либо пизда в дребезги, другого не дано.


А еще соль, что при обновлении мне приходится параллельно поднимать клон сервера, на случай если обновка сделает мозги, можно будет на старую версию переключиться. Удобство через край…

И на закуску фаталити — обновку накатывать нужно поздно ночью, либо в выходные, когда разработчики в режиме AFK. Хуита какая-то!

Можно и в будни, но заебут вопросами — а когда заработает?

Короче я такие апдейты на хую Лунтика вертел.


Хоть отдельного человека нанимай, чтобы каждый день обновки катил в три часа ночи.

Что я буду с этим делать? НИЧЕГО! Пусть нахуй всё взламываеют и пиздят, заебали!

Пардон. Накипело!

ps: так, мне еще вам конкурс придумывать сегодня, так что чуть позже увидимся, пойду успокоительное пить да Зельду на свиче задрачивать.


tags: #рабочиебудни
—
🔔 @bashdays
Post #483 10.4K
🔥 Кишочки. Короче познавательное.

В документации для команды eval довольно пространное описание. Давай сегодня с ней поковыряемся.

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

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

Короче дохера всего. Полный список можешь найти в разделах SIMPLE COMMAND EXPANSION и EXPANSION выполнив:

man 1 bash


Ну дак вот, команда eval запускает эту обработку кода. Но прежде чем команда eval будет запущена, код должен быть обработан.

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

Очевидно? Совсем нет. Но вот оно так работает, чо с него взять.

Эта возможность используется по-разному, например для генерации и последующего исполнения кода.

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

Ниже примеры. При присваивании значения переменной, приведенная конструкция с фигурными скобками не расширяется.

Расширение переменной в строке с командой echo происходит гораздо позже, чем расширение фигурных скобок.

Поэтому используем eval. Первая обработка развернет переменную. Вторая, которая запустит eval, развернет конструкцию с фигурными скобками.

str={1..10}   
echo $str
eval echo $str


В результате получим:

{1..10}
1 2 3 4 5 6 7 8 9 10


Другой пример. Здесь из-за использования одинарных кавычек, переменной присваивается указанная строка, а не значение переменной.

И обработка строки делает расширение переменной один раз. Получаем значение переменной s0. Количество обработок строки равно количеству eval плюс один.

(s0=100 ; s1='$s0' ; s2='$s1' ; echo "$s2")
(s0=100 ; s1='$s0' ; s2='$s1' ; eval echo "$s2")
(s0=100 ; s1='$s0' ; s2='$s1' ; eval eval echo "$s2")


На экране ты увидишь:

$s1
$s0
100


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

Это значит, что если ты откроешь файл на чтение и слева укажешь переменную содержащую нужный дескриптор, эта переменная не будет участвовать в перенаправлении.

И раз не указан дескриптор, файл будет ассоциирован со стандартным потоком ввода.

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

(fd=6 ; exec "$fd"</dev/null) 
(fd=6 ; eval exec "$fd</dev/null")
(fd=6 ; eval exec "$fd"\</dev/null)
(fd=6 ; eval exec "$fd"'</dev/null')


В первой строке: /dev/null на stdin и пытается запустить 6.

Круглые скобки использовались, чтобы не засорять текущую оболочку. И чтобы она не завершилась на первом примере. Из-за того что на её стандартный ввод повесили /dev/null. Проверяем какой дескриптор ассоциирован с устройством /dev/null.

bash -c 'shopt -s execfail ; fd=6 ; exec $fd</dev/null ; ls -l /proc/$$/fd'  
bash -c 'shopt -s execfail ; fd=6 ; eval exec $fd\</dev/null ; ls -l /proc/$$/fd'
bash -c 'shopt -s execfail ; fd=6 ; eval exec "$fd</dev/null" ; ls -l /proc/$$/fd'


Этот «хак» с перенаправлением можно использовать для исследований. Когда требуется определённый диапазон дескрипторов.

Почитать: man 1 bash, разделы:

# REDIRECTION  
# SHELL BUILTIN COMMANDS -> eval
# SHELL BUILTIN COMMANDS -> exec
# SHELL BUILTIN COMMANDS -> shopt


А завтра запускаем конкурс с картами. Моя ленивая жопа соизволила добраться до почты.

Хороших выходных!

tags: #bash
—
🔔 @bashdays
Post #481 11.2K
Отличный способ запихать все свои crontab джобы в git репозиторий и раскатывать по желанию на сервера.

Подойдет для хейтеров всяких ансамблей, паппетов и других бродячих цирков абсурда.

По мотивам этого поста про факап с кронами и его восстановление через grep.


Короче создаешь репу в гите, создаешь текстовый файл supercron. И в этот файл переносишь все свои действующие джобы. Коммит && Пуш --форцед инда мастер оф паппетс.

Ну а дальше элементарно. Накидываем чото подобное:

#!bin/bash

REPO_DIR=/tmp
CRON_FILE=/tmp/supercron
cd $REPO_DIR
git pull origin master
crontab $CRON_FILE


Суть — забрать из репы файл supercron и импортировать жопы джобы. Импорт осуществляется последней строкой crontab /tmp/supercron.

Сразу предупрежу, твой /var/spool/cron/crontab/root перетрется без предупреждения содержимым файла supercron.

Можешь этот скрипт повесить на крон и сервер «даст ёбу». Крон, который импортирует крон. 💃 Идеальная рекурсия.

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

Короче ништяк костыль. Инфраструктура как кот! Не благодари )

tags: #devops #bash
—
🔔 @bashdays
Post #479 10.9K
Сегодня будем искать самое длинное слово в текстовом файле. На pure bash. Зачем? Джаст фор фан, чтоб мозги подразмять. А вообще эта задачка из методички для собесов.

Создаем текстовый файл bashdays.txt с таким содержимым:

hello world хуйпиздаджигурда bashdays комутохеровато бидон


Пишем скрипт:

#!/bin/bash

longest=0
for word in $(<bashdays.txt)
do
len=${#word}
if (( len > longest ))
then
longest=$len
longword=$word
fi
done
printf 'Самое длинное слово %s и его длина %d.\n' "$longword" "$longest"


В результате получаем: Самое длинное слово «хуйпиздаджигурда» и его длина 16.

Алгоритм таков: цикл проходит по каждому слову в файле, вычисляет длину текущего слова len=${#word} и сохраняет результат в переменную len. Ну и логика больше-меньше.

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

Вечером еще чтиво подъедет. На связи!

tags: #bash
—
🔔 @bashdays
Post #478 12.2K
Разыгрывать будем 👆 только среди подписчиков могзотрах, чатика и полезняшек, королевство кривых ебал — мимо. Так что не облажайся, подпишись на все три.
Post #474 14.7K
Сегодня подъехал экземпляр «Релиз», Лемитед блядь эдищен.

Если моя ленивая жопа завтра соизволит сходить на почту, то завтра и разыграем эту колоду среди подписчиков нашего Пантеона.
Post #473 10.8K
а у кого какие бест практики подобных деплоев? 👆 давайте в комментах найдем эти практики, будет всем полезно, чтоб гавно не делать впредь

скидывайте, не бойтесь, любые даже самые топорные решения, главное не ругайтесь
Post #472 13.7K
Со шрамами приходит сила

И снова здрасти. Хуй знает очевидная эта штука для тебя или нет, но я все равно ее подсвечу.

Предположим у тебя есть какой-то проект описанный в docker-compose.yml. Вся эта чача раскатывается через пайплайны gitlab на продакшен.

Из того что я постоянно вижу — После сборки проекта, все собранные файлы копируются на продакшен с помощью rsync, scp или подобных утилит, ну и ранится все это дело через ssh.

Например:

script 
- билд хуилд
- rsync -avz --delete ./ user@$prod:/var/www`
- ssh user@$prod "docker compose up -d"


1. Что-то там собралось
2. Файлы синканулись с продом
3. Запустилось если смогло

✔ Хуита! Всё делается изящнее. Ща покажу.

stage: deploy
image:
name: docker/compose
script:
    - docker-compose -H "ssh://root@$prod" down --remove-orphans
    - docker-compose -H "ssh://root@$prod" pull
    - docker-compose -H "ssh://root@$prod" up -d


Используем мощности docker-compose, не привлекаем никакие rsync, scp и т.п. А сразу нативно запускаем на проде наш docker-compose.yml файл.

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

В штыки не воспринимай, способ с rsync и т.п. вполне годный. Но делюсь, тем, чем пользуюсь сам. У меня телеграм боты так деплоятся.

Изучай. Не отвлекаю! Если хоть одному из вас пригодится, это уже хорошо!

tags: #devops
—
🔔 @bashdays
Post #471 11.3K
Ну и пекло, по ощущениям +60 и комары. Сегодня на изи, KPI нулевой.

Узнаем имя и путь последнего файла/каталога. Иногда нужно отработать подобный кейс, чтобы произвести какие-то манипуляции над последним файлом в каталоге.

ls -t ~/backups/* | head -1


Выдаст полный путь до файла/каталога. В примере папка с бекапами. Чтобы не ебстись и городить кишку с find, у ls есть для этого ключик для сортировки.

Ну и с помощью head, забираем имя последнего файла/каталога.

Всё, пойду дальше плавиться…

tags: #bash #linux
—
🔔 @bashdays
Post #469 12K
Забавная хуита. Виндовз что с тобой?

Короче если создать текстовый файл с содержимым «This content is no longer available.» и сохранить его, винда начинает жестко угорать.

Мол, вы пиздец хакер и только что создали вирус под названием Trojan:Win32/Casdet!rfn. Касдет-пиздет.

Trojan:Win32/Casdet!rfn – это вредоносная программа, относящаяся к категории удаленного доступа (RAT). Она позволяет злоумышленникам получить контроль над вашим компьютером, красть ваши данные и устанавливать другие вредоносные программы.


Прикольно. Что-то из оперы EICAR

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


По-видимому, это коллизия хэшей. Потому что только Windows Defender его детектит, вот репорт с вирус-тотал.

tags: #мозготрах
—
🔔 @bashdays
Post #468 9.77K
Зрасти. Сегодня замутим простую проверку корректности формата файла. Для этого воспользуемся утилитой sed.

Вводные

Есть файл с последовательностью символов 1, 2, 3, 4, 5. Каждая цифра с новой строки. Эти символы могут располагаться в любой позиции строки. Строка может содержать другие символы отличные от символов заданной последовательности.

Пример такого файла:

1  
2
3
4
a1
b2
3c
4d


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

✔ Создаем скрипт check

#!/usr/bin/sed -nf

$bE ; /1/!bE ; n
$bE ; /2/!bE ; n
$bE ; /3/!bE ; n
/4/b

:E = ; q


Необычно? Необычно! Это скрипт на языке Sed. Давай Разберем, что тут происходит.

$bE = Если находимся на последней строке переход к метке «E».

/1/!bE ; n = Если текущая строка не содержит 1, переход к метке «E». В противном случае переходим к следующей строке.

… аналогично для 2 и 3

/4/b = Если текущая строка содержит 4, перейти в конец скрипта.

:E = ; q = метка «E» печатает текущую строку и завершает выполнение.

Погнали чекать кейсы. Не забудь на check впиздярить +x.

printf '%s\n' {1..3} | ./check
printf '%s\n' {1..4} | ./check
printf '%s\n' {1..4} {1..5} | ./check
printf '%s\n' {1..4} {1..4} | ./check
printf '%s\n' a{1..4} b{1..4} | ./check
printf '%s\n' a{1..4} b{1..3} | ./check


1. Выводится 3 номер строки
2. Пусто. Файл валиден.
3. Выводится 9 номер строки
4. Пусто. Файл валиден.
5. Пусто. Файл валиден.
6. Выводится 7 номер строки

Вместо перехода на метку можно просто выходить и возвращать нужное значение с помощью команды «q» которая в GNU версии принимает аргумент.


Чтиво: адресация, команды, шаблоны

tags: #bash #linux
—
🔔 @bashdays
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →