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

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

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

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Download Telegram
Здарова! Годнота подъехала!

Если любишь копаться в «кишочках» эта штука тебе обязательно пригодится, называется Binsider.

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

У хорошего девопса и бычий хуй веревка!


Короче это хуйня на расте позволяет анализировать «Эльфов» (ELF бинарники).

- Статический анализ: изучение структуры бинарного файла, включая секции, сегменты, символы и релокации.

- Динамический анализ: выполнение бинарного файла с отслеживанием системных вызовов и сигналов (strace/ltrace).

- Извлечение строк: поиск полезных строк (например, паролей или URL) внутри бинарного файла.

- Шестнадцатеричный дамп: просмотр содержимого файла в виде шестнадцатеричного кода с удобной визуализацией.

Инструкция по установке тут, есть докеры-хуёкеры и т.п.

Я собрал из исходников, делов 30 секунд:

cd /tmp

VERSION="0.1.0"

wget "https://github.com/orhun/binsider/releases/download/v${VERSION}/binsider-${VERSION}-x86_64-unknown-linux-gnu.tar.gz"

tar -xvzf binsider-*.tar.gz

cd "binsider-${VERSION}"

./binsider


➡️ Репка на гитхабе

➡️ Заценить на ютубе

Обязательно посмотри, рекомендую!

Ааа, еще всех вас с пятницей, хороших предстоящих выходных. Ну и самое главное — береги себя! Всех обнял 🙃

tags: #debug #linux #utils #utilites

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
554812
Богатствуйте!

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

Меня часто спрашивают… Нет, всем похуй. Короче:

systemctl restart php-fpm

Unit php-fpm.service could not be found.


Хм, я точно знаю что php на сервере есть! Так какого чернослива?

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

В примере выше, php сервис называется: php8.2-fpm-fuck-you!

Ха! В жизни не догадаешься.

Первым делом пиздуем в:


history | grep php


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

Если не повезло делаем так:

systemctl | grep php

php8.2-fpm-fuck-you.service
phpsessionclean.timer


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

Можно конечно воспользоваться внешними утилитами, но не рекомендую. Потому что systemctl есть всегда, а внешних утилит - нет.

➡️ Сразу привыкай работать с инструментами из коробки и будет тебе счастье.

Все!

Ну и анекдот как обещал: еслиб у бабушки был бы хуй, она была бы дедушкой.

tags: #linux #debug

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
259824
Реверсим Dockerfile

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

Как произвести реверсинг?

Для примера соберем образ из такого Dockerfile

FROM python:3.8-slim
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]


Запускаем сборку имейджа:

docker build -t pythoner:latest .


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

docker history pythoner:latest


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

docker history --no-trunc pythoner:latest


Вылетит простыня, но при сноровке и насмотренности, всё вполне предсказуемо.

В идеале совмещаем с dive, смотрим окно Layers и стрелками перемещаемся по слоям, а там уже видно все команды, которые выполнялись из Dockerfile.

По итогу из говна и палок собираем копию нужного нам Dockerfile.

А файлы, которые были добавлены через COPY, вытягиваем себе на локальную машину так:

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


Про дебаг докер имейджей и контейнеров я писал в этом посте, почитай, достаточно информативно.


Как вариант можешь воспользоваться анализаторами, например trivy.

Trivy это комплексный и универсальный сканер безопасности для docker images. Заодно еще безопасность своих решений можно позырить и приуныть.

А еще есть клевая поделка для этого на python, но про нее закину уже завтра.

Вот такие пироги, если знаешь еще способы — пиши в комменты, будет полезно!

tags: #debug #devops #docker

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
156618
Вчера мы рассмотрели способы как отреверсить Dockerfile с помощью рук и глаз.

Сегодня рассмотрим никому не известную утилиту — «Дедок».

Утилита написана на питоне и позволяет свести к минимуму handjob по реверсу.

Грубо говоря «Дедок» проанализирует твой docker image и выплюнет на экран готовый Dockerfile.

Ну как готовый, очень приближенный к реальности.

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

Запускаем так:

docker run -v /var/run/docker.sock:/var/run/docker.sock mrhavens/dedockify <ID Image>


Либо сразу в алиас:

alias dedoc="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm mrhavens/dedockify"


Предварительно подставь нужный ID Image.


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

➡️ Репа проекта и документашка.

Развлекайся. Увидимся совсем скоро!

tags: #debug #devops #docker

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
123714
Интересный вопрос сегодня залетел:

Если функции, вынесены в файл, подключенный через source, bash каждый раз его будет открывать/перечитывать при обращении к функции? Или как-то считает в память и все?


Давай посмотрим что происходит в кишках в это время. Давненько мы с тобой в strace не смотрели.

Предположим есть bash скрипт с функциями:

functions.sh

#!/bin/bash

bashdays_function() {
echo "Hello from BashDays"
}


И основной скрипт, который сорсит файл с функциями:

test_script.sh

#!/bin/bash

source ./functions.sh

bashdays_function
bashdays_function


Не забываем сделать: chmod +x test_script.sh

Запускаем test_script.sh под контролем strace:

strace -e trace=openat ./test_script.sh


И видим:


openat(AT_FDCWD, "./test_script.sh", O_RDONLY) = 3
openat(AT_FDCWD, "./functions.sh", O_RDONLY) = 3

Hello from BashDays
Hello from BashDays


То есть в контексте скрипта test_script.sh, файл с функциями был прочитан один раз.

При втором вызове функции всё считалось из памяти.

Если бы файл functions.sh читался каждый раз, то мы увидели бы несколько строчек openat(AT_FDCWD).

Грубо говоря при каждом запуске test_script.sh, подключенный файл через source будет прочитан один раз.

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

Изучай!

tags: #bash #debug #linux

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
166625
Здрасти. Как-то я писал про strace и как применять инъекции. Если пропустил, то читай тут и тут.

Ниже скрипт который автоматически пронумерует системные вызовы для последующих инъекций.

#!/usr/bin/perl

use strict;
use warnings;

my %numbs;
select STDERR;
while(<STDIN>) {
if( /^[0-9]++\s++([a-z0-9_]++(?=\())/ ) {
my $t = ++$numbs{$1};
s/\s+/ \e[31m$t\e[m /;
die $! if( keys %numbs == 1000 );
}
print;
}
exit(0);


Сохраняем это безобразие в файл num_syscalls и делаем chmod +x, ну а дальше запускаем в связке с strace:

strace -o'|./num_syscalls' -yf sh -c 'ls|cat'


Теперь получаем такой выхлоп:

456107 48 close(3</usr/) = 0
456107 52 rt_sigreturn({mask=[]})
456107 63 openat(AT_FDCWD</usr/local/sbin>)
456107 53 newfstatat(3)
456107 64 openat(AT_FDCWD</usr/local/sbin>)


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

Например, возьмем системный вызов openat, видим 63, 64. Это значит что openat был вызван 64 раза. А newfstatat 53.

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

Тема крутая, не нужно ебаться и считать руками.

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

А чтобы получить только трассировку, можно сделать так:

strace -o'|./num_syscalls' -yf ls > /dev/null


Если бесит подсветка, выпили из перловского скрипта управляющий символ «\e[31m\[em».

Такие дела, изучай!

tags: #linux #debug

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
113415
Service или Systemctl?

Каждый стартует или стопает процессы как привык. Во времена динозавров когда еще не существовало systemd, всё сводилось к командам:

service apache restart


Сейчас мир изменился, появился systemd, но привычки остались прежними.

Теперь сервисами рекомендуется управлять через systemctl.

Но какая в хуй разница как управлять сервисам?

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

На самом деле сейчас команда service это обёртка вокруг systemctl.

Давай убедимся:

strace -f service nginx restart 2>&1 | grep execve


По итогу ты получишь:

execve("/usr/bin/systemctl", ["systemctl", "restart", "nginx.service"])


То есть service обратился к systemctl и произвел перезапуск nginx.

А если глянуть исходник service:

cat /usr/sbin/service


То ты увидишь обычный bash скрипт в котором и происходит вся эта магия.

Если система использует SysVinit или Upstart (например, старые версии Debian, CentOS 6, Ubuntu 14.04), то service будет работать напрямую со скриптами /etc/init.d/.

По бест-практикам старайся использовать systemctl. Но опять же service никто не запретит тебе использовать.

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

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

Кроме systemctl и service есть такие штуки для управления процессами:

/etc/init.d/nginx restart
rc-service nginx restart
sv restart nginx
s6-rc -d change nginx
supervisorctl restart nginx


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

ps -p 1 -o comm=


Вот и вся наука.

А как ты рулишь сервисами? Как скуф или как современный молодой человек?

tags: #linux #debug #strace

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
88
Если тебе необходимо изменить файл сервиса в Linux, не нужно пиздовать ручками в папку /etc/systemd искать и править его.

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


А бест-практика уже заложена в systemctl!

Достаточно выполнить команду:

sudo systemctl edit nginx


Откроется редактор с нужным сервисом. НО, редактировать ты будешь не корневой юнит, а override. То есть прокладку, которая переопределит параметры основного юнита.

В моём случае с nginx будет открыт файл:

/etc/systemd/system/nginx.service.d/override.conf

В нем я переопределяю нужные параметры для сервиса и НЕ трогаю основной файл юнита.

А если я хочу править корневой?

Да похуй, вот тебе команда:

sudo systemctl edit --full nginx


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

1. Копирует оригинальный юнит-файл из /lib/systemd/system/nginx.service в /etc/systemd/system/nginx.service

2. Открывает его в редакторе.

3. После сохранения — systemd использует именно эту копию в /etc/.

Это безопасный способ редактировать полные юниты, без риска перезаписи при обновлении пакетов.

Есть еще ключ --force, но про него погугли сам.


Как проверить валидность файла юнита?

systemd-analyze verify /etc/systemd/system/nginx.service


В ответ получишь:

/etc/systemd/system/nginx.service:31: Missing '=', ignoring line.


Ага, ошибочка, правим и только после этого можно делать:

sudo systemctl daemon-reload
sudo systemctl restart nginx


Короче учись работать правильно и всё у тебя будет хорошо!

С пятницей! Хороших тебе предстоящих выходных и береги себя!

🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
8211
Сегодня будем профилировать Linux сервисы.

В прошлый раз мы с тобой посмотрели, как без хуйни обращаться с юнитами.

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

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


Запускаем и смотрим:

systemd-analyze blame


По итогу получаем список юнитов и их время запуска.

17.084s docker.service
10.961s systemd-journal-flush.service
7.595s containerd.service
7.496s cloud-final.service
7.189s cloud-init-local.service
3.260s apt-daily-upgrade.service
2.522s cloud-init.service
2.095s dpkg-db-backup.service
1.991s networkd-dispatcher.service
1.963s chrony.service


В моём примере дольше всего грузится служба с докером.

Отрубаем службу и радуемся приросту в 17 секунд. Но НЕТ! На самом деле тут всё немного сложнее.

Иногда сам юнит стартует достаточно быстро, но сука ждет другой юнит, который «Блиц — скорость без границ».

Смотрим цепочку зависимостей:

systemd-analyze critical-chain


└─docker.socket @13.269s +8ms
└─sysinit.target @13.261s
└─cloud-init.service @10.735s +2.522s
└─systemd-networkd-online.service @12.806s +31ms
└─systemd-networkd.service @12.741s +59ms


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

То есть docker.service зависит от systemd-networkd-wait-online.service, ну и дальше пошли по цепочке.

Почему так?

Docker по умолчанию может иметь After=network-online.target, а при использовании systemd-networkd это приводит к ожиданию systemd-networkd-wait-online.service.

А чё делать?

Выйти из айти, купить яхту и поехать ловить крабов.

Если тебе нужно, чтобы Docker НЕ ждал сеть, поменяй юнит:

sudo systemctl edit docker.service


[Unit]
After=network.target
Wants=network.target


Ну или вообще убрать After=network-online.target, если нет зависимости от сети на старте.

После этого снова смотрим выхлоп через blame:

4.739s cloud-init-local.service
4.041s containerd.service
2.329s dev-sda1.device


Всё блядь! Теперь докер не тормозит загрузку, но после загрузки системы докер исправно работает.

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

Забирай в копилку, для дебага маст-хев!

🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
3128
Как безопасно тестировать юниты

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

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

Ключ --runtime — создаёт временное переопределение, которое исчезнет после перезагрузки.


Идеально подходит, если ты тестишь, не уверен или не хочешь ничего портить.

А вот и сама команда:

SYSTEMD_EDITOR=vim systemctl edit --runtime nginx


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


Всё! Теперь правим юнит, тестируем. Временный файл с override будет создан тут /run/systemd/.

И самое главное — все изменения сохранятся только до следующей перезагрузки системы.

А какая в этом польза?

1. Для временного изменения конфигурации systemd без затрагивания оригинального файла.

2. Для тестов или отладки (например, сменить ExecStart для nginx только на время текущей сессии).

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

Пример с nginx

Хочу временно запустить nginx с другим конфигом! Создаю рантайм.

[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -c /home/user/nginx-bashdays.conf


Перезапускаю nginx и радуюсь результату, теперь nginx запущен с другим конфигом.

А почему ExecStart идет дважды?

Хе брат, это очередная приколюха systemd. Оно очищает предыдущее значение ExecStart из основного юнита. А следующая строка задаёт новое значение.

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

Думаю на этом можно закончить. Я неочевидную базу выдал, а ты стал еще сильнее. Изучай и ничего не бойся!

🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
156