Закрыть периметр правилами iptables и не остаться при этом за дверью вместе с атакующим.
Посмотреть, что слушает наружу
Даёт порт, состояние и процесс:
Найти, кто держит больше всего соединений
Нюанс: в шпаргалках этот однострочник идёт без
Закрыть вход по умолчанию
Нюанс: в подборках порядок обратный — сначала
Заодно
Ограничить SSH подсетью и числом сессий
Оба правила встали. Полезная деталь:
Отправить подсеть в никуда без файрвола
Нюанс: это не тихий дроп. Локальные попытки получают отлуп сразу —
И общее: всё это живёт до перезагрузки.
А вы вредоносные IP баните iptables напрямую или отдаёте это CrowdSec и fail2ban?
#Linux #Security #iptables #Networking #DevOps
Посмотреть, что слушает наружу
ss -tulpn
Даёт порт, состояние и процесс:
0.0.0.0:8099 users:(("python3",pid=3545,fd=3)). Первое, с чего начинается любой аудит — половина находок обычно в том, что сервис слушает 0.0.0.0 вместо 127.0.0.1.Найти, кто держит больше всего соединений
ss -Hntu | awk '{print $5}' |
sed 's/:[^:]*$//' | sort | uniq -c | sort -rn
Нюанс: в шпаргалках этот однострочник идёт без
-H и с cut -d: -f1. Оба места ломаются. Без -H в подсчёт попадает строка заголовка, и в топе появляется несуществующий адрес Local. А cut по первому двоеточию режет IPv6: адрес [2001:db8::2]:54321 превращается в [2001. Отсечение через sed берёт только порт с конца.Закрыть вход по умолчанию
iptables -A INPUT -m conntrack \
--ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP
Нюанс: в подборках порядок обратный — сначала
-F, потом -P INPUT DROP, а разрешающие правила ниже. Между этими двумя строками сессия уже мертва, и до правил вы не дойдёте. Политика ставится последней, всегда.Заодно
-m state там устаревший, актуален -m conntrack --ctstate.Ограничить SSH подсетью и числом сессий
iptables -A INPUT -p tcp --dport 22 \
! -s 10.0.0.0/24 -j DROP
iptables -A INPUT -p tcp --dport 22 \
-m connlimit --connlimit-above 3 -j REJECT
Оба правила встали. Полезная деталь:
iptables -S показывает, что модуль сам дописал --connlimit-mask 32 --connlimit-saddr — лимит считается по одному адресу, а не по подсети. Если нужен другой охват, маску задавайте явно.Отправить подсеть в никуда без файрвола
ip route add blackhole 192.168.10.0/24
Нюанс: это не тихий дроп. Локальные попытки получают отлуп сразу —
ping вернул connect: Invalid argument, curl завершился с кодом 7. Для исходящего трафика это плюс, ошибка приходит мгновенно вместо таймаута, но маскировки не ждите.И общее: всё это живёт до перезагрузки.
netfilter-persistent для правил, ip route — в конфигурацию сети, иначе следующий ребут откроет всё обратно.А вы вредоносные IP баните iptables напрямую или отдаёте это CrowdSec и fail2ban?
#Linux #Security #iptables #Networking #DevOps
👍6
Разобрать строку штатным <regex.h> и не получить молчаливое «нет совпадения».
Проверял на glibc, gcc 13.3, Ubuntu 24.04. Все фрагменты ниже собраны в одну программу и скомпилированы с
Скомпилировать шаблон
Понять, почему не скомпилировалось
Буфер обязан быть массивом. На незакрытой скобке
Сопоставить и достать группы
Не забыть освободить
Замерил: 100 тысяч компиляций в цикле без
Где POSIX молчит вместо ошибки
Самое неприятное не в том, чего API не умеет, а в том, как он об этом сообщает:
Просмотры и именованные группы падают на компиляции — это честно. А вот
А вы в C-утилитах держитесь
#Linux #C #POSIX #regex #DevOps
Проверял на glibc, gcc 13.3, Ubuntu 24.04. Все фрагменты ниже собраны в одну программу и скомпилированы с
-Wall -Wextra без единого предупреждения.Скомпилировать шаблон
regex_t re;
int rc = regcomp(&re, "^([a-z]+)=([0-9]+)$",
REG_EXTENDED);
REG_EXTENDED включает ERE: скобки и + работают без обратных слешей. Без флага получите BRE, где группа пишется как \(...\).Понять, почему не скомпилировалось
char err[256];
if (rc != 0) {
regerror(rc, &re, err, sizeof err);
fprintf(stderr, "regcomp: %s\n", err);
}
Буфер обязан быть массивом. На незакрытой скобке
[a-z получите Unmatched [, [^, [:, [., or [=. Нюанс: regfree вызывайте только после успешного regcomp, для неудачной компиляции освобождать нечего.Сопоставить и достать группы
regmatch_t m[3];
const char *s = "app=100";
if (regexec(&re, s, 3, m, 0) == 0)
printf("%.*s\n", (int)(m[1].rm_eo - m[1].rm_so),
s + m[1].rm_so);
m[0] — всё совпадение, m[1] и дальше — группы по порядку. На app=100 вышло app в первой группе и 100 во второй. Нюанс: смещения в байтах, не в символах. В строке ключ=42 вторая группа начинается с байта 9, хотя символов перед ней пять. И если компилировали с REG_NOSUB, массив m не заполняется вовсе.Не забыть освободить
regfree(&re);
Замерил: 100 тысяч компиляций в цикле без
regfree раздули процесс до 1.4 ГБ, с ним — 1.8 МБ. В демоне, который компилирует шаблон на каждый запрос, это вопрос часов.Где POSIX молчит вместо ошибки
Самое неприятное не в том, чего API не умеет, а в том, как он об этом сообщает:
\d+ на "abc 123" -> No match
<.*?> на "<a><b>" -> <a><b>
(?<=x)y -> Invalid preceding regular expression
Просмотры и именованные группы падают на компиляции — это честно. А вот
\d компилируется и тихо ничего не находит, вместо него нужен [0-9]. И .*? не ошибка, а просто жадный .*: вернул всю строку вместо <a>. Привычки из PCRE здесь ломают логику молча.А вы в C-утилитах держитесь
<regex.h> или сразу тянете PCRE2?#Linux #C #POSIX #regex #DevOps
🔥 Знаешь только ip a? 10 неочевидных команд ip для Linux
Большинство админов знают про ip ровно две команды —
1️⃣ Вся сеть одним экраном, в цвете:
Интерфейс, состояние и адреса — по строке на каждый.
2️⃣ Куда реально уйдёт пакет:
Покажет интерфейс, шлюз и source-адрес. Незаменимо, когда маршрутов много и непонятно, какой победил.
3️⃣ Маршруты, которых нет в
ВАЖНО:
4️⃣ Сменить шлюз без риска потерять сервер:
Атомарно: нет окна без маршрута, как между
5️⃣ Дропы и ошибки на интерфейсе:
Растут errors или dropped — копай в кабель, драйвер или буферы, а не в приложение.
6️⃣ Жив ли шлюз на L2:
7️⃣ Сеть в прямом эфире:
Каждое изменение с меткой времени: упал линк, DHCP или VPN переписали маршрут. Оставь в tmux и лови, кто ломает сеть по ночам.
8️⃣ Отрезать IP без фаервола:
Ответы на этот адрес уходят в никуда, TCP-сессия с ним не установится.
9️⃣ IP интерфейса в скрипте без awk-акробатики:
🔟 Процесс без сети за две команды:
В новом namespace только выключенный
Всё, что меняешь через ip, живёт до перезагрузки. Постоянные настройки — в netplan, NetworkManager или systemd-networkd.
А какую из десяти ты уже держишь в алиасах?
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Networking #iproute2 #CheatSheet #SysAdmin #DevOps
Большинство админов знают про ip ровно две команды —
ip a и ip r, а дальше ifconfig по старой памяти. Держи 10 команд, которые покажут то, чего не видно в ip a: скрытые маршруты VPN, дропы на интерфейсе и мёртвый шлюз. Проверил на iproute2 6.1.1️⃣ Вся сеть одним экраном, в цвете:
ip -br -c a
Интерфейс, состояние и адреса — по строке на каждый.
-br работает и с link.2️⃣ Куда реально уйдёт пакет:
ip route get 8.8.8.8
# какая запись в таблице сработала
ip route get fibmatch 8.8.8.8
Покажет интерфейс, шлюз и source-адрес. Незаменимо, когда маршрутов много и непонятно, какой победил.
3️⃣ Маршруты, которых нет в
ip route:
ip rule
ip route show table all
ВАЖНО:
ip route показывает только таблицу main. wg-quick с AllowedIPs = 0.0.0.0/0 уводит дефолт в таблицу 51820, а ip route делает вид, что всё как раньше.4️⃣ Сменить шлюз без риска потерять сервер:
sudo ip route replace default via <gw>
Атомарно: нет окна без маршрута, как между
del и add. Упадёт с ошибкой — старый маршрут останется на месте.5️⃣ Дропы и ошибки на интерфейсе:
ip -s link show <iface>
# двойной -s — ошибки с разбивкой: crc, frame, fifo
ip -s -s link show <iface>
Растут errors или dropped — копай в кабель, драйвер или буферы, а не в приложение.
6️⃣ Жив ли шлюз на L2:
ip neigh show dev <iface>
REACHABLE и STALE — норма. Шлюз висит в FAILED или INCOMPLETE — он не отвечает на ARP, и пинговать дальше бесполезно.7️⃣ Сеть в прямом эфире:
ip -ts monitor link route
Каждое изменение с меткой времени: упал линк, DHCP или VPN переписали маршрут. Оставь в tmux и лови, кто ломает сеть по ночам.
8️⃣ Отрезать IP без фаервола:
sudo ip route add blackhole 203.0.113.5/32
# проверить и убрать
ip route show type blackhole
sudo ip route del blackhole 203.0.113.5/32
Ответы на этот адрес уходят в никуда, TCP-сессия с ним не установится.
ip route get по нему вернёт Invalid argument — так ядро отвечает на blackhole, это не ошибка.9️⃣ IP интерфейса в скрипте без awk-акробатики:
ip -j -4 addr show dev <iface> \
| jq -r '.[0].addr_info[0].local'
-j отдаёт JSON: парсинг не сломается, когда поменяется формат вывода. Нужен пакет jq.🔟 Процесс без сети за две команды:
sudo ip netns add lab
sudo ip netns exec lab <command>
# убрать за собой
sudo ip netns del lab
В новом namespace только выключенный
lo. Удобно проверить, как приложение переживёт падение сети, не трогая хост.Всё, что меняешь через ip, живёт до перезагрузки. Постоянные настройки — в netplan, NetworkManager или systemd-networkd.
А какую из десяти ты уже держишь в алиасах?
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Networking #iproute2 #CheatSheet #SysAdmin #DevOps
👍20🔥2
💀 CPU под 100%, а в top пусто? Ловим невидимые процессы через eBPF
Сервер греется, в шапке top
Ловим каждый запуск
Один и тот же PPID и новые процессы каждые 50 мс — вот он, виновник.
Кто плодит больше всех
Почему не strace -f
Проверил:
ВАЖНО: bcc-версия
Вместо «CPU горит, а кто — непонятно» получаешь имя процесса, аргументы и PID родителя. Дальше дело техники: поправить крон или скрипт.
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #eBPF #bpftrace #Troubleshooting #SysAdmin #DevOps
Сервер греется, в шапке top
us под 90%, а в списке процессов — никого. Классика: кто-то плодит процессы, которые живут 10–50 мс, а top опрашивает /proc раз в 3 секунды и их просто не застаёт. Показываю, как поймать виновника, не роняя прод.Ловим каждый запуск
# 1. В Ubuntu утилита идёт в пакете bpftrace
sudo apt install bpftrace
# Каждый execve() в реальном времени:
# время, PID и PPID родителя.
sudo execsnoop.bt
TIME PID PPID ARGS
16:55:42.684175 1112 1097 /bin/true
16:55:42.685129 1113 1097 curl --version
16:55:42.691294 1114 1097 sleep 0.05
Один и тот же PPID и новые процессы каждые 50 мс — вот он, виновник.
Кто плодит больше всех
# 2. Считаем запуски по родителю за 10 секунд.
# Подсчёт идёт ПРЯМО в ядре, без потока событий.
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_execve
{ @[comm, curtask->real_parent->tgid] = count(); }
interval:s:10 { exit(); }'
# Вывод: @[bash, 1097]: 525
# bash с PID 1097 за 10 секунд породил 525 процессов.
# 3. Смотрим, кто это и откуда он взялся
pstree -sp \<PPID>
ps -o pid,etime,cmd -p \<PPID>
Почему не strace -f
Проверил:
dd с bs=1 под strace работает в ~47 раз медленнее. И в ~37 раз — даже если трассировать только accept(), которого dd вообще не вызывает: ptrace останавливает процесс на КАЖДОМ системном вызове. eBPF процесс не останавливает и считает события в ядре.ВАЖНО: bcc-версия
execsnoop-bpfcc компилирует программу на лету и без linux-headers-$(uname -r) падает с «Unable to find kernel headers». execsnoop.bt работает через BTF, заголовки ему не нужны. Есть ли BTF в ядре: ls /sys/kernel/btf/vmlinux.Вместо «CPU горит, а кто — непонятно» получаешь имя процесса, аргументы и PID родителя. Дальше дело техники: поправить крон или скрипт.
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #eBPF #bpftrace #Troubleshooting #SysAdmin #DevOps
👍7🔥5
📊 Диск тормозит, а iostat показывает норму? Ищем хвост задержек
Приложение подвисает на записи, в логах таймауты к БД, а
Что на самом деле показывает iostat
ВАЖНО:
Гистограмма вместо среднего
Проверил на тестовой нагрузке (столбики убрал, чтобы влезло в экран): iostat в тот же момент показывал
Чей I/O висит
Видишь
Среднее говорит «всё хорошо», гистограмма показывает хвост, а третья команда — чей он. Дальше — по месту: вынести бэкап, развести нагрузку или идти к провайдеру с цифрами.
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #eBPF #Storage #Troubleshooting #SysAdmin #DevOps
Приложение подвисает на записи, в логах таймауты к БД, а
iostat рисует w_await в пару миллисекунд. Подвох в том, что iostat показывает среднее: 990 запросов по 0.1 мс и 10 по 200 мс дают в среднем 2 мс. Показываю, как достать хвост, который тонет в среднем.Что на самом деле показывает iostat
# 1. -x — расширенные колонки, раз в секунду
iostat -x 1
# r_await и w_await — СРЕДНЕЕ за интервал:
# редкие зависшие запросы в нём растворяются
ВАЖНО:
%util под 100% на SSD, NVMe и RAID не значит, что диск упёрся: они обслуживают запросы параллельно. Это прямо написано в man iostat.Гистограмма вместо среднего
# 2. В Ubuntu утилита идёт в пакете bpftrace.
# Ctrl+C — и получаешь распределение задержек.
sudo biolatency.bt
@usecs:
[16, 32) 426043
[32, 64) 15436
[64, 128) 527
...
[1K, 2K) 24
[2K, 4K) 17
[4K, 8K) 13
Проверил на тестовой нагрузке (столбики убрал, чтобы влезло в экран): iostat в тот же момент показывал
w_await 0.02 мс, а в хвосте висели запросы по 4–8 мс — в сотни раз дольше среднего.Чей I/O висит
# 3. Каждый запрос дольше 10 мс — с процессом.
# Порог подстрой: для HDD 10 мс — норма.
# На tracepoint'ах: не сломается с новым ядром.
sudo bpftrace -e '
t:block:block_bio_queue {
@ts[args->sector] = nsecs;
@who[args->sector] = comm;
}
t:block:block_rq_complete /@ts[args->sector]/ {
$ms = (nsecs - @ts[args->sector]) / 1000000;
if ($ms >= 10) {
printf("%s %d ms\n", @who[args->sector], $ms);
}
delete(@ts[args->sector]);
delete(@who[args->sector]);
}
END { clear(@ts); clear(@who); }'
Видишь
kworker или jbd2 вместо своего процесса — это отложенная запись из page cache. Настоящего писателя покажет pidstat -d 1.Среднее говорит «всё хорошо», гистограмма показывает хвост, а третья команда — чей он. Дальше — по месту: вынести бэкап, развести нагрузку или идти к провайдеру с цифрами.
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #eBPF #Storage #Troubleshooting #SysAdmin #DevOps
👍9
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥1
💀 df показывает 100%, а du молчит? 5 шагов спасения прода
Сервисы падают с «No space left on device»,
Шаг 1. Что именно кончилось
При 100% в
Шаг 2. Ищем удалённые, но открытые файлы
Шаг 3. PID и номер дескриптора
Шаг 4. Обнуляем файл без рестарта
Проверил на тестовой ФС: 141 МБ вернулись мгновенно, процесс продолжил писать. Только для логов и мусора — усечёшь файл данных БД, потеряешь данные.
Подвох: если сервис пишет без
Шаг 5. Аварийный запас на ext4
После уборки верни
Чтобы не повторилось — logrotate с
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Troubleshooting #Storage #SysAdmin #DevOps
Сервисы падают с «No space left on device»,
df -h рисует 100%, а du -sh /* насчитывает куда меньше. Классика: кто-то удалил гигантский лог, а процесс держит его открытым — файла уже нет, а блоки заняты. Показываю, как вернуть место без рестарта сервиса.Шаг 1. Что именно кончилось
df -h /var
# Место есть, а пишет «No space left»? Кончились inode:
df -i /var
При 100% в
df сервисы от root ещё пишут в резерв ext4, а остальные уже падают.Шаг 2. Ищем удалённые, но открытые файлы
# +L1 — файлы без единой ссылки в ФС.
# Точка монтирования в конце = только эта ФС.
sudo lsof -nP +L1 \<mountpoint>
COMMAND PID FD SIZE/OFF NAME
python3 690 3w 73400887 /mnt/t/app.log (deleted)
Шаг 3. PID и номер дескриптора
3w в колонке FD — дескриптор 3, открыт на запись. Проверка:sudo ls -l /proc/\<PID>/fd/\<FD>
# ... -> /mnt/t/app.log (deleted)
Шаг 4. Обнуляем файл без рестарта
# ВАЖНО: sudo : > файл НЕ сработает —
# перенаправление делает твой шелл, а не sudo.
sudo truncate -s 0 /proc/\<PID>/fd/\<FD>
Проверил на тестовой ФС: 141 МБ вернулись мгновенно, процесс продолжил писать. Только для логов и мусора — усечёшь файл данных БД, потеряешь данные.
Подвох: если сервис пишет без
O_APPEND (например, запущен как app > file.log), он продолжит с прежнего смещения. Размер снова покажет 70 МБ, хотя на диске файл занимает 4 КБ: он станет разреженным, и мониторинг по размеру будет врать.Шаг 5. Аварийный запас на ext4
# Резерв под root, по умолчанию 5%
sudo tune2fs -l /dev/\<disk> | grep -i "reserved block"
# Временно отдать 4% — работает на лету
sudo tune2fs -m 1 /dev/\<disk>
После уборки верни
-m 5: резерв нужен, чтобы root мог чинить систему на полном диске. Только ext2/3/4, на XFS не сработает.lsof +L1 пуст, а расхождение осталось? Файлы могут прятаться под точкой монтирования: смонтируй корень через mount --bind в пустую папку и запусти du там.Чтобы не повторилось — logrotate с
postrotate, который просит сервис переоткрыть лог, вместо ручного rm.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Troubleshooting #Storage #SysAdmin #DevOps
👍9
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👀1
🚨 Сервер под подозрением? 8 шагов аудита прав и SUID-бэкдоров
Кажется, что кто-то получил лишние привилегии, а с чего начать проверку — непонятно. Держи чек-лист на первые минуты: ищем скрытые пути к root — SUID, capabilities, PAM и sudo. Команды с SELinux проверены по документации, остальное прогнано на Ubuntu 24.04.
🔴 Шаг 1. SELinux: снять маску dontaudit
ВАЖНО: без
🔑 Шаг 2. SUID и SGID
Сравни список с чистой системой. Свежая дата у файла в
🎭 Шаг 3. Capabilities: SUID, который find не видит
ВАЖНО:
🚪 Шаг 4. PAM: вход мимо пароля
👤 Шаги 5–6. Скрытый root и sudo-лазейки
🔐 Шаги 7–8. Чужие ключи и входы
Порядок: dontaudit и AVC → SUID и capabilities → PAM → root и sudo → ключи. Нашёл подозрительное — не «чисти», а снимай образ: подчищенный сервер невозможно расследовать. И держи эталонный список SUID и
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #SkillHunter@LinuxSkill
#Linux #Security #SELinux #Forensics #Hardening #SysAdmin
Кажется, что кто-то получил лишние привилегии, а с чего начать проверку — непонятно. Держи чек-лист на первые минуты: ищем скрытые пути к root — SUID, capabilities, PAM и sudo. Команды с SELinux проверены по документации, остальное прогнано на Ubuntu 24.04.
🔴 Шаг 1. SELinux: снять маску dontaudit
# Правила dontaudit глушат часть отказов —
# атака может не попасть в лог AVC.
# Временно снимаем глушилку:
sudo semodule -DB
sudo ausearch -m avc -ts today
# Вернуть как было:
sudo semodule -B
ВАЖНО: без
semodule -DB часть заблокированных попыток доступа в журнал AVC просто не пишется. -DB держи включённым только на время аудита.🔑 Шаг 2. SUID и SGID
# Бинарники с SUID/SGID, по дате изменения
sudo find / -xdev -type f -perm -4000 \
-printf '%TY-%Tm-%Td %p\n' 2>/dev/null | sort
Сравни список с чистой системой. Свежая дата у файла в
/tmp, /dev/shm или /var/tmp — почти наверняка бэкдор.🎭 Шаг 3. Capabilities: SUID, который find не видит
# Права root без бита SUID
getcap -r / 2>/dev/null
ВАЖНО:
cap_setuid даёт тот же root, что и SUID, но в поиске -perm -4000 НЕ появится. Проверил: файл с cap_setuid+ep дал обычному юзеру uid 0, а find -perm -4000 его не нашёл. Опасные: cap_setuid, cap_setgid, cap_dac_override, cap_sys_admin, cap_sys_ptrace.🚪 Шаг 4. PAM: вход мимо пароля
# Модули, дающие проход: pam_permit,
# pam_rootok не на месте, чужой pam_exec
grep -rnE "pam_permit|pam_exec|pam_rootok" \
/etc/pam.d/
sufficient pam_permit.so в common-auth — открытая дверь. pam_permit там штатно идёт только как required в хвосте стека.👤 Шаги 5–6. Скрытый root и sudo-лазейки
# Второй UID 0 — сразу к делу
awk -F: '$3==0 {print $1}' /etc/passwd
# NOPASSWD, добавленный в обход
sudo grep -rEn "NOPASSWD" /etc/sudoers /etc/sudoers.d/
🔐 Шаги 7–8. Чужие ключи и входы
# Ключи SSH у всех, кто есть
sudo cat /root/.ssh/authorized_keys \
/home/*/.ssh/authorized_keys 2>/dev/null
# Неудачные входы — брутфорс перед взломом
sudo lastb -Fai | head
Порядок: dontaudit и AVC → SUID и capabilities → PAM → root и sudo → ключи. Нашёл подозрительное — не «чисти», а снимай образ: подчищенный сервер невозможно расследовать. И держи эталонный список SUID и
getcap заранее — сравнивать будет с чем.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #SkillHunter@LinuxSkill
#Linux #Security #SELinux #Forensics #Hardening #SysAdmin
👍5
💀 OOM Killer убивает базу данных? 6 шагов отладки утечек RAM
OOM Killer снова прибил PostgreSQL, а
Шаг 1. Кого убили и почему
ВАЖНО:
Шаг 2. Что на самом деле занято
Смотри
Шаг 3. Давление памяти
Растущий
Шаг 4. Кто ест память
Шаг 5. Лимит и счётчик убийств cgroup
Шаг 6. Где растёт память процесса
Растёт
Убитый — не всегда виновник: OOM Killer бьёт по самому большому
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Memory #OOM #Troubleshooting #SysAdmin #DevOps
OOM Killer снова прибил PostgreSQL, а
free -m показывает гигабайты свободной памяти. Так бывает, когда память кончилась не у сервера, а у cgroup сервиса, или когда «кэш» на самом деле нельзя освободить. Показываю, как найти настоящую причину.Шаг 1. Кого убили и почему
sudo dmesg -T | grep -iE 'oom-kill|killed process'
oom-kill:constraint=CONSTRAINT_MEMCG,…,oom_memcg=/dbtest
Memory cgroup out of memory: Killed process 280 (python3)
ВАЖНО:
Memory cgroup out of memory и CONSTRAINT_MEMCG — память кончилась у cgroup, а не у сервера. Глобальная нехватка выглядит как Out of memory и CONSTRAINT_NONE. Проверил: процесс убит на лимите 100 МБ, хотя на хосте было 3.8 ГБ available.Шаг 2. Что на самом деле занято
free -m
grep -E 'MemAvailable|Shmem:|SUnreclaim' /proc/meminfo
Смотри
available, а не free плюс buff/cache. Подвох: tmpfs и shared memory сидят в buff/cache, но не освобождаются. У меня 800 МБ в /dev/shm остались в buff/cache и после drop_caches. Растёт SUnreclaim — течёт само ядро, смотри slabtop.Шаг 3. Давление памяти
cat /proc/pressure/memory
Растущий
some — ядро уже вытесняет страницы и тормозит процессы. Ранний сигнал до OOM.Шаг 4. Кто ест память
# сервисы systemd, сортировка по памяти
systemd-cgtop -m
# процессы по RSS
ps -eo pid,rss,comm --sort=-rss | head
Шаг 5. Лимит и счётчик убийств cgroup
cd /sys/fs/cgroup/system.slice/\<unit>.service
cat memory.max memory.current
grep oom_kill memory.events
oom_kill — сколько раз ядро уже убивало процессы этой cgroup.Шаг 6. Где растёт память процесса
# крупные области; повтори через минуту и сравни
sudo pmap -x \<PID> | sort -k3 -n | tail -5
Растёт
[ anon ] — утечка в куче приложения.Убитый — не всегда виновник: OOM Killer бьёт по самому большому
oom_score, а у базы с её буферами он часто максимальный. Пока ищешь утечку, прикрой БД: OOMScoreAdjust=-900 в override юнита через sudo systemctl edit \<unit>.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Memory #OOM #Troubleshooting #SysAdmin #DevOps
👍8🔥2
🔥 10 незаменимых флагов journalctl для моментального поиска логов
Журнал разросся до гигабайтов, а
1️⃣ Логи сервиса — сразу с конца или в реальном времени:
2️⃣ Только ошибки текущей загрузки:
3️⃣ Окно по времени:
4️⃣ Прошлая загрузка — почему сервер ребутнулся:
ВАЖНО: «no persistent journal was found» — журнал живёт в
5️⃣ Ядро прошлой загрузки:
OOM или паника перед ребутом видны здесь, а в
6️⃣ Какие значения вообще есть в журнале:
7️⃣ Фильтр по полям вместо grep:
Поля через пробел — И, через
8️⃣ Встроенный grep:
Подвох: шаблон в нижнем регистре ищет без учёта регистра, с заглавной буквой — строго. У меня
9️⃣ Вывод для скриптов и разбора:
🔟 Журнал съел диск или лежит на чужом:
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #journalctl #systemd #Logs #SysAdmin #DevOps
Журнал разросся до гигабайтов, а
journalctl | grep думает по несколько секунд на каждый запрос. Половина флагов journalctl ищет по индексу и отвечает мгновенно. Держи 10 — проверил на systemd 255.1️⃣ Логи сервиса — сразу с конца или в реальном времени:
journalctl -u nginx -e
journalctl -u nginx -f
2️⃣ Только ошибки текущей загрузки:
journalctl -p err -b
-p err — это уже err и всё серьёзнее. Диапазон: -p warning..err.3️⃣ Окно по времени:
journalctl --since "1 hour ago"
journalctl --since "09:00" --until "09:30"
4️⃣ Прошлая загрузка — почему сервер ребутнулся:
journalctl --list-boots
journalctl -b -1 -p err
ВАЖНО: «no persistent journal was found» — журнал живёт в
/run и умирает с перезагрузкой. Лечится так: sudo mkdir -p /var/log/journal и рестарт systemd-journald.5️⃣ Ядро прошлой загрузки:
journalctl -k -b -1
OOM или паника перед ребутом видны здесь, а в
dmesg их уже нет.6️⃣ Какие значения вообще есть в журнале:
journalctl -F _SYSTEMD_UNIT
journalctl -F SYSLOG_IDENTIFIER
7️⃣ Фильтр по полям вместо grep:
journalctl _COMM=sshd _UID=0
journalctl _PID=1234 + _COMM=cron
Поля через пробел — И, через
+ — ИЛИ. Поле читается по индексу: на 300 000 записей journalctl | grep думал 3.4 с, фильтр по полю — 0.025 с.8️⃣ Встроенный grep:
journalctl -u nginx -g 'timeout|refused'
Подвох: шаблон в нижнем регистре ищет без учёта регистра, с заглавной буквой — строго. У меня
-g 'Payment' не нашёл ни одной строки с payment. И -g индекса не видит: 1.4 с против 0.03 с у поля — сначала сузь выборку.9️⃣ Вывод для скриптов и разбора:
journalctl -u nginx -n 1 -o json-pretty
journalctl -u nginx -o cat
json-pretty покажет все поля записи — так и узнаёшь, по чему фильтровать. cat — только текст.🔟 Журнал съел диск или лежит на чужом:
journalctl --disk-usage
sudo journalctl --vacuum-size=1G
# журнал с другого диска, например в rescue
journalctl -D /mnt/var/log/journal
--vacuum удаляет только архивные файлы, активный не трогает.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #journalctl #systemd #Logs #SysAdmin #DevOps
👍8
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
💀 Ошибка No space left, хотя свободны гигабайты? Диагноз inode
apt падает с «No space left on device», сервис перестал писать логи, а
Шаг 1. Проверяем inode, а не место
На тестовой ФС
ВАЖНО: резерва под root, как у места на диске, тут нет. У меня root не смог создать даже конфиг — встают все сервисы разом.
Шаг 2. Ищем каталог-пожиратель
Частые виновники: PHP-сессии в
Шаг 3. Удаляем правильно
Подвох:
Шаг 4. Понять, сколько inode у ФС
На ext4 число inode задаётся при
Чтобы не повторилось, найди источник — крон для сессий, logrotate — и добавь
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Troubleshooting #Storage #ext4 #SysAdmin #DevOps
apt падает с «No space left on device», сервис перестал писать логи, а
df -h показывает гигабайты свободного места. Место ни при чём — кончились inode: у каждого файла, даже пустого, свой номер, и на ext4 их число конечно.Шаг 1. Проверяем inode, а не место
df -i /
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/loop0 5024 5024 0 100% /mnt/ino
На тестовой ФС
df -h в этот момент показывал 1% занятого места.ВАЖНО: резерва под root, как у места на диске, тут нет. У меня root не смог создать даже конфиг — встают все сервисы разом.
Шаг 2. Ищем каталог-пожиратель
# Где больше всего inode, с учётом вложенных
sudo du --inodes -x / 2>/dev/null | sort -n | tail
# Файлов прямо в каталоге
sudo find / -xdev -printf '%h\n' | sort | uniq -c \
| sort -rn | head
Частые виновники: PHP-сессии в
/var/lib/php/sessions, очередь почты, кэш приложения, старые linux-headers в /usr/src — их убирает apt autoremove --purge.Шаг 3. Удаляем правильно
# Сначала посмотри, что попадёт под удаление
sudo find /var/lib/php/sessions -type f -mmin +1440 | head
sudo find /var/lib/php/sessions -type f -mmin +1440 -delete
Подвох:
rm /path/* на сотнях тысяч файлов падает с «Argument list too long» — глоб не влезает в командную строку. Проверил на 300 000 файлов: rm отказался, find -delete справился за 1.7 с.Шаг 4. Понять, сколько inode у ФС
sudo tune2fs -l /dev/\<disk> | grep -i 'inode count'
На ext4 число inode задаётся при
mkfs — по умолчанию одна на 16 КБ. Добавить их можно только вместе с размером: resize2fs при расширении ФС вдвое удвоил и inode. Под миллионы мелких файлов форматируй с mkfs.ext4 -i 4096 или бери XFS — там inode выделяются динамически.Чтобы не повторилось, найди источник — крон для сессий, logrotate — и добавь
IUse% в мониторинг рядом с Use%.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Troubleshooting #Storage #ext4 #SysAdmin #DevOps
👍10
🔥 10 незаменимых фишек rsync, о которых забывают администраторы
rsync знают все. А потом бэкап молча теряет ACL,
1️⃣ Слэш в конце решает всё:
2️⃣ Полный архив, а не почти:
ВАЖНО:
3️⃣ Посмотреть, что изменится:
4️⃣ Страховка для
ВАЖНО: если источник пуст — скажем, диск не примонтировался, —
5️⃣ Докачка после обрыва:
6️⃣ Сверка по содержимому:
Подвох: rsync пропускает файл, если совпали размер и время изменения. У меня новое содержимое с прежними размером и mtime не скопировалось, с
7️⃣ Снапшоты без лишнего места:
Неизменённые файлы становятся хардлинками на прошлый снапшот: два снапшота по 51 МБ заняли 51 МБ.
8️⃣ Нестандартный порт и лимит скорости:
9️⃣ Исключения списком:
В файле по шаблону на строку:
🔟 Восстановление с rescue-системы:
По умолчанию владельцы сопоставляются по именам: в rescue тот же
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #rsync #Backup #CheatSheet #SysAdmin #DevOps
rsync знают все. А потом бэкап молча теряет ACL,
--delete стирает копию, а обрыв связи начинает передачу с нуля. Держи 10 приёмов — каждый проверил на rsync 3.2.7.1️⃣ Слэш в конце решает всё:
rsync -a src/ dst/ # содержимое src → в dst
rsync -a src dst/ # сама папка → dst/src
2️⃣ Полный архив, а не почти:
rsync -aAXH src/ dst/
ВАЖНО:
-a не сохраняет ACL, xattr и хардлинки. Проверил: после -a у копии пропали ACL и xattr, а хардлинк стал отдельным файлом. С xattr уходят и метки SELinux.3️⃣ Посмотреть, что изменится:
rsync -ani --delete src/ dst/
-n — ничего не трогать, -i — что и почему. Строки *deleting будут удалены.4️⃣ Страховка для
--delete:rsync -a --delete --max-delete=100 src/ dst/
ВАЖНО: если источник пуст — скажем, диск не примонтировался, —
--delete сотрёт бэкап целиком и вернёт 0. У меня так и вышло. --max-delete остановит удаление с кодом 25.5️⃣ Докачка после обрыва:
rsync -aP big.iso user@host:/data/
-P = --partial --progress. Без --partial обрыв выбрасывает недокачанное — у меня не осталось ничего. С ним 29 МБ из 100 сохранились и повторно не шли. Общий прогресс — --info=progress2.6️⃣ Сверка по содержимому:
rsync -ac src/ dst/
Подвох: rsync пропускает файл, если совпали размер и время изменения. У меня новое содержимое с прежними размером и mtime не скопировалось, с
-c — скопировалось. Цена — чтение всех файлов.7️⃣ Снапшоты без лишнего места:
rsync -a --link-dest=../2026-10-16 src/ snap/2026-10-17/
Неизменённые файлы становятся хардлинками на прошлый снапшот: два снапшота по 51 МБ заняли 51 МБ.
8️⃣ Нестандартный порт и лимит скорости:
rsync -a -e 'ssh -p 2222' --bwlimit=10M \
src/ user@host:/data/
--bwlimit — в мегабайтах в секунду, не в мегабитах: 50 МБ ушли ровно за 5 с.9️⃣ Исключения списком:
rsync -a --exclude-from=exclude.txt src/ dst/
В файле по шаблону на строку:
cache/, *.tmp. Ведущий / привязывает шаблон к корню источника.🔟 Восстановление с rescue-системы:
rsync -a --numeric-ids backup/ /mnt/root/
По умолчанию владельцы сопоставляются по именам: в rescue тот же
mysql может иметь другой UID, и файлы получат чужого владельца. --numeric-ids переносит UID и GID как есть.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #rsync #Backup #CheatSheet #SysAdmin #DevOps
👍9
⚡️ Онлайн-митап IT_ONE: Между кодом и продом
Три прикладных доклада для тех, кто отвечает за стабильность инфраструктуры. Обсудим на встрече защиту Helm-чартов
от некорректных данных, научим писать надежные проверки
на helm-unittest и разберем развертывание собственной LLM-модели без лимитов на токены.
12 ноября
18:00 (мск), онлайн
Регистрация: по ссылке
Приглашаем разработчиков, DevOps-, QA- и SRE-инженеров, тимлидов и архитекторов.
В программе митапа — три выступления:
Приходи со своими рабочими вопросами — можно будет обсудить их с экспертами. Авторы лучших вопросов получат мерч IT_ONE: футболку, стикеры и плед.
📎 Всем зарегистрированным участникам после митапа отправим презентации спикеров и другие полезные материалы.
Регистрируйся до 11 ноября, 23:59 (мск)
Три прикладных доклада для тех, кто отвечает за стабильность инфраструктуры. Обсудим на встрече защиту Helm-чартов
от некорректных данных, научим писать надежные проверки
на helm-unittest и разберем развертывание собственной LLM-модели без лимитов на токены.
12 ноября
18:00 (мск), онлайн
Регистрация: по ссылке
Приглашаем разработчиков, DevOps-, QA- и SRE-инженеров, тимлидов и архитекторов.
В программе митапа — три выступления:
1️⃣ Персональный ИИ своими руками.
Руслан Кашафутдинов расскажет, как развернуть свою ИИ-модель и работать без квот облачных сервисов.2️⃣ Helm-чарты: когда они действительно нужны.
Виталий Перваков разберет защиту от некорректных данных и сравнит инструменты проверки конфигураций.3️⃣ Стабильные unit-тесты для Helm-чартов.
Андрей Слатимов покажет, как с помощью helm-unittest находить ошибки шаблонизации и проверять обратную совместимость.
Приходи со своими рабочими вопросами — можно будет обсудить их с экспертами. Авторы лучших вопросов получат мерч IT_ONE: футболку, стикеры и плед.
Регистрируйся до 11 ноября, 23:59 (мск)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
💀 Тормозит диск в проде? 5 шагов диагностики iowait без лишней паники
Сервер отвечает с задержкой в секунды,
Шаг 1. Понять, что такое wa
ВАЖНО: iowait — это простой CPU, а не нагрузка диска. Проверил: при записи на диск
Шаг 2. Кто завис и на чём
Подвох:
Шаг 3. Какой диск тормозит
Смотри
Шаг 4. Кто нагружает
Подвох: колонка IO% в iotop показывает
Шаг 5. Железо и ядро
Вместо «диск тормозит, перезагрузим» — конкретный процесс, место, где он ждёт, и конкретный диск.
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Troubleshooting #Storage #Performance #SysAdmin #DevOps
Сервер отвечает с задержкой в секунды,
top показывает wa под 90%, процессы висят в состоянии D. Прежде чем винить диск — пять шагов, которые покажут, кто ждёт, чего и почему.Шаг 1. Понять, что такое wa
vmstat 1
wa — время, когда CPU простаивал, пока висел I/O. b — процессы, ждущие ввода-вывода.ВАЖНО: iowait — это простой CPU, а не нагрузка диска. Проверил: при записи на диск
wa было 86%, добавил CPU-нагрузку — wa упало до 0, а процесс так же висел в b. Низкий iowait не значит, что с диском всё хорошо.Шаг 2. Кто завис и на чём
ps -eo state,pid,wchan:24,cmd | awk '$1 ~ /D/'
sudo cat /proc/\<PID>/stack
wchan и стек ядра показывают, где именно ждёт процесс. Функции nfs_* — виноват NFS, а не локальный диск.Подвох:
b в vmstat считает только ждущих I/O. Процесс на замороженной ФС у меня висел в D, а b показывал 0 — поэтому D-процессы ищи через ps.Шаг 3. Какой диск тормозит
iostat -xz 1
Смотри
r_await, w_await и очередь aqu-sz. Это средние за секунду — редкие зависшие запросы в них тонут, хвост покажет biolatency.bt.Шаг 4. Кто нагружает
sudo pidstat -d 1
sudo iotop -oPa
Подвох: колонка IO% в iotop показывает
?unavailable? — с ядра 5.14 учёт задержек выключен по умолчанию. Включается sudo sysctl kernel.task_delayacct=1 — после диагностики верни 0, учёт стоит ресурсов. pidstat -d работает и без него.Шаг 5. Железо и ядро
sudo dmesg -T | grep -iE 'blocked for more|I/O error|reset'
blocked for more than 120 seconds — ядро само сообщает о процессах, застрявших в D, и печатает их стек. I/O error и reset — уже железо, смотри smartctl -a.Вместо «диск тормозит, перезагрузим» — конкретный процесс, место, где он ждёт, и конкретный диск.
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Troubleshooting #Storage #Performance #SysAdmin #DevOps
👍6
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
🚨 Сервер не поднимается после обновления? 7 шагов спасения из chroot
После ребута — kernel panic или «dropping to emergency shell». Без паники: загружаемся с LiveCD или rescue-образа провайдера и чиним систему изнутри. Держи чек-лист — проверил на Ubuntu 24.04.
🔍 Шаг 1. Найти корень
LVM — сначала
💽 Шаг 2. Смонтировать корень и /boot
Подвох: забыл отдельный
🔗 Шаг 3. Пробросить /dev, /proc, /sys
ВАЖНО: без этого инструменты в chroot падают. Проверил:
🚪 Шаг 4. Войти
🧩 Шаг 5. Пересобрать initramfs
Если сборка упала, старый образ остаётся на месте — у меня так и было. dracut по умолчанию собирает образ под найденное железо; не уверен —
📄 Шаг 6. Проверить fstab
⚙️ Шаг 7. GRUB
На RHEL с UEFI
Выход:
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Recovery #GRUB #Troubleshooting #SysAdmin #DevOps
После ребута — kernel panic или «dropping to emergency shell». Без паники: загружаемся с LiveCD или rescue-образа провайдера и чиним систему изнутри. Держи чек-лист — проверил на Ubuntu 24.04.
🔍 Шаг 1. Найти корень
lsblk -f
LVM — сначала
vgchange -ay, LUKS — cryptsetup open.💽 Шаг 2. Смонтировать корень и /boot
sudo mount /dev/\<root> /mnt
sudo mount /dev/\<boot> /mnt/boot # если отдельный
sudo mount /dev/\<esp> /mnt/boot/efi # если UEFI
Подвох: забыл отдельный
/boot — initramfs и GRUB запишутся в пустую папку на корне, а настоящий раздел останется сломанным.🔗 Шаг 3. Пробросить /dev, /proc, /sys
for d in dev proc sys run; do
sudo mount --rbind /$d /mnt/$d
sudo mount --make-rslave /mnt/$d
done
ВАЖНО: без этого инструменты в chroot падают. Проверил:
ps просит «mount -t proc proc /proc», grub-probe пишет «cannot find a device for / (is /dev mounted?)». --make-rslave нужен, чтобы umount -R потом не отмонтировал /dev у live-системы.🚪 Шаг 4. Войти
sudo chroot /mnt /bin/bash
🧩 Шаг 5. Пересобрать initramfs
update-initramfs -u -k all # Debian/Ubuntu
dracut -f --regenerate-all # RHEL/Fedora
Если сборка упала, старый образ остаётся на месте — у меня так и было. dracut по умолчанию собирает образ под найденное железо; не уверен —
--no-hostonly. Драйвер диска в образе: lsinitramfs или lsinitrd + grep nvme.📄 Шаг 6. Проверить fstab
blkid
findmnt --verify
[E] — диск, без которого загрузка уйдёт в emergency. Некритичным дискам ставь nofail: у меня с ним ошибка по отсутствующему диску стала предупреждением.⚙️ Шаг 7. GRUB
grub-install /dev/\<disk> && update-grub # Ubuntu
grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL
На RHEL с UEFI
grub2-install не запускают — переустанавливают пакеты grub2-efi-x64 и shim-x64.Выход:
exit, sudo umount -R /mnt, перезагрузка. И сделай снапшот перед следующим обновлением ядра — откат за минуту лучше chroot за час.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Recovery #GRUB #Troubleshooting #SysAdmin #DevOps
👍6
🚀 Безопасный чистильщик Docker: 39 строк Bash без риска снести лишнее
Docker съел диск, а
Что делает: удаляет остановленные контейнеры, неиспользуемые образы и кэш сборки старше заданного возраста, плюс анонимные тома. Всё с меткой
Три ловушки, которые он обходит
Данные БД держи на именованных томах. Анонимный том живёт ровно столько, сколько его контейнер.
Запуск по крону
Логи контейнеров скрипт не трогает — их ограничивай через
❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Docker #Bash #Scripting #SysAdmin #DevOps
Docker съел диск, а
docker system prune -af --volumes из первого же гайда удаляет остановленную базу вместе с данными. Держи 39 строк, которые чистят мусор и не трогают то, что помечено. Проверил на Docker 29.#!/usr/bin/env bash
# docker-clean.sh [возраст, по умолчанию 168h]
# Чистит мусор Docker и не трогает данные.
set -euo pipefail
AGE=${1:-168h}
[[ $AGE =~ ^[0-9]+[smh]$ ]] ||
{ echo "AGE: например 168h" >&2; exit 2; }
exec 9> /run/lock/docker-clean.lock
flock -n 9 || { echo "уже работает" >&2; exit 0; }
# До Docker 23 (API 1.42) volume prune сносил
# и именованные тома — на старых версиях их пропускаем
API=$(docker version -f '{{.Server.APIVersion}}')
MIN=$(printf '%s\n' 1.42 "$API" | sort -V | head -1)
docker system df
# until у контейнера считается от СОЗДАНИЯ, не от остановки:
# старую БД на обслуживании спасёт только метка keep
docker container prune -f \
--filter "until=$AGE" --filter "label!=keep"
# Образы без контейнеров, собранные раньше AGE
docker image prune -af \
--filter "until=$AGE" --filter "label!=keep"
# Кэш сборки — часто самый тяжёлый
docker builder prune -af --filter "until=$AGE"
# Без -a — только анонимные тома, именованные целы
if [[ $MIN == 1.42 ]]; then
docker volume prune -f --filter "label!=keep"
else
echo "Docker API $API < 1.42: тома пропускаю" >&2
fi
docker system df
Что делает: удаляет остановленные контейнеры, неиспользуемые образы и кэш сборки старше заданного возраста, плюс анонимные тома. Всё с меткой
keep не трогает. До и после печатает docker system df.Три ловушки, которые он обходит
docker system prune -af --volumes у меня удалил остановленный контейнер «базы» вместе с анонимным томом и данными. Именованный том уцелел: с Docker 23 prune без -a трогает только анонимные. На старых версиях уходили и именованные.until у контейнера считается от создания. Контейнер, созданный 4 с назад и остановленный только что, ушёл под until=3s. Спасает только метка: docker run --label keep ….Данные БД держи на именованных томах. Анонимный том живёт ровно столько, сколько его контейнер.
Запуск по крону
# по воскресеньям в 04:00, мусор старше недели
0 4 * * 0 /usr/local/bin/docker-clean.sh 168h
Логи контейнеров скрипт не трогает — их ограничивай через
max-size в daemon.json.❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Docker #Bash #Scripting #SysAdmin #DevOps
🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8