LinuxSkill - Сводки с прода и Шпаргалки
10.6K subscribers
68 photos
102 videos
12 files
531 links
Следим за новостями Linux, DevOps и ИБ, чтобы быть готовым к любым факапам.
Бонусом — плотные шпаргалки и чеклисты для ежедневной работы в терминале.

📩 По всем вопросам: @chorapov

Зеркало в MAX: https://max.ru/LinuxSkill

РКН https://vk.cc/cMUwm4
Download Telegram
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
# Правила 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, а 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 для моментального поиска логов

Журнал разросся до гигабайтов, а 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», сервис перестал писать логи, а 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, --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-инженеров, тимлидов и архитекторов.
 
В программе митапа — три выступления:
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 без лишней паники

Сервер отвечает с задержкой в секунды, 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. Найти корень
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 съел диск, а 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
Как доставлять приложение в продакшен без ручных операций и зависимости от внешних сервисов?

На открытом уроке покажем связку GitLab CI и Argo CD внутри Kubernetes-кластера: от сборки и тестирования кода до автоматической доставки приложения.

За 90 минут соберём работающий конвейер и разберём, как настроить автономный процесс CI/CD внутри собственной инфраструктуры.

Урок проходит в преддверии старта курса «Инфраструктурная платформа на основе Kubernetes» 16 ноября в 20:00 МСК. Все участники получат скидку на обучение. Принять участие: https://otus.pw/oYXOo/

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
💀 Потеря пакетов на 10GbE интерфейсе? 6 шагов отладки drop-ов в ядре

Приложение теряет трафик, ping показывает редкие пропуски под нагрузкой, а сетевики клянутся, что коммутатор чист. Часто они правы: пакет доходит до сервера и умирает внутри — в карте, ядре или сокете.

Шаг 1. Счётчики интерфейса
ip -s -s link show \<iface>

Смотри dropped, missed и fifo в RX. Растут они — теряем на этом сервере, а не в сети.

Шаг 2. Счётчики карты
ethtool -S \<iface> | grep -iE 'drop|miss|fifo|buf' \
| grep -v ': 0$'

Имена зависят от драйвера: у Intel это rx_missed_errors, у Mellanox — rx_out_of_buffer. Оба значат: кадр пришёл, а положить его некуда.

Шаг 3. Кольцевой буфер карты
ethtool -g \<iface>
sudo ethtool -G \<iface> rx 4096

Выше «Pre-set maximums» не поставить — у меня карта ответила «requested ring size exceeds maximum». И на многих драйверах -G на секунду перезапускает интерфейс: по SSH через него же это обрыв.

Шаг 4. Прерывания по ядрам
grep \<iface> /proc/interrupts
ethtool -l \<iface>

ВАЖНО: все счётчики в колонке CPU0 — одно ядро разгребает весь трафик, не успевает опустошать ring-буфер, и карта дропает. Лечится irqbalance, привязкой через /proc/irq/\<N>/smp_affinity_list и большим числом очередей: ethtool -L \<iface> combined 8. Очередь одна, как у virtio в виртуалке, — раздай обработку через RPS:
# ff — маска для CPU 0–7
echo ff | sudo tee \
/sys/class/net/\<iface>/queues/rx-0/rps_cpus


Шаг 5. Очередь ядра
cat /proc/net/softnet_stat

По строке на CPU, значения в hex. Второй столбец — дропы из-за net.core.netdev_max_backlog, третий — ядро не успело разгрести пакеты за отведённый бюджет, крути net.core.netdev_budget.

Шаг 6. Сокет приложения
nstat -az UdpRcvbufErrors TcpExtTCPRcvQDrop

Подвох: пакет дошёл до сервера и умер в буфере сокета — приложение не успевает читать. Проверил: медленный UDP-слушатель потерял 19 994 пакета из 20 000, и все они в UdpRcvbufErrors. Лечится буфером в приложении (SO_RCVBUF) и net.core.rmem_max.

Порядок: интерфейс → карта → прерывания → ядро → сокет. На каком уровне растут счётчики, там и чини.

❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Networking #Performance #ethtool #SysAdmin #DevOps
👍5