Bash Days | Linux | DevOps
23.3K subscribers
155 photos
24 videos
676 links
Авторский канал от действующего девопса

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

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

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Download Telegram
Здрасти здрасти хуймордасти, оказывается есть люди, которые не знают как залетать в mysql без пароля.

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

А нужно всего лишь создать файл в домашнем каталоге пользователя и обозвать его /home/user/.my.cnf.

Содержимое файла .my.cnf

[client]
user=user
password=passwd
database=db


Этот файл содержит настройки по умолчанию для команд mysql.

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

Либо передавать напрямую в mysql путь до файла с помощью ключа:

--defaults-file==filename


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

Теперь если в командой строке просто ввести mysql, ты залетишь в mysql без юзера и пароля + сменится база данных.

Обычно этот хак используют на рутах, чтобы рут не ебался и залетал с первым же лучиком солнца.


А для винды есть mysql_config_editor, который поможет зашифровать пароль, ведь в винде нужные права на файл хуй поставишь.

Почитать: Параметры командной строки, влияющие на обработку.

Хороших предстоящих выходных!

tags: #linux #mysql

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
9526
На пути к умноватому дому напишем простой ip watchdog на баш. Будем мониторить наличие интернета и перезапускать роутер, если он "завис".

#!/bin/bash
declare -i COUNTER=0
declare -r P=1m # задержка между пингами или циклами

function EXECUTE(){ echo $COUNTER Need execute ; }

while :;do
COUNTER+=1
for LNK in "ya.ru" "youtube.ru" "list.ru" "vk.com" "8.8.8.8" \
"2ns.info" "aliexpress.com" "yandex.ru" "77.88.8.8" "ozon.ru" \
"8.8.4.4" "gmail.com" "mail.ru" "ok.ru" "youtube.com";do
ping -c1 -w2 $LNK > /dev/null 2>&1
if [[ $? -eq 0 ]];then
COUNTER=0
sleep $P
fi
done

case $COUNTER in
0) continue;;
2|5|10|15|20|40|60|90|120|180|300) EXECUTE;;
600) COUNTER=300; EXECUTE;;
esac
sleep $P
done
#--


COUNTER - счетчик циклов присутствия проблемы.

P=1m - задержка в цикле 1 минута

function EXECUTE() - функция, в которой прописываем действия для устранения проблемы.

for LNK in ... done в цикле пингуем адреса, и если хотя бы один ответ получили, сбрасываем счетчик проблем в 0 и выдерживаем паузу. Если ответ на ping не получили без задержек переходим к следующему адресу.

Адреса на ping не проверял. Проверяйте, добавляйте, изменяйте сами.

ping -c1 - один пакет -w2 - время ожидания 2 сек

Таким образом, если все адреса отвечают - каждый из них пингуется раз в 15 минут (задержка * количество адресов). Если отвечает только 1 - пинговаться он будет ежеминутно. Не хорошо, но не критично.

case $COUNTER in ... esac самый удобный оператор для множественных условий.

Если проблем нет ($COUNTER=0) сразу возвращаемся к пингам. Если проблема есть попробуем ее решить (перезагрузить роутер, например).

Попытки будут предприниматься с нарастанием времени на 2,5,...300 циклах.

600) COUNTER=300...;; - далее попытки проводятся через 300 циклов. Вообще-то строку "600) COUNTER=300; EXECUTE;;" можно было бы заменить на "599) COUNTER=299;;" с сохранением логики работы. Но оставил более понятный вариант.

Прошу обратить внимание, что цикл чуть больше минуты, когда все хорошо, но когда ping не получает ответа - время ~ 2 сек. То есть время fail-цикла = задержка + (число адресов * 2сек) ~ 1мин 30 сек.

Ну, и теперь самое интересное.

На aliexpress ищем "usb relay". (одиночный < 200 рублей).

Качаем и ставим драйвера и пишем что-то вроде:

declare -r HEX_CODE_OFF='\xA0\x01\x01\xA2'
declare -r HEX_CODE_ON='\xA0\x01\x00\xA1'
#use ls /dev/ttyUSB* ###############################
declare -r USB_DEV=/dev/ttyUSB0
echo -n -e $HEX_CODE_OFF > $USB_DEV
sleep 30
echo -n -e $HEX_CODE_ON > $USB_DEV


Подключаем релюху (контакты NO) в разрыв провода питания роутера - и автомат готов.

PS от Ромы — НО будьте аккуратны, чтобы ёбом не токнуло!


tags: #homework #DIY © by Tagd Tagd

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
6222
А давай потрясём cиськами с помощью Bash!

Я думаю этот пост должен здесь быть, а постарался наш внештатный корреспондент Tadg Tadg. Погнали 👇

Сегодня разберем потрясный скрипт. Не в том смысле, что классный.

Просто он трясет сисками при выполнении длительных операций (копирование, загрузка, синхронизация).

Я когда-то видел что-то подобное, но найти не смог и пришлось писать свой. Вообще-то я против «красотулек», но кому-то нравится...

Сохраняем его в файл tits.sh и проверяем:

chmod +x tits.sh

# демо:
./tits.sh
# тест:
./tits.sh 7z b


Собственно скрипт:

#!/bin/bash

declare -r LOG=$(mktemp)
declare -r BS='\b\b\b\b\b\b\b'
declare -r SPC=' '
trap 'echo
tput cnorm
test -f "$LOG" && cat "$LOG" && rm "$LOG"
exit ' INT TERM HUP QUIT EXIT ERR
tput civis
CMD="$@"
test -z "$CMD" && CMD='sleep 10'
function TITS(){
declare N P T=${1:-21}
case "${T:0:1}" in
1) N='(.)';;
2) N='(o)';;
*) N='(*)';;
esac
case "${T:1:1}" in
1) P=${N}${N}' ';;
2) P=${N}' '${N};;
*) P=' '${N}${N};;
esac
echo -n "$P"
}
$CMD > "$LOG" 2>&1 &
PID=$!
echo -n "$SPC"
while :;do
for i in 21 12 23 33 23 12 21 31;do
echo -en $BS
TITS $i
ps -q "$PID" > /dev/null 2>&1 || exit
sleep .3
done
done
#--


Разбор скрипта:

LOG=$(mktemp) - создать лог в темповом каталоге
BS='\b\b\b\b\b\b\b' - забои для перемещения в начало строки (число равно размеру сисек в символах)
SPC=' ' - пробелы, для очиски сисек (число то же)

Поскольку используется темповый файл, пишем правильно.

trap INT TERM HUP QUIT EXIT ERR - Перехват сигналов, (последние два - башизм)
echo - перевод строки после сисек
tput cnorm - включение курсора
test -t "$LOG && "cat "$LOG" && rm "$LOG" - вывод на экран лога и его удаление (при наличии).
tput civis - гашение курсора
test -z "$CMD" && CMD='sleep 10' - если параметры скрипта не заданы - запускаем паузу 10 сек
function TITS() - входной параметр двузначное число, где десятки - форма соска, единицы - положение
declare N P T=${1:-21} - описываем локальные переменные. Если входной параметр не задан, используется 21
case "${T:0:1}" ... esac - задаем форму соска
case "${T:1:1}" ... esac - задаем положение
echo -n "$P" - выводим сиськи, без перевода строки.

Кстати, интересная особенность echo $P. Если переменная P содержит пробелы в начале и конце - они отбрасываются!

Если пробелы важны - нужно использовать "$P"

$CMD > "$LOG" 2>&1 & - запуск команды фоном, с выводом stdout и err в лог
PID=$! - запомнили PID запущенного процесса
echo -n "$SPC" - перед печатью сисек старые очищаются, чтобы было что очищать - печатаем пробелы.
while :;do - бесконечный цикл
for i in 21 12 23 33 23 12 21 31 - анимация
echo -en $BS - очищаем старый вывод (используем ESC-символы, без перевода строки)
TITS $i - печатаем сиськи
ps -q "$PID" > /dev/null 2>&1 || exit - проверяем не закончился ли фоновый процесс
sleep .3 - пауза 0.3 секунды

Вообще-то можно было бы обойтись буквально одним циклом... Но нужно же и учится. Даже на сиськах.

man tput mktemp signal ps
help trap declare
https://cheatsheets.zip/bash


Надеюсь тема сисек раскрыта. Всем добра. Tagd

tags: #bash

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
107526
Любишь линукс? А готов ли ты сыграть в опасную игру?

У тебя будет всего лишь одна попытка и как только ты ошибешься, придется знатно поебаться.

Поэтому прежде чем что-то сделать в консоли — подумай, а правильно ли ты ввел команду и готов ли ты поставить на карту всё самое дорогое?

Если готов всё потерять, запускай:

docker run --rm -it -v /:/host tiagoad/suicide-linux


Я проиграл спустя пару секунд и по настоящему проебал всё! Но испытал непередаваемое чувство радости и свободы. Вот и повод пересесть на 24.04. Вообще забавно получилось!


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

Рискнешь? Пиши в комменты, сколько тебе удалось продержаться и какую бурю эмоций ты испытал.

Все еще любишь линукс?

Вечный холивар, какой дистрибутив выбрать. Ответ однозначный - Suicide Linux! Он тебя дисциплинирует, с ним ты выйдешь на новый уровень и преисполнишься.

Рекомендую потыкать, но будь осторожен, сапёр ошибается только один раз.

Страница проекта: https://github.com/tiagoad/suicide-linux

tags: #linux

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
324616
У меня еще осталась пара тем по ssh, но пока отдохните, наберитесь сил... Я тут решил протестировать циклы for и поделиться результатами.

for ((i = 0 ; i < 100 ; i++)); do
echo $i
done


Годный цикл. Главное логичный и понятный.

for i in {1..3}; do
echo $i
done

# или его расширенная версия с шагом

for i in {50..5..-5}; do
echo $i
done


Возможно построение циклов с нарастанием и убыванием. Циклы не допускают подстановки переменных в параметры цикла!!! Чистый башизм. Не рекомендую.

for i in $(seq 1 10); do
echo $i
done


У разработчиков seq странная логика.seq [OPTION]... FIRST INCREMENT LAST. INCREMENT в средине!!! Несмотря на логику рекомендую.

IFS=$'\n'
for i in $(cat /etc/passwd); do
echo $i
done


Годный цикл для построчного чтения файла, но нужно помнить про разделитель IFS.

for i in "./space test/"*; do
echo $i
done


Годный цикл для перебора файлов, обратите внимание путь в кавычках, а звездочка - нет.

for i in 5 9 8 3;do
echo $i
done


Годный цикл с перечислятельством, для не очень больших количеств.

echo 1 2 3|for i in $(</dev/stdin);do
echo $i
done


Если цикл не работает - верните IFS=" "

Тройка упоротых конструкций:

for ((a=0,b=9;a<10;a++,b--));do
echo $a,$b
done

for ((a=1;a<2000;a+=a));do
echo $a
done

for i in $(j=10;while ((j--));do echo $j;done);do
echo $i
done


Последнюю сам придумал. Можно вообще на собесах применять с предложением упростить или объяснить.

Продолжение следует... © by Tagd Tagd

tags: #bash

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
544813
Как собрать все логи в один.

Иногда возникает задача найти что-то в логах ручками, без установки анализаторов логов.

Логов может быть много, некоторые сжатые - некоторые нет. Для работы со сжатыми файлами есть утилиты, начинающиеся на z. zcat, zgrep, zdiff...

ls -/bin/z* в помощь.

Для сборки логов в один я написал простой скрипт. Он выдает в stdout все логи, в порядке создания, сжатые разжимаются.

#!/bin/bash

test -z "$1" && echo "need log file" && exit

declare EXT=gz

for CUR_LOG in $(ls -tr "$1"*);do
PREFIX=z
if [[ "${CUR_LOG##*.}" != "$EXT" ]];then
PREFIX=
fi
${PREFIX}cat ${CUR_LOG}
done


Сохраняем его в файл sumlog.sh делаем файл исполняемым:

chmod +x sumlog.sh



sudo ./sumlog.sh /var/log/apache2/access.log


Лог файл без индексов и архивных расширений.

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

declare EXT=gz - сжатый файл.
ls -tr "$1"* спиcок файлов, отсортированный по времени (-t), в порядке убывания (-r)

Если у файла расширение не gz, то используем утилиту cat, если gz - zcat

А дальше обрабатывать вывод можно как угодно:

sudo ./sumlog.sh /var/log/apache2/access.log|grep ...
sudo ./sumlog.sh /var/log/apache2/access.log|awk ...
sudo ./sumlog.sh /var/log/apache2/access.log|sed ...


UPD: Тут пользователь Кирилл Катаевский (@rosskk) подсказал, как можно упростить:
#!/bin/bash
test -z "$1" && echo "need log file" ||zcat -f $(ls -tr "$1"*)


tags: #bash © by Tagd Tagd

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
1104915
Горизонт

Выходные заебись, никто не срёт в голову, все копят таски до понедельника и отдыхают... Потому что работая в найме ты видишь горизонт (пятницу), а дальше ебутся блохи в суматохе!

Но стоит тебе выйти из найма и начать своё дело, выходные дни странным образом «смещаются», ну как смещаются, ты уже не видишь горизонта событий до которого тебе нужно дойти, ты видишь какой-то кусок земли и лопату в руках.

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

Всегда было интересно когда учителя в школе говорили — ты закончишь под забором. Ты будешь продавать пирожки на базаре. Под каким блядь нахуй забором? Где ХУЙ написан? А пирожки я люблю, особенно на базаре! WTF???

Эт я к чему, если решил копать — не бросай, даже если каждый первый тебе говорит — что ты дурной пизды ребёнок…

Всё у тебя получится, просто копай дальше и не останавливайся! Получится! Равновесие мира. Балансировка нагрузки.

А кто дохуя пиздит и сеет в тебе сомнения, пусть идут — нахуй!

tags: #рабочиебудни

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
2414747
Ха! Не ждали? Ща будет кринж, но кринж просветит тех, кто глубоко копается в жопах линукса. Ну а если решил провести выходной на изи, оно нахуй тебе не всралось. Короче...

У кодировки ASCII есть особенность:

a -> 01*1*00001  A -> 01*0*00001
b -> 01*1*00010 B -> 01*0*00010
c -> 01*1*00011 C -> 01*0*00011
d -> 01*1*00100 D -> 01*0*00100
e -> 01*1*00101 E -> 01*0*00101
f -> 01*1*00110 F -> 01*0*00110
g -> 01*1*00111 G -> 01*0*00111
h -> 01*1*01000 H -> 01*0*01000
i -> 01*1*01001 I -> 01*0*01001
j -> 01*1*01010 J -> 01*0*01010
k -> 01*1*01011 K -> 01*0*01011
l -> 01*1*01100 L -> 01*0*01100
m -> 01*1*01101 M -> 01*0*01101
n -> 01*1*01110 N -> 01*0*01110
o -> 01*1*01111 O -> 01*0*01111
p -> 01*1*10000 P -> 01*0*10000
q -> 01*1*10001 Q -> 01*0*10001
r -> 01*1*10010 R -> 01*0*10010
s -> 01*1*10011 S -> 01*0*10011
t -> 01*1*10100 T -> 01*0*10100
u -> 01*1*10101 U -> 01*0*10101
v -> 01*1*10110 V -> 01*0*10110
w -> 01*1*10111 W -> 01*0*10111
x -> 01*1*11000 X -> 01*0*11000
y -> 01*1*11001 Y -> 01*0*11001
z -> 01*1*11010 Z -> 01*0*11010


Строчные и заглавные отличаются только шестым битом. Ну и для изменения регистра достаточно поменять этот бит.

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


Давай установим его, например в 0 или 1:

printf '%b %b\n' $( printf '\\%03o \\%03o' 65 $((65 ^ 32)) )  
printf '%b %b\n' $( printf '\\%03o \\%03o' 97 $((97 ^ 32)) )

printf '%s\n' $((65 ^ 32))
printf '%s\n' $((97 ^ 32))


Нихуясе? Да!

Позырить таблицу ascii: man ascii

А для изменения регистра в баше есть удобные конструкции:

( a='abc'; echo "${a^}" )   
( a='ABC'; echo "${a,}" )
( a='abc'; echo "${a^^}" )
( a='ABC'; echo "${a,,}" )


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

Да будет так!

tags: #bash #linux

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
187514
Практика, которая увеличит твою пенсию в 3 раза!

Есть такая практика «Помодоро», в общем это когда ты 25 минут усердно работаешь, потом 5 минут отдыхаешь и так по кругу.

Практика так сказать — ХУЙНЯ ПОЛНАЯ. Но если критикуешь, предлагай!

Оказывается давным-давно я случайно изобрел свою практику, которую в шутку назвал «Тюленинг».

Суть этой практики полная противоположность «Помодоро». То есть ты работаешь 5 минут и 30 минут отдыхаешь, повторяешь до бесконечности.

В чем плюсы «Тюленинга»?

Главная киллер фича — спустя пару часов нихуя не делания тебе становится скучно и возникает желание поработать. Это желание обычно появляется внезапно. Либо не появляется, тогда практикуешь «тюленинг» дальше.

И как только появилось желание, беги за комп и пили таски. Твой KPI будет прокачен на 100500%, мозг раскочегарен на азарте и в жопе будет приятный зуд.

Двухнедельный спринт закроешь буквально за полчаса. Без хуйни!

Думаешь это прикол такой? Неа! Сегодня лично провел эксперимент, практика работает — идеально!

В общей сложности я провалялся часов 8 + 30 минут ушло на работу + три раза пообедал. Завтра обязательно повторю!

Попробуй, тебе понравится!

#рабочиебудни


🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
1713634
- Ты такой душный...
- Не могли бы вы поподробнее разъяснить мне, в чём конкретно это выражается?


AMD E1-6010 6Gb Swap 0

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

Скрипт для тестирования циклов. Каждый цикл выводит два числа.

Первое - число секунд от начала цикла до вывода первого значения.

Второе - число секунд длительности цикла.

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

В остальных - через переменную MAX. Меняйте синхронно. Выводы будут в конце. Рекомендую рассмотреть код.

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

#!/bin/bash
declare -i MAX=5000000
declare -i MA1=MAX+1
declare -i Z0=0
declare -i Z1=1
declare -i P
declare LOG=./log.txt
declare LOOPNAME

clear
LOOPNAME=FOR0
P=0
SECONDS=0
for i in {1..5000000};do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=FOR1
P=0
SECONDS=0
for i in $(seq $Z1 $MAX);do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=FOR2
P=0
SECONDS=0
seq $Z1 $MAX|for i in $(</dev/stdin);do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=FOR3
P=0
SECONDS=0
for ((i=$Z0;i++<$MAX;));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=FOR4
P=0
SECONDS=0
for ((i=$MAX;i--!=0;));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=FOR5
P=0
SECONDS=0
for ((i=$Z1;i<$MA1;i++));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=WHL0
P=0
i=$Z0
SECONDS=0
while ((i++<$MAX));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

LOOPNAME=WHL1
P=0
i=$MAX
SECONDS=0
while ((i--));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS

gawk 'BEGIN{p=0
for(i = 1;i < 5000000;i++){
if(p==0)
print "GAWK 0";p++}
}'

gawk 'BEGIN{t=systime();p=0
for(i = 1;i < 5000000;i++){
if(p==0){
print "GAWK " systime()-t;p++}
}
print "GAWK "systime()-t}'


FOR0 14
FOR0 76
FOR1 11
FOR1 72
FOR2 10
FOR2 53
FOR3 0
FOR3 97
FOR5 0
FOR5 103
WHL0 0
WHL0 100
WHL1 0
WHL1 78


--- Я немного отделил, поскольку gawk не совсем bash, но привел для примера.

GAWK 0
GAWK 2 (тут реально 1.6) но баш оперирует целыми.


Выводы:

1. Самый быстрый - FOR2 for in (seq)

2. Самый медленный - FOR5 (сишный классический)

3. Несмотря на небольшие разницы в скорости выполнения скорость циклов соизмерима.

4. Циклы for in - ВНАЧАЛЕ получают полный список значений (в памяти) потом быстро его перебирают.

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

4.2 У этих циклов может быть большая задержка на инициализацию цикла. Это может быть критичным - если сам цикл большой, но очень часто происходит прерывание цикла в самом начале.

5. awkgawk самый медленный awk) значительно быстрее bash. Если скорость в приоритете - используйте его.

6. Цикл FOR0 вообще нежелательно применять, постокольку пределы цикла и инкремент нельзя задать переменными. только константы. Но сам конструкт {1..5} применять можно и даже нужно в подстановках (но не циклах). Например: ls text{9..27}.txt.

7. Главное помнить, что скорость выполнения определяется не скоростью самого цикла, а оптимизацией его тела.

Продолжение следует...

tags: #bash © by Tagd Tagd

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
11377
Сегодня разберем, чем отличаются различные циклы при работе с файлами.

#!/bin/bash
seq 1 5 >file.txt

for i in $(<file.txt);do
echo $i
read -p 'press ENTER'
done
echo ---
while read i;do
echo $i
read -p 'press ENTER'
done <file.txt
rm file.txt
#--


Сохраняем в файл loop3.sh

chmod +x loop3.sh


Создаем файл из пяти нумерованных строк.

seq 1 5 > file.txt


Блок for: читаем файл, и выводим построчно. После каждой строки жмем ENTER для продолжения.

Блок while - тело цикла - один в один.

Запускаем: ./loop3.sh

1
press ENTER
2
press ENTER
3
press ENTER
4
press ENTER
5
press ENTER
---
1
3
5


Часть срок второго цикла потерялась. ENTER нажимать никто не просил.

Все дело в том, что циклы работают принципиально по-разному.

Цикл for in сначала вычисляет/считывает все значения для перебора в память, потом начинает с ними работать.

Цикл while(until) читает последовательно, по одному значению. Мало того в данном случае цикл работает НЕ С ФАЙЛОМ НАПРЯМУЮ, а с stdin, (куда мы перенаправляем файл) поэтому любое чтение stdin приводит к чтению записи файла. Результат вы видели.

Продолжение следует...

tags: #bash © by Tagd Tagd

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
73711
This media is not supported in your browser
VIEW IN TELEGRAM
Всех с пятницей!

Проект Linux Factory большинству прям зашёл!

😲 На этом хорошие новости заканчиваются.

Потому что через несколько дней перестают действовать летние скидки и ценник для новеньких улетает в космос (в 2 раза).

Но ты еще можешь успеть запрыгнуть в последний вагон.

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

Короче просто напоминалка.

А кто уже в LF, не забудь продлить членство, в боте есть кнопочка — Продлить подписку.

Хороших тебе предстоящих выходных и береги себя!
Please open Telegram to view this post
VIEW IN TELEGRAM
213012
Ну вот и отгуляли лето, впереди новый учебный год, подъемы в 6 утра и ожидание выходных. Но есть и плюсы, хотя…

Ладно, сегодня я тебе принес WatchYourLAN.

Эта хуёвина представляет собой лёгкий сетевой сканер с веб-мордой.

На днях выкатили вторую версию.

Основные фишки:

- Если в твоей сети появился пидор, она тебе сообщит
- Отправляет данные в графану через InfluxDB2

Ради прикола взгромоздил я на малинку WatchYourLAN. Завязал на графану и alertmanager и теперь получаю в телегу алерты, если в сети зарегистрировалось новое устройство.

Охуенно! Чем бы дитя не тешилось.

Запускается прям с докера одной командой:

docker run --name wyl \
-e "IFACES=$YOURIFACE" \
-e "TZ=$YOURTIMEZONE" \
--network="host" \
-v $DOCKERDATAPATH/wyl:/data/WatchYourLAN \
aceberg/watchyourlan:v2


Не забываем забить свои переменные. На вебморду можно попасть так:

< IP >:8844


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

Официальная репка на гитхабе тут

tags: #utilites

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
84818
Когда собирался писать об этом операторе на ум пришла считалочка, которой меня научили в пионерском лагере.

А поскольку я сейчас не матерюсь, чтоб никто не догадался, перейду на старославянский алфавит.

Итак: Шёл Хер по херу, встретил Хера на херу, взял Хер Хера за хер, и к херам закинул нахер.

Вот, а сейчас говорят, что пионеров ничему хорошему не учили... exec.

Есть два варианта использования:

1. exec command — билет в один конец. Для чего это нужно я так и не понял, может умные в комментах напишут. Перед выполнением команды, bash фактически завершается, управление передаётся команде. И все...

пример:

exec echo 123 — результат очень красочный. Такой же, как и с любой другой командой.

2. Перенаправление. Это штука крайне нужная и очень понятная. В других, нормальных ЯП она называлась бы open.

В Basic open "filename.txt" for input as #3
В bash exec 3<fileneme.txt
В Basic open "filename.txt" for output as #4
В bash exec 4>filename.txt
В Basic open "filename.txt" for append as #5
В bash exec 5>>filename.txt
В Basic open "filename.txt" for random as #6
В bash exec 6<>filename.txt

Приведу несколько полезных примеров

exec 2>/dev/null — все сообщения об ошибках отправить по пути, указанному в считалочке.

На код ошибки (типа errorlevel) это не влияет.

exec 1>filename.txt все сообщения, кроме ошибок отправить в файл.
exec 1>filename.txt 2>&1 все сообщения, включая ошибки отправить в файл.

Стоп-стоп. Откуда взялся &? Легко запомнить. Это костыль. Если вы не укажите &, сообщения попадут в файл с именем "1".

Все помнят, что 0=/dev/stdin 1=/dev/stdout 2=/dev/stderr. Остальные 3-9 можем использовать по собственному усмотрению.

Пример:

#!/bin/bash
seq 1 3|tee 1.txt > 2.txt
exec 3<1.txt
while read -u3 L1;do
exec 4<2.txt
while read -u4 L2;do
echo $L1 $L2
done
done


seq — создаем два файла, по три строки в каждом
exec 3<1.txt - открываем файл для чтения с дескриптором 3
read -u3 L1 читаем из файла с дескриптором 3. Дальше все аналогично.

Если нужно закрыть 4, например, дескриптор за ненадобностью exec 4>&-

man tee seq
help while read exec


tags: #bash © by Tagd Tagd

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
103019
После того как я проверил на себе Suicide Linux, я всё проебал. Пришлось с нуля настраивать всё окружение.

В процессе настройки решил отказаться от zsh + oh-my-zsh и жить на чистом bin/bash.

Через пару дней понял, что мне не хватает «авто-подсказок». В zsh я использовал плагин zsh-autosuggestions, но а как быть с чистым башем? Там плагин через .bashrc хуй поставишь.

И нашел я BLE.sh (Bash Line Editor). Звучит же?

Софтина полностью меня устроила, даж красненьким подсвечивает команды когда я хуйню пытаюсь ввести.

Устанавливается просто, клонируешь себе из гит репки файлы, компилируешь и в ~/.profile подключаешь. Выглядит это так:

git clone --recursive https://github.com/akinomyoga/ble.sh.git
make -C ble.sh
echo "source ble.sh/out/ble.sh" >> ~/.profile


Перезапускаешь сессию и получаешь подсказки по командам, которые ты ранее вводил.

Бле так Бле!

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

Но как быть со сфистоперделками и новогодними ёлками? Там оформление добавить, нерд-фонты и т.п.

Ха, на этот случай есть штука oh-my-posh.

Ставится так:

curl -s https://ohmyposh.dev/install.sh | bash -s

mkdir ~/.poshthemes
wget https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest/download/themes.zip -O ~/.poshthemes/themes.zip
unzip ~/.poshthemes/themes.zip -d ~/.poshthemes
chmod u+rw ~/.poshthemes/*.omp.*
rm ~/.poshthemes/themes.zip


Дополнительно ставишь темы оформления. Ну и потом не забываем всё это дело подключить в ~/.profile

eval "$(oh-my-posh --init --shell bash --config ~/.poshthemes/capr4n.omp.json)"


В ключик --config вставляем название понравившейся темы. Ну и оболочку указываем, я естественно захуярил туда bash.

Темы визуально позырить тут. Итог ты можешь посмотреть на скриншоте к посту.

А завтра покажу как для всего этого дела ещё одну очень полезную штуку прикрутить.

tags: #utilites #рабочиебудни #bash

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
127014
Привет. В дополнение к предыдущему посту про свистоперделки.

Чтобы каждый раз не вводить такую дичь:

ssh -i ~/.ssh/id_rsa user@xxx.xxx.xxx.xxx


Ключик можно автоматически добавлять в ssh-agent и тогда подключение будет выглядеть так:

ssh user@xxx.xxx.xxx.xxx


Чтобы это провернуть, прописываем в ~/.profile

if [ -z "$SSH_AUTH_SOCK" ]; then
eval $(ssh-agent -s) > ~/.ssh/ssh-agent
fi

ssh-add ~/.ssh/gitlab_rsa
ssh-add ~/.ssh/production_rsa
ssh-add ~/.ssh/home_rsa


Первый блок проверяет запущен ли SSH агент, а если нет — запускает его.

Второй блок добавляет нужные ключи в агент. Посмотреть все ключи в агенте можешь командой ssh-add -L, а удалить всё из агента можно командой ssh-add -D.

Вот и вся наука. Ну а теперь интерактивная часть.

Ну а чтоб тебе не скучно было, можешь написать башник и скинуть в комменты, который автоматически пробегается по всем ключам в папке ~/.ssh и добавляет их в агент.

Но учти что в этой папке могут быть косячные ключи, ключи с неправильными правами, да и всякие файлы вида config, known_hosts. Короче потребуется работа с эксепшенами.

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

tags: #utilites #рабочиебудни #bash

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
143512
Здрасти приехали, пятница!

Частый вопрос который задают ребята с проекта Linux Factory:

Как в gitlab registry чистить докер имейджы, а то там такая пиздец блядь каша после экспериментов.


В gitlab есть встроенная херня, которая находится в Settings → Packages & Registries → Container Registry. Заранее не забудь выбрать нужный проект.

Там есть раздел: Cleanup Policies, в нём нажимаешь кнопку Set cleanup rules иии видишь еще кучу какого-то гавна.

Короче:

Run cleanup — выбираешь как часто запускать зачистку

Keep these tags — теги которые не нужно зачищать

Remove these tags — теги которые будем удалять

Remove tags older than — ну тут ежу понятно

В этих штуках работают регулярные выражения, примеры этих регулярок можешь глянуть тут.

Еще момент, если заполнить Keep these tags, то это даст протекцию тегам и даже если их прописать в Remove these tags имейджы не будут удалены.

Заполняешь, сохраняешь и оно автоматически будет тебе все подчищать.

Дополнительные варианты зачистки:

- удаляешь мышкой в UI самого гитлаба
- удаляешь через API самого гитлаба (например баш скриптом)
- используешь утилиты типа regclient или docker-gc

Такие дела, надеюсь было полезно. Давай, хороших тебе предстоящих выходных и береги себя!

UPD: от Малахитовая Штукатурка

а еще можно так зачистить:
sudo gitlab-ctl registry-garbage-collect -m



tags: #devops

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
134717
Еще раз привет. В последнее время многие столкнулись с проблемой при запуске пайплайнов в гитлабе.

Требуется какая-то ебучая Verify my account, квест который не так просто пройти. Но есть способ это обойти, спасибо за наводку Akhmed Gvashev.

Пиздуем в Settings → CI/CD → Runners → Instance runners и отключаем Enable instance runners for this project.

Всё, дело в шляпе. А дальше регистрируешь свои локальные раннеры и запускаешь пайплайны хоть до посинения.

Пользуйтесь!

tags: #devops

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
135223
Обычно bash используется для неинтерактивного выполнения скриптов. А что делать, если хочется чего-то интерактивного?

Можно использовать оператор read. По умолчанию он читает ту херню, которую пользователь пишет на клавиатуре. Ну, не всю херню.

В общем, тут возникают проблемы. Даже не так. ТУТ ВОЗНИКАЮТ ПРОБЛЕМЫ.

Проблем несколько, и они нихрена не решаются простыми способами:

1. Только простые клавиши генерят одиночные коды типа буквы, цифры, печатные символы.
2. Стрелки, HOME, END... и особенно функциональные клавиши (F1-F12) генерят многобайтные коды.
3. Клавиши TAB ENTER SPACE вообще нихрена не выдают.
4. Коды нажатых клавиш зависят от терминала, который у вас эмулируется.
5. Очень много клавиш используется в качестве "горячих", поэтому их обработка производится раньше, чем их обработает bash.

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

А если похожи на меня - приведу функцию, которая помогает минимизировать проблемы.

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

Понятней.

Программа более-менее обрабатывает совместное нажатие CTRL+, ALT+. Не обрабатывает нажатия нескольких клавиш.


#!/bin/bash

function GET_KEY(){
declare K1 K2 K=
declare -i i
read -rsn1 K1;read -rsn4 -t 0.001 K2
if [[ "$K1" != $'\x1b' ]];then
K2=
fi
K1="${K1}${K2}"
i=${#K1}
while ((i--));do
printf -v K2 "%02X" \"${K1:$i:1}\"
K=${K2}${K}
done
printf "%s" $K
}
clear
echo "TERMINAL="$TERM
KEY=1
while [ "$KEY" != "" ];do
KEY=$(GET_KEY)
echo $KEY
# echo -e "\x$KEY"
done


сохраните в файл key2hex.sh

chmod +x ./key2hex.sh
./key2hex.sh


Под закрытым текстом объяснения для начинающих.

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

read -rsn1 K1;read -rsn4 -t 0.001 K2 считывает 1 символ, потом возможно еще 4, но с малым временем ожидания. Если символ многобайтный - в буфере он уже есть.

Если символ начинается не с кода
1b (ESC) он должен быть однобайтным.
${#K1} -число символов в строке.

Далее в цикле
while ((i--));do посимвольно преобразуем строку в hex, накапливая в переменной K

echo -e "\x$KEY" команда перевода hex в char привожу для примера.

Для прикола попробуйте выполнить программу в разных терминалах (LxTerminal и tty1) и посмотреть на
F5.

Поясню, в tty1 можно перейти из GUI
CTRL+ALT+F1, а вернуться обратно обычно ALT+F7

Ну, или не
F7. посмотреть, куда возвращаться можно командой w . Даже маленькие разберутся.

В общем, терминал(ы) - штука сложная. И тот только теперь я начал немного понимать, нахрена нужна библиотека ncurses.

help read printf
man w printf


tags: #bash © by Tagd Tagd

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
5315
Здрасти. Еще один частый вопрос с проекта Linux Factory:

Я собрал докер имейдж, а контейнер вечно в ребуте либо вообще не запускается, чо делать и как отлаживать?


Давай симулируем ситуацию и попробуем что-то с этим сделать.

Для начала соберем имейдж, это будет простой nginx + свой конфиг, который будет копироваться с локальной машины в имейдж.

Создаем на хостовой машине пару файлов:

Dockerfile:

FROM nginx:latest
WORKDIR /etc/nginx
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]


nginx.conf

user  nginx;
worker_processes 1;

events {
worker_connections 1024;
}

http {
server {
listen 80;
server_name localhost;

location / {
return 200 'Hello, Docker!'
add_header Content-Type text/plain;
}
}
}


Собираем имейдж:

docker build -t my-nginx .


Ждем, на экране бежит куча всякого непотребства. Это нормально. Ждем…

Проверяем:

docker images


Ага, все ок, выплюнуло что-то вроде:

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
my-nginx latest b844ef77daa3 33 seconds ago 188MB


Запускаем:

docker run -d -p 80:80 my-nginx


Проверяем:

docker ps


Хуй там плавал. Ничо не стартануло… ошибок нет, куда смотреть?

Если контейнер вообще не запускается, то для начала смотрим логи:

1. Узнаем состояние контейнера:

docker ps -a


Видим хуй с маслом: Exited (1) 4 minutes ago

2. Смотрим логи:

docker logs --follow <id or name>


В <id or name> подставляем айдишник либо имя контейнера:

В логах видим ошибку:

 invalid number of arguments in "return" directive in /etc/nginx/nginx.conf:15


Вот! С ней уже можно работать. Получается мы посмотрели логи, даже для незапущенного контейнера. Пиздуем в nginx конфиг и видим, что в 14й строке проебали точку с запятой.

Дополнительно можно посмотреть коды выхода:

docker inspect <id or name>


Например, если код выхода ExitCode = 137, значит не хватило ресурсов, подкинь памяти и все взлетит. Наверное…

Это основные моменты отладки.

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

docker exec -it <id or name> bash/sh


Подставляешь id/name контейнера и выбираешь шелл, частенько bash и коробки не установлен, поэтому как вариант запускаешь sh.

А для визуализации слоев используем утилиту dive

Установка dive:

DIVE_VERSION=$(curl -sL "https://api.github.com/repos/wagoodman/dive/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
curl -OL https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.deb
sudo apt install ./dive_${DIVE_VERSION}_linux_amd64.deb


Открываем имейдж на анализ:

dive <id or imagename>


Подставляем id или имя — ИМЕЙДЖА (не контейнера)

Смотрим, охуеваем, закрываем.

Еще можно глянуть конкретный файл в контейнере:

docker exec -it <id or name> cat /etc/nginx/nginx.conf


Либо скопировать его себе на локальную машину:

docker cp <id or name>:/etc/nginx/nginx.conf /tmp


Поправить и скопировать обратно в контейнер:

docker cp /tmp/nginx.conf <id or name>:/etc/nginx/nginx.conf


Перезапускаем контейнер с новым конфигом:

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


docker exec <id or name> nginx -s reload


Такие дела! Если знаешь еще хаки и способы отладки контейнеров/имеджей, пиши в комменты, будет полезно!

tags: #devops #debug #docker

@bashdays @gitgate
257012