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

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

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

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Download Telegram
Время неумолимо. Кажется ещё сегодня пятница, а уже на горизонте маячит понедельник.

Привет. Сегодня про сигналы и как с ними взаимодействовать через bash скрипты. Да те самые SIGINT, SIGTERM, SIGKILL.

Вероятно ты про них слышал. Ладно, скажу больше, ты даже ими пользуешься. Банально нажимая CTRL+C, ты посылаешь сигнал SIGINT. Этот сигнал позволяет скрипту корректно завершить работу.

Если прервать скрипт по нажатию CTRL+C, то вернется код ошибки 130 (echo $?). А откуда взялось 130?

Потому что если процесс завершается из-за полученного сигнала, он возвращает значение, которое является суммой 128 и кода сигнала. SIGINT = 2, итого получаем 128+2=130.

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


Для обработки сигналов, в Bash можно использовать обработчики. Спасибо, капитан!

Пример обработки сигналов:

#!/bin/bash

# Функция для обработки SIGINT (Ctrl+C)
sigint_handler() {
echo "Caught SIGINT (Ctrl+C). Exiting..."
exit 1
}

# Функция для обработки SIGTERM
sigterm_handler() {
echo "Caught SIGTERM. Exiting..."
exit 1
}

# Установка обработчиков сигналов
trap sigint_handler SIGINT
trap sigterm_handler SIGTERM

# Главный цикл
while true; do
echo "Script is running..."
sleep 1
done


Скрипт запустит бесконечный цикл. Если нажать CTRL+C, сработает хендлер sigint_handler и скрипт завершится с кодом 1. Видишь, мы поменяли дефолтный код 130 на 1.

А хендлер sigterm_handler сработает в том случае если скрипт убить через kill -TERM PID. Процесс так же завершится с кодом 1.

Таким образом в хендлерах мы можем построить любую логику, например вывести слово «хуй». А если выпилить exit 1, то по нажатию CTRL+C скрипт вообще никак не отреагирует на завершение и продолжит выполняться дальше. БЕСКОНЕЧНО!

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

SIGTERM
= Этот сигнал обычно отправляется операционной системой при попытке завершения процесса. Обработка SIGTERM позволяет скрипту завершить работу безопасно и корректно освободить ресурсы.


Да, есть еще SIGKILL, а вот его обработать не получится. Он нужен для крайних мер. Например, если из скрипта выше убрать exit 1, то бесконечный цикл удастся завершить только через SIGKILL (kill PID). Ну ту тоже логично, всё продумано.

Но я уверен, что и SIGKILL можно перехватить, правда пока лень с этим разбираться, всяко придется в ядро лезть в strace ковыряться и возможно что-то патчить.

Существуют и другие сигналы SIGHUP / SIGUSR1 / SIGPIPE / SIGCHLD и т.п. но сути это не меняет, пост про перехват сигналов.

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

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

Всех с пятницей, хороших предстоящих выходных и береги себя! Увидимся!

tags: #bash #linux

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
105
О чо на почту сегодня прилетело. Вчера в чатике видел, ссылка уже пролетала от Константина, но чет значения не придал. А после этого письма придал.

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

Короче под капотом Debian 12 или Windows Server 2016 (14393.6709) Длительность онлайн сессии 15 минут.

С докой по сервакам, можешь ознакомиться здесь, там с картинками и всеми подробностями.

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

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

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

Выжимка из доки:

Мы создали ультимативное решение для частых задач в жизни каждого пользователя сети интернет, включая вашу потребность в:

- дополнительном рабочем столе
- виртуальном браузере для открытия любых веб-сайтов вне личного ПК
- сервере для тестирования той или иной сомнительной программы
- проверке собственного ПО и скриптов в виртуальной среде
- тестировании консольных команд
- проверки доступности вашего сайта или приложения
- тестировании сайтов, приложений, программ в виртуальной среде
- запуске социальной сети, мессенджера или сайта в режиме полного инкогнито
- способе удалить папку system32 без риска для здоровья

tags: #services

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
87
Зима меня что-то прям знатно так подзаебала, тысяча одёжек, реанимация автомобиля в -40, то дождь за шиворот, то метель в морду лица. Всё же летом как-то попроще мне кажется, хотя и жара сильно изматывает. Нежные мы стали с этой удалёнкой, жёсткая зависимость от зоны комфорта. Ладно…

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

Можно ли после запуска скрипта, перенаправить STDOUT и STDERR в другое место, не останавливая сам скрипт/процесс? Ответ ты и сам знаешь, конечно можно! Ща покажу как.

Чтобы все стало понятным, берем для эксперимента такую команду и запускаем ее в терминале.

tail -f /var/log/auth.log &


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

Как только в файле auth.log появляются новые записи, оно начинает нам срать в терминал, мешая дальнейшей работе. Хоть задача и запущена в фоне, но активно работает с текущим tty и stdout.

Чтобы нам все это дело отправить в dev/null не останавливая фоновую задачу/скрипт. Проделываем следующий трюк:

ps aux | grep tail


Узнаём PID процесса, в моём случае это 1327692, далее смотрим файловые дескрипторы этого процесса:

ls -l /proc/1327692/fd


Получаем нечто подобное:

0 -> /dev/pts/1
1 -> /dev/pts/1
2 -> /dev/pts/1
3 -> /var/log/auth.log


Знакомо? stdout = 1 (поток вывода), stderr = 2 (поток с ошибками) и т.п. Уже наталкивает на мысль чо будем делать? Нет? Поехали дальше.

Теперь каким-то образом, надо зареврайтить это говнище в dev/null. Для этого будем использовать утилиту gdb, она обычно идет в коробке либо ставится через апт-инсталл.

gdb - отладчик для программ, написанных на Си. Отладчик позволяет выполнить программу пошагово, посмотреть значения всех переменных на каждом из этапов выполнения, а если это необходимо, то и дизассемблировать код и посмотреть состояние регистров процессора.


Запускаем кракена:

gdb -p 1327692 /usr/bin/tail


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

Всё, теперь ты находишься в «хакерской» оболочке (gdb), начинаем реврайтить говнище. Вводим такие команды:

p (int) dup2((int) open("/dev/null", 0), 1)
p (int) dup2((int) open("/dev/null", 0), 2)


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

$1 = 1
$2 = 2


После этого закрываем gdb:

detach
quit


Вот и всё. Говнище из auth.log перестало выводиться на экран, хотя фоновый процесс продолжает работать. Смотрим что у нас получилось:

ls -l /proc/1327692/fd


И видим что наш реврайт сработал:

0 -> /dev/pts/1
1 -> /dev/null
2 -> /dev/null
3 -> /var/log/auth.log
4 -> anon_inode:inotify
5 -> /dev/null
6 -> /dev/null


Теперь stdout(1) и stderr(2) смотрят в dev/null, собственно этого мы и желали добиться.

Разберем команды gdb

«p» (print), выводим результат команды на экран.

«dup2», дублирует файловый дескриптор. Первым аргументом идет файловый дескриптор, который нужно продублировать. Второй аргумент это новый файловый дескриптор, который нужно использовать.

Все это дело приводим к типу Int, хотя раньше и без этого всё отлично работало, видимо что-то поменялось.

И получается такое: Команда сначала открывает файл dev/null, затем дублирует его файловый дескриптор, а затем перенаправляет stdout в этот файл. Прозрачно? Прозрачно!

Вот такие пироги. Надеюсь было интересно.

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


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

tags: #bash #linux

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
158
🅰️🅰️🅰️
7 причин, почему коты делают «тыгыдык»

Вчера наконец-то собрался силами и добрался до иммобилайзера, всего-то понадобилась неделя. За 5 дней я знатно себе так жопу отморозил без автозапуска. Починил, правда палец сука порезал. Ну это капля в море, на фоне всратых сервисов и неоправданных счетов за ремонт.

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

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

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

Есть у меня сервер, на нем крутится самописная bastion оболочка. Как это работает:

1. Цепляюсь в bastion
2. В консоль вываливает список серверов
3. Коннект к серверу ssh <index>

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

Bastion я написал, впечатлившись этим решением от ITSumma, которое называется isolate.


Как я подключался раньше

> ssh user@bastion.bashdays.com


Как я подключался потом

> export alias bas="ssh user@bastion.bashdays.com"
> bas


Как я подключаюсь сейчас

> alt+b


Прям эволюционный роадмэп. Интересно, какая стадия будет следующей. Итак, повесил я подключение на хоткей, стало довольно удобно. Только открылась консоль, бряк alt+b и я уже внутри.

Хоткей вешал так, добавив это в .bahsrc:

bastion() {
echo "connect to bastion server"
ssh -t qa@bastion.bashdays.com 'reset;bash'
}

bind -x '"\eb": bastion'


«ёб» в последней строчке, это как раз клавиша alt+b в кодах ANSI escape sequences. Если нужны другие кнопки, го в гугол, там этого полно.

«-t» создаёт псевдотерминал, чтобы команды вводились на сервере, а не в текущей оболочке.

А reset;bash понадобился, чтобы победить проблему с отображением команд, которые вводишь. Если убрать это хак, то когда будешь что-то вводить в консоли, это не будет отображаться на экране.

В zsh я на быструю руку попытался подобное провернуть, оно даже подключается, но терминал впадает в бэдтрип Read Only, какая-то абстракция с псевдотерминалами. Пока руки не дошли докопаться до сути. Но если у тебя получится это завести, пиши в комменты, сделаешь ОЧЕНЬ нужное и доброе дело.

Вот мои наработки для .zshrc:

bastion() {
echo "connect to bastion server"
ssh -tt user@bastion.bashdays.com
}

zle -N bastion
bindkey '\eb' bastion


Так, совсем забыл про котов, эту тему обязательно нужно обсудить. И дело тут не в блуждающем нерве.

На хоткеи ты можешь повесить любую команду, любой комбайн, который только заблагорассудится, например можешь запускать vim или редактирование файла /etc/hosts. Короче изучай.

И давай краба, жду тебя в комментах!

tags: #bash #linux

@BASHDAYS
Please open Telegram to view this post
VIEW IN TELEGRAM
147
Что случится, если отключить буферизацию

Привет. Чтобы результаты вывода софта/скриптов отображались без задержек в реальном времени — отключи буферизацию.

На практике, эффект буферизации незаметен, либо софт/скрипты и так работают в реальном времени.

Распространенный случай.

Ты всяко с таким сталкивался: запустил программу, которая пишет данные в файл. И пока софтина не отработает, файл с результатами, визуально пустой. Грыжа!

Но хочется же в реальном времени наблюдать, как файл заполняется и делать выводы. А что если софтина работает 10 часов? А выхлоп нужен вчера?

/usr/local/sbin/script.sh &> bashdays.log


Проблема этого условного скрипта, в том, что файл bashdays.log создаётся только, после выполнения скрипта. Как отслеживать прогресс?

Воспользуйся отключением буферизации!

Всё делается с помощью утилиты stdbuf. Утилита изменяет способ буферизации программ.

stdbuf -oL /usr/local/sbin/script.sh &> bashdays.log


Ключ «o» взаимодействует со стандартным выводом (stdout). А аргумент «L» означает Line buffered, то есть, буферизация по строкам.

По умолчанию при перенаправлении в файл, стандартный вывод (stdout) полностью буферизуется и записывается в файл после сброса.


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

Одно из применений stdbuf:

stdbuf -oL nohup /usr/local/sbin/script.sh &> bashdays.log


Если закрыть вкладку с сессией, скрипт продолжит работу.

Либо можешь воспользоваться утилитой script:

script -c <PROGRAM> -f bashdays.txt


Ключ «f» выполняет аналогичную функцию, после каждой операции, запускается flush, запись на диск.

На этом смею откланяться, хорошего дня/вечера!

tags: #bash #linux

@BASHDAYS
121
Охохо, привет! Размазывать бытовуху не буду, сразу к делу. В bash есть офигительная команда, называется она «readonly». С помощью неё ты сможешь защитить любую переменную от изменения. Получается этакая константа, которую довольно сложно перезаписать.

И не дай бог кто-то решит ее перезаписать, получит в лоб ошибкой:

bash: VAR: readonly variable


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

Оказалось, всё очень даже очевидно. Этот скуфяра мало того что применил ООП в скриптах (это пиздец), так еще и воспользовался «readonly». Спасибо тебе дорогой друг. Надеюсь на новом месте, тебе такого с кубернейтсами не позволяют делать. Диверсант блядь.

Еще раз, НЕ НУЖНО УСЛОЖНЯТЬ, ООП и выкрутасы оставь для программистов.


Ладно. Теперь про «readonly». Если не можем победить, значит нужно изучить и победить. Это как в анекдоте 18+:

Я ебу все что движется, а всё что не движется, я двигаю и ебу.

Поехали двигать!

Переменная защищается так:

readonly VAR=1234


Если её попытаться переопределить, то моментально отправляешься в пешее эротическое. Возникает логичный вопрос — как её откатить обратно и сделать нормальной переменной?

В голову приходит логичный ответ, сделай так:

unset VAR


А вот и нет! Сразу получишь хуем ошибкой по башке: bash: unset: VAR: cannot unset: readonly variable.

Хм… интересное кино. А чо делать? Не использовать «readonly»! Ну а если пришлось с этим столкнутся, придется использовать древнюю магию. Мы её кстати недавно использовали в этом посте.

Чтобы заансетить константу, открываем «Ящик Пандоры»:

gdb -ex 'call (int) unbind_variable("VAR")' --pid=$$ --batch


Если получил $1 = 0, значит всё прошло успешно.

Такими консервированными переменными хорошо манипулировать во всяких конфигах, например в .bashrc и т.п. Если кто-то захочет что-то переопределить, у него ничего не получится. Защита от дурака. Но помни, что древняя магия gdb может не сработать на этом проклятии, если ты не root.

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

В общем изучай. Хороших тебе предстоящих выходных и береги себя!

tags: #bash #linux

@BASHDAYS
140
Любишь унижения? Рекомендую!

Здрасти. В Linux есть возможность включить «оскорбительный режим», который работает из коробки без установки дополнительного шлака.

Суть этого режима: при использовании команды sudo, если ты ввел неправильный пароль, система унизит тебя.

Для включения, добавь в файл /etc/sudoers (либо в /etc/sudoers.d/fuck.conf) такую строчку:

Defaults insults


А после этого попробуй выполнить от пользователя:

sudo apt update


И введи неправильный пароль. Результаты бывают разные:

Take a stress pill and think things over.
You fucking stupid shit!
My mind is going. I can feel it.
Realy? Are you on drugs?


Все эти фразочки зашиты в библиотеке /usr/libexec/sudo/sudoers.so. Но на английском не интересно. Поэтому можно выводить своё сообщение через такой хак:

Делается так:

Defaults  badpass_message="Еще одна попытка и я тебя выебу!"


Предварительно закомментируй Defaults insults. Можно конечно пересобрать sudoers.so со своими фразами, но геморно. Ну либо пропатчить прям этот файл через HEX редактор.

Уверен есть способ запустить такой Bash скрипт по триггеру:

#!/bin/bash

messages=("Неверный блядь пароль! У тебя палец сломан?"
"Еще одна попытка и я тебя выебу"
"Может, тебе стоит попробовать свою девичью фамилию?")

echo "${messages[$RANDOM % ${#messages[@]}]}"


Изучай!

tags: #bash #linux

@BASHDAYS
213
Кто сеет ветер, тот пожнет бурю

А давай пожнем бурю! Как мы любим. Недавно я писал пост про readonly и переменные. Ну дак вот, заансетить переменную можно и другим способом.

Не спеши переключать канал, будет ОХУЕННО интересно.

Bash теперь не менее опасен чем perl.


ctypes - это не просто очередная скриптовая библиотека, это штука позволяет вызывать функции из shared библиотек на СИ, прямо из bash скриптов. Охуеть да?

Можно сказать это внештатный модуль для Bash с огромным функционалом. Где не справился Bash, справится Bash + ctypes.

Могу сравнить это с паскалем и вставками на ассемблере, ох любил я это дело в школе. Учительница по информатике плакала кровавыми слезами, когда читала мои исходники. А потом вообще просто начала ставить пятерки, чтобы не видеть моих брейнфаков.

Давай попрактикуемся. Собираем модуль ctypes.

git clone https://github.com/taviso/ctypes.sh.git
cd ctypes.sh
./autogen.sh
./configure
make
sudo make install


По умолчанию вся эта байда ставится в папку /usr/local/bin и /usr/local/lib. Но при сборке путь можно изменить через параметр PREFIX=$HOME make install.

Так собрали, установили. Чо дальше? А дальше пишем самую простую so библиотеку:

#include <stdio.h>

void hello_bashdays() {
printf("Hello, Bashdays!\n");
}


Компилируем:

gcc -shared -o /tmp/bashdays.so bashdays.c


На выходе получаем готовый файл bashdays.so с функцией hello_bashdays. Проверяем какие символы доступны в скомпилированной библиотеке:

nm -g /tmp/bashdays.so


Команда nm покажет, все глобальные функции и переменные, которые доступны в библиотеке bashdays.so. Мне выдало такое:

w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w __cxa_finalize@GLIBC_2.2.5
w __gmon_start__
0000000000001119 T hello_bashdays
U puts@GLIBC_2.2.5


Ок. Всё верно! Символ T перед названием функции, означает, что функция глобальная. А символ U (puts) = что эту функцию можно вызвать из вне.

Ну и теперь с помощью ctypes мы можем вызвать эту функцию из Bash скрипта.

#!/bin/bash

source /usr/local/bin/ctypes.sh

dlopen "/tmp/bashdays.so"
dlcall "hello_bashdays"


Опа нихуя! На экран получаем результат выполнения СИ функции hello_bashdays. Собственно Hello, Bashdays!

И это всего лишь верхушка айсберга, если копнуть глубже…

Вот несколько отзывов на ctypes:

- Это отвратительно
- Это должно прекратиться
- Вы зашли слишком далеко
- Это шутка?

Вот такие интересные штуки существуют. Надеюсь тебе понравилось. Теперь ты знаешь как собирать shared so файлы и легко вызывать от туда функции.

Аа забыл, как заансетить переменную:

readonly VAR=123
source /usr/local/bin/ctypes.sh
dlcall unbind_variable string:VAR


Вот и все. И никаких тебе танцев с gdb. Переменная VAR обнулена.

Примени это с умом, ведь на тёмную сторону перейти очень легко. Увы, но я уже там!

🌐 Страница проекта на github


tags: #bash #linux

@BASHDAYS
Please open Telegram to view this post
VIEW IN TELEGRAM
138
Кот насрал в макбук

Причем не «На», а конкретно «Вв». Сегодня снова про гавно и котов, которые выставляют айтишников на 200к рублей.

Сторис

С утра настраивал примитивный kubernetes кластер для клиента, пилил таску с ноута, сидя на унитазе. Ну а как, удалёнка, могу себе позволить. Жил бы один, вообщеб обратно в обезьяну эволюционировал.

Короче время дейлика с другим клиентом, бросаю открытый ноут в сортире на коврик, бегу к стационарному компу где установлен zoom. 15 минут слушаю очередную хуиту от лосей, проблема не у нас, а на серверах. Классика. По привычке — выгораю, шлю нахуй, реву.

Ну и вот!

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

Ноут который я бросил на коврик… Ему был произведен основательный апгрейд +100500 к бренду.

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

А новое и тёплое всегда безумно манит. Тем более присутствует интерактив — закрыть крышку. Зона комфорта. Ну ты и сам это прекрасно понимаешь.

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

Напомнил знакомого, который, любил гадить в лифтах. Сейчас кстати работает JAVA разработчиком. Тоже сеньор, лифты заменил на GIT репозитории. Забавно, но ситуация страшная.

Сначала комбик за 50к, потом стена и диван в зале, а сегодня макбук за 200к. Хотя сам кот стоил всего 5к. Сомнительно конечно вложение было. Что дальше, хуй знает. Снова выгорел, поревел…

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


Проанализировав произошедшее, в очередной раз убедился, что от apple и кубернейтсов одно зло. Linux / Windows / Android / Bash / Ctypes наше всё.

Таску в джире пометил как кот - Blocked, а ноут выставил на авито. Так что будь аккуратнее если решишь купить б/у железяку, возможно ранее в её красиво насрали проапгрейдили.

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

И всегда помни — даже если кот кастрирован, с его жопой ты ничего не сделаешь. Максимум сможешь провести ретроспективу по методологии «Scrum».

Говорят в айти охуенно весело. Справедливо!

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

@BASHDAYS
228
Есть такие команды, они выведут справку по утилите printf:

1. help printf
2. printf --help
3. env printf --help


НО. Каждая команда выведет свою версию справки (почти). То есть результат вывода будет отличаться в разных случаях. Не веришь? Попробуй сам.

В первом пункте с help printf всё понятно. Получишь некий огрызок, который трудно назвать страницей помощи. Да и во втором тоже самое.

В 1-2 вызывается именно встроенная утилита printf в оболочку Bash. А вот в третьем пункте, выведется достаточно внушительный хелп.

И этот внушительный хелп будет от схожей, внешней утилиты printf, которая располагается тут: /usr/bin/printf.

Посмотреть все варианты printf можно так:

type -a printf


На экран выведется список:

printf is a shell builtin
printf is /usr/bin/printf
printf is /bin/printf


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

Я очень редко читаю документацию таким способом, предпочитаю сразу загуглить. Ладно. Изучай.

tags: #bash

@BASHDAYS
58
Привет, я тут немного затроил, но без чтива вас не оставлю. Сегодня обсудим что делает kill -0 $pid в Bash скриптах.

В принципе логично, команда должна убить какой-то процесс. Но как мы знаем, сигналы начинаются с единицы (1) = SIGHUP, а тут какой-то странный нолик затесался.

Что забавно, в официальной документации и всяких манах информации по этому нулю очень мало.

В некоторых дистрибутивах, через man 2 kill можно получить такой ответ:

If sig is 0, then no signal is sent, but existence and permission checks are still performed; this can be used to check for the existence of a process ID or process group ID that the caller is permitted to signal.

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

Более подробно про сигналы я писал в этом посте


Давай к примерам:

sleep 120 &
pid=$!
kill -0 $pid && kill $pid
fg


1. Запускаем в фоне задачу sleep
2. Присваиваем переменной PID процесса
3. Проверяем, если процесс с $pid запущен, то убиваем его
4. Проверяем что процесс убит

Здесь мы с помощью нуля проверили наличие запущенного процесса и на возможность отправлять ему сигналы. Если всё ок, то отрабатывает команда kill $pid.

А если запустить так:

kill -0 $pid; echo "Exit status: $?"


Получим статус выхода. То есть процесс не запущен и можно смело выходить со статусом 1.

Про статусы и коды возврата можешь почитать в этом посте.


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

sudo sleep 120 &
kill -0 $!; echo "Exit status: $?"


В итоге получим:

bash: kill: (1644755) - Operation not permitted
Exit status: 1


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

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

Хорошего дня, а я пошел дальше диван давить, да лечиться. Увидимся!

tags: #bash

@BASHDAYS
97
In your head, in your head, Zombie, zombie, zombie-ie-ie…

Привет. Вчера Юра в комментах спросил за зомби процессы и как с ними деликатно обходиться. Расскажу про свой не деликатный опыт. Поехали.

Что такое зомби-процессы?

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

Всё, с теорий хватит.
Чтобы потыкать палкой какой-нибудь зомби процесс, нужно его искусственно создать. Пишем на СИ портянку (ниже будет и на Bash):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
pid_t child_pid;
child_pid = fork();

if (child_pid > 0) {
sleep(7200);
} else if (child_pid == 0) {
printf("Дочерний процесс выполнен.\n");
exit(0);
} else {
perror("Ошибка при вызове fork");
exit(EXIT_FAILURE);
}
return 0;
}


Этот код создает дочерний процесс, который сразу же завершается. Родительский процесс ждет 2 часа и затем завершается без вызова wait(). Вот так мы и получим своего маленького зомби, над которым будем ставить эксперименты.

Компилируем и запускаем в фоне этого зомбаря:

gcc zombie.c -o zombie
./zombie &


Либо создаем зомби через Bash:

(sleep 1 & exec /bin/sleep 7200) &


Выполняем команды и наблюдаем zombie процесс:

ps aux | grep Z


Вывод на экран:

root 1669051 Z 14:09 0:00 [zombie] <defunct>


Ага, хорошо, зомби завели. Теперь как это дело всё закилить. Простой kill -9 PID не поможет, так как PID родительского процесса будет отличаться от дочернего.

Чтобы найти PID родителя, смотрим:

ps ax | grep zombie


Кто-то грепает по слову defunct, тут уже по потребностям выбирай.

Видим все PIDы и родителя и дочернего:

1669050 S+ 0:00 ./zombie
1669051 Z+ 0:00 [zombie] <defunct>


В моем случае PID родительского = 1669050, а дочернего 1669051, который собственно и есть зомбик.

Теперь накидываем однострочник:

kill -9 $(ps -A -o stat,ppid | grep -e '[zZ]'| awk '{ print $2 }')


Эта штука найдет все зомби процессы и уничтожит их. Даже не нужно никакие циклы на Bash колхозить.

А если требуется регулярно зачищать зомборей, вешаем однострочник на cron и радуемся.

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

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


У меня зомбаки порой случались с nginx на древней CentOS, но после апгрейда на убунту, все прошло.

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

Давай, хороших выходных, не болей!

tags: #bash #linux

@BASHDAYS
98
Начинаем утреннюю гимнастику!

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

Задачи без хуйни, но с элементом соревнований. Как сейчас модно говорить — челендж. Так намного интереснее, это вызывает азарт. Обучение через геймификацию, все же топ штука.

Нужно написать самый короткий Bash скрипт, команду:

1. Вывести на экран таблицу умножения
2. Вывести на экран шахматную доску

Ниже я покажу самые короткие решения, которые меня порадовали. Авторы этих решений, 16ти летние пацаны. Видимо мозги еще не убиты кубиками и всратым скрамом.

Перед тем как откроешь спойлера, попробуй сам решить эти задачки и закинуть свои наработки в комментарии. Чьи решения наберут больше реакций/лайков — получат пиздюдей приз.


Чо по плюшкам

1. Аналоговая шаурма/тортик/пиво/другое. Макс закинет тебе приятный бонус на РФ карточку.

2. Статус в чатике - воин дракона (ну или какой сам захочешь).

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

В комментах закинул скриншоты с рабочих вариантов.


Таблица умножения

printf '%3s%3s%3s%3s%3s%3s%3s\n' $[{1..9} * {1..8}]

Шахматная доска

printf '%b%b%b\n' {1..4}'\b'{{1..5}'\b\e[107m \e[m ',{1..4}'\b \e[107m \e[m'}

Дерзай, сегодня наверное еще увидимся. Хорошего тебе дня! А я побежал дальше graylog ковырять.

tags: #bash #linux #games

@BASHDAYS
972
Сделать через жопу, это лучше, чем не сделать совсем

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

А как быть? Да всё просто, диск можно забить искусственно, не забивая его. Для этого существует такая поебень как: /dev/full.

/dev/full — это специальный файл устройства, источник данных, который всегда возвращает ошибку «No space left on device».


При попытке записи в /dev/full, тебе выдаст — опа, а места нету! Даже если физически место есть.

Это удобно для тестирования софта и обработчиков исключений. Например, пишет твой скрипт в файл какую-нибудь суету, место закончилось. Что будет дальше делать скрипт? Как он себя поведет?

Держу пари, будет пытаться продолжать писать. А по-хорошему, он должен сообщить тебе про это, либо корректно завершиться и освободить файл. Смекаешь?

Вот пример скрипта:

#!/bin/bash

output_file="data.txt"

while true; do
# Записываем данные в файл
echo "bashdays data" >> "$output_file"

# Проверяем на "No space left on device"
if ! echo "bashdays data" >> "/dev/full"; then
echo "Disk is full!"
break
fi
done


Скрипт при каждой итерации проверяет заполнен ли диск и если заполнен то выводит сообщение «Disk is full!».

Символ «!» в этом примере = инвертирует результат выполнения команды. То есть если запись в /dev/full не вызывает ошибки, то диск еще не заполнен.

Echo можешь заменить например на триггер, который тюкнет тебе в телеграм и скажет, что твой скрипт сожрал всё место.

Как взаимодействовать с API телеграм через Bash, я писал тут.


Такие дела. Изучай.

tags: #bash #linux

@BASHDAYS
1101
Всегда задавай себе вопрос — а не хуйню ли я делаю?

Кринжатину давно не постил. Исправляюсь. А ты знал… хотя нет, скорее всего не знал. Короче если к слову «Linux» применить XOR шифрование с маской 28, то получится слово PURID = «Чистый».

Это как если к слову «хлеб» применить XOR, то получится «пиво»


Смотри:

echo -e $(printf '\\x%x' $[ 64#{L,I,N,U,X} + 29 ^ 28 ])  
echo -e $(printf '\\x%x' $[ 64#{P,U,R,I,D} + 29 ^ 28 ])


Сразу пример, туда-обратно. Что тут происходит? Если кратно — происходят вычисления.

Для слова «Linux» в фигурных скобках применяется Bash Brace Expansion, который приводит слово к такому виду:

`L`,`I`,`N`,`U`,`X`


Арифметическое действие происходит в «$[». А решетка + 64 означает, что числа будут интерпретированы как шестидесятеричные (в системе счисления по основанию 64).

В итоге получаем число, которое будет вычислено как комбинация ASCII-кодов символов L, I, N, U, X (в шестидесятеричной системе) + 29, взятое по модулю 28 (используется оператор ^ как побитовое исключающее ИЛИ).

Ну и echo -e = разрешаем интерпретацию escape-последовательностей в строке.

Кринжатина? Еще какая! А сейчас давай оверхед на perl:

perl -E 'say map { chr(ord($_) ^ 28) } qw(L i n u x)'  
perl -E 'say map { chr(ord($_) ^ 28) } qw(P u r i d)'


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

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

tags: #bash #linux

@BASHDAYS
671
0xB105F00D, 0xB16B00B5, 0x0B00B135, 0xDEADBABE

И снова здрасти. Сегодня на изи, работы валом.

Короче эти штуки сверху называются HexSpeak. Это не просто HEX смещение, это запись английский слов, с помощью чисел в шестнадцатеричной системе счисления.

Такой вот отголосок из 80х, когда была сцена, демки в 4кб и т.п. Многие персонажи, делали себе подобные ники:

B105F00D = BIOS food
B16B00B5 = big boobs
0B00B135 = boobies
DEADBABE = dead babe
E11TE = elite


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

Про magic numbers писал тут.


Кто всю эту тему раскачал хуй знает, видимо народное творчество.

Смысл ты наверное понял, как все это кодируется. Но вкратце: символ «0 - ноль» может быть буквой «О», а «1» = «L» или «I» ну и т.д.

Короче это гиковская культура.

Теперь смотрим на картинку к посту. Если открыть JAVA файл c классом в редакторе, его первая строка будет выглядеть как «cafe babe». Первые четыре байта. Это магическое число используется для идентификации классов JAVA.

А почему вообще «cаfe babe»? На самом деле предположений много разных. Но позже Джеймс Гослинг (батя JAVA) все прояснил. Они вечно тусовались в кофейне, которое прозвали «CAFE DEAD». На самом деле там длинная история, погуглите.

Ну и вот, в процессе работы Джеймсу понадобилось заебенить магическое число, а «CAFE DEAD» как раз представляло шестнадцатеричное число. Ну и он его запихал для формата объектного файла. Короче ничо специально не делалось, все произошло в моменте.

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

Давай, завтра увидимся, а на выходные уж отдохнем.

tags: #linux

@BASHDAYS
761
Не бей себя ушами по щекам!

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

Есть два бесконечных bash цикла:

while :
do
done



while true
do
done


Вопрос: почему в первом случае используется «:», а во втором «true»?


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

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

Ведь как происходит, пишешь ты годами bash скрипты и даже не задумываешься, а схренали я использую «:» а не «true»? Да потому что оно нахер не всралось про это думать, работает и ок.

На самом деле эти циклы делаю одно и тоже. Объяснение простое:

Команда «:» всегда возвращает 0. Да «:» это команда, попробуй её запустить, а следом выполнить echo $? и получишь 0.

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

Для while справедливо требуется продолжение, вот мы и продолжаем с помощью «:» чтобы интерпретатор не засыпал ошибками. Этакая заглушка, для синтаксической корректности.

Ну а так как true тоже команда и всегда возвращает статус 0, получается что «:» и true = идентичны. Просто написать двоеточие намного быстрее.

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


Ноги растут из древних Bourne Shell, где не было встроенных команд ни true ни false. Использовали именно «:».

Получается «:» легаси? Ну можно и так сказать. Если хочешь чтобы твои скрипты работали в древних оболочках, используй «:». А если похер, то делай true.

Вот что лучше читается?

if true; then
echo "hello bashdays"
fi


if :; then
echo "hello bashdays"
fi


Мне очевиднее первый вариант, если не знать за «:», то словишь ступор. Такие дела. Изучай.

tags: #linux #bash

@BASHDAYS
2172
Если ты относишь себя к девопс-инженеру или что-то в этом духе — никогда не используй панельки ISPManager/VestaCP и т.п. для настройки серверов.

Привет. Короче сторис.

День первый.

100 лет назад я устроился в свою первую, местную веб-студию и велком таска на испытательном сроке была — подготовить сервер для клиентского проекта.

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

В то время я уже был уверенный джун, но никогда не настраивал сервера таким способом, для меня это было — дичь ебаная!

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

Уже тогда, моя хитрожопость не знала границ. У меня был доступ в панель управления хостинга. И что я сделал? Правильно, пересоздал сервер с готовой Free ISPМ панелькой.

Ну а дальше по накатанной, мышкой натыкал за полчаса, домены прописал, пехапе и апачу (фу-фу) завел. Таску в done двинул. Сижу радуюсь, какой же я охуенный!

Потратил полчаса на таску, на которую мне выделили 8 часов. Естественно остальное время я пропинал хуи.

День второй.

На следующий день состоялся релиз клиентского проекта. Но… деплой не прошел, jenkins высрал еррор, мол — пермишен денаед.

И понеслась пизда по кочкам. Шеф вызвал на ковер и задал свой любимый вопрос — как такое произошло? Я долго что-то мямлил, ну и каким-то чудом всё вскрылось.

Как оказалось, инструкция по которой мне дали настраивать сервак, была отлажена годами и под эту настройку был заточен jenkins. Разработчик просто указывал IP адрес сервера куда выкатить вонючий битрикс и оно выкатывалось.

В моём случае, на серваке банально не были прописаны ssh ключи этого злоебучего jenkins’а. Нууу…. и не хватало структуры каталогов, заведенных пользователей, нехватало — ничего! Короче ЖОПА!

Ну я же не знал… Хотя мне потом все красиво объяснили, что я лось дырявый. И что нужно делать все по ТЗ, а не как мне оленю захочется. Процессы, все дела.

Короче пиздов отхватил знатно, а задачу вернули на доработку. С тех пор, я научился придерживаться условиям задачи. Ну и самое главное нехило так качнул свои знания в Linux. Правда на всё про всё ушла неделя.

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

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

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

Сейчас, когда я умею с закрытыми глазами настраивать чёрта через консоль, я могу позволить себе панельки ISPM/VESTA, потому что понимаю что там под капотом и как это работает. Но в 99% предпочитаю консольку. Олдскулл.

Такие дела.

Всегда иди туда, где страшно. Чем страшнее, тем больше опыта получишь. А используя панельки, ты остаешься на уровне овоща, никакого развития. Понятно дело, оно проще, быстрее, но минус значительный — деградируешь.

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

Ладно, давай, хорошей тебе недели и не будь овощем!

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

@BASHDAYS
217
Про шлюх и CodeFest

Привет, хотел про рабочие будни, падших женщин и CodeFest рассказать, но это скучно. Как-нибудь в другой раз.

А сегодня рассмотрим интересную команду — compgen.

С помощью compgen можно вывести список всех консольных команд, которые вообще доступны в твоём Linux дистрибутиве.

✔️ Запускаем:

compgen -c


И наблюдаем. Да, это полный список команд, мне выплюнуло аж 3490. Поверь там ОЧЕНЬ много интересного.

✔️ Секрет успеха

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

А через месяц ты настолько преисполнишься в своем сознании, что аж пиздец. Я на полном серьезе!

Кстати по аналогии, я каждый день читаю по 10-20 слов из словаря Ожегова. Отлично расширяет словарный запас. Рекомендую.

У compgen есть еще масса ключей, некоторые из них:

-a = выведет список алиасов
-b = список всех bash модулей
-k = вывод ключевых слов
-A function = вывод всех функций

Ладно, что еще можно с compgen сделать:

✔️ Генерация списков

files=( $(compgen -f) )
echo "${files[@]}"


На экран выведется список файлов в текущем каталоге.

✔️ Анализ окружения

variables=( $(compgen -v) )
echo "${variables[@]}"


Выведется весь список переменных окружения.

✔️ Генерация динамических списков

users=( $(compgen -u) )
echo "${users[@]}"


Скрипт динамически создаст список всех пользователей в Linux.

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

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


Ну и вот. Пойду дальше диван давить, изучай. Увидимся!

tags: #bash #linux

@BАSHDАYS | BАSHDАYS.CОM
Please open Telegram to view this post
VIEW IN TELEGRAM
1911
This media is not supported in your browser
VIEW IN TELEGRAM
Если пишешь говнокод, неважно куда он попадет, в GIT репозиторий или унитаз. Суть одна.

Привет отдыхающим. Нашел на github неплохую пепяку «config-file-validator», которая из консольки валидирует файлы в форматах:

Apple PList XML, CSV, ENV, HCL, HOCON, INI, JSON, Properties, TOML, XML, YAML


Работает на всём, линуксы, винда, макоська, малина. Надо только установить. В репах увы её нет. Написано на golang.

✔️ Репа с рейтингом, люди пользуются, форкают.

Я качнул с репозитория zip’ник и закинул в /usr/local/sbin

cd /tmp
wget https://github.com/Boeing/config-file-validator/releases/download/v1.6.0/validator-v1.6.0-linux-amd64.tar.gz
tar -xf validator-v1.6.0-linux-amd64.tar.gz
mv validator /usr/local/sbin


А если любишь docker, то можно прям контейнер подтянуть с этим валидатором.

Теперь в каталоге с файлами запускаем: validator и смотрим:

root@dev:# validator
× bashdays.json
error: Error at line 3 column 2: invalid character '"' after object key:value pair
✓ bashdays.yml
Summary: 1 succeeded, 1 failed


Отличное решение, когда лень или нет возможности запускать IDE. Быстро, просто, бесплатно.

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

🌐 Страница проекта на github

tags: #utils

@BАSHDАYS | BАSHDАYS.CОM
Please open Telegram to view this post
VIEW IN TELEGRAM
129
This media is not supported in your browser
VIEW IN TELEGRAM
А у тебя спина белая!

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

Самый лучший тренажер это конечно же VIM. Это аксиома.


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

Я загрузил в него тексты «Красной Плесени» и отправился в бой. Но есть варианты с текстами по умолчанию. Сука, это даже не тренажер, это шедевр. Затягивает основательно.

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

✔️ Оригинальная версия
✔️ С поддержкой RU языка

tags: #games

@BАSHDАYS | BАSHDАYS.CОM
Please open Telegram to view this post
VIEW IN TELEGRAM
140