Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

🐧 Linux Cheat Sheet — шпаргалка по командам Linux

Самая удобная шпаргалка по Linux и Bash на русском: теория простым языком (как устроены файлы, процессы, права, память, загрузка и сеть), команды терминала, права доступа, процессы, сеть, SSH, systemd, grep/sed/awk, Vim и готовые однострочники — с примерами. А для тех, кто идёт дальше, — продвинутый уровень: Bash для профи, LVM и RAID, трассировка и производительность, ядро, безопасность, контейнеры, восстановление системы и вопросы с собеседований. И практикум: 8 пошаговых сценариев из реальной работы и 28 задач с решениями на учебном полигоне.

License: MIT Language Bash Linux

⭐ Поставь звезду, чтобы шпаргалка всегда была под рукой!


Для кого: начинающие пользователи Linux, студенты, DevOps / SRE-инженеры, системные администраторы, разработчики, все, кто готовится к собеседованию или экзамену (LPIC, RHCSA, Linux+). Работает в Ubuntu, Debian, Linux Mint, CentOS, RHEL, Rocky, AlmaLinux, Fedora, Arch, Manjaro, openSUSE, WSL и на macOS (большая часть команд).

Легенда

ЗначокЗначение
🟢База — нужно знать каждому
🟡Продвинутый уровень
🔴Опасно: может удалить данные или сломать систему
💡Совет / лайфхак

📺 Лучшие бесплатные каналы для изучения Linux на русском

  • 🖥 Linux Academy — с помощью понятных картинок и коротких видео авторы объясняют сложные концепции и учат профессиональному подходу в работе с Linux.
  • ⚡️ Kali Linux — авторский канал, который научит тебя хакингу и защите информации с нуля.
  • 🧠 Machine learning — показываем на примере, как использовать AI, который может генерировать готовые базы данных, код; разбираем всё, что нужно знать в области ИИ.
  • 📚 Linux Books — канал с книгами по Linux: наверное, самая большая подборка — около 320 книг бесплатно.
  • 🔝 Здесь мы собрали целую кладезь полезных Linux-ресурсов для прокачки.

📚 Содержание

  1. 🧠 Теория: как устроен Linux — ядро, файлы, inode, права, процессы, потоки, PATH, кавычки, память, загрузка, ФС, пакеты, сеть, SSH-ключи
  2. Первые шаги и справка
  3. Навигация по файловой системе
  4. Работа с файлами и папками
  5. Просмотр содержимого файлов
  6. Поиск: find, locate, grep
  7. Права доступа: chmod, chown
  8. Пользователи и группы, sudo
  9. Процессы и сигналы
  10. Информация о системе
  11. Диски и файловые системы
  12. Сеть
  13. SSH, SCP, rsync
  14. Архивы и сжатие
  15. Пакетные менеджеры
  16. Systemd и службы
  17. Логи и journalctl
  18. Обработка текста: sed, awk, cut, sort
  19. Перенаправление, пайпы, xargs
  20. Bash: переменные и скрипты
  21. Горячие клавиши терминала
  22. Vim — минимум для выживания
  23. Cron — планировщик задач
  24. Файрвол: ufw, firewalld, iptables
  25. Структура каталогов Linux (FHS)
  26. Полезные однострочники
  27. 🟡 Bash для профи: массивы, раскрытие параметров, trap
  28. 🟡 LVM, RAID и снапшоты
  29. 🟡 Продвинутая сеть
  30. 🟡 Производительность и трассировка
  31. 🟡 Systemd для профи
  32. 🟡 Ядро: sysctl, модули, лимиты, cgroups
  33. 🟡 Безопасность и hardening
  34. 🟡 Контейнеры изнутри: namespaces, Docker, Podman
  35. 🔴 Восстановление системы
  36. 🎯 Вопросы с собеседований
  37. Диагностика: что делать, если…
  38. Опасные команды
  39. 🧰 Практические сценарии: пошаговые рецепты
  40. 🎓 Практикум: задачи с решениями
  41. Глоссарий

🧠 0. Теория: как устроен Linux

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

0.1. Ядро, дистрибутив, оболочка

┌─────────────────────────────────────────────┐
│  Пользователь                               │
├─────────────────────────────────────────────┤
│  Оболочка (bash, zsh) / графика (GNOME, KDE)│  ← ты вводишь команды
├─────────────────────────────────────────────┤
│  Утилиты и библиотеки (coreutils, glibc)    │  ← ls, cp, grep…
├──────────────── системные вызовы ───────────┤  ← open(), read(), fork()
│  Ядро Linux (kernel space)                  │  ← процессы, память, ФС, сеть, драйверы
├─────────────────────────────────────────────┤
│  Железо: CPU, RAM, диски, сеть              │
└─────────────────────────────────────────────┘
ТерминЧто это
Ядро (kernel)Собственно «Linux». Управляет железом, памятью, процессами. Версия: uname -r
ДистрибутивЯдро + утилиты GNU + пакетный менеджер + настройки: Ubuntu, Fedora, Arch…
User space / kernel spaceПрограммы работают в пространстве пользователя и просят ядро о действиях через системные вызовы
ТерминалОкно-программа, которая показывает текст (GNOME Terminal, Konsole, iTerm)
Консоль / TTYТекстовый терминал без графики (Ctrl+Alt+F3)
Оболочка (shell)Интерпретатор команд внутри терминала: bash, zsh, fish, sh

0.2. Анатомия команды

ls  -l -a  --color=auto  /etc /var
──  ─────  ────────────  ─────────
│     │         │            └── аргументы (с чем работать)
│     │         └── длинная опция (--слово)
│     └── короткие опции (можно слить: -la)
└── команда (программа, встроенная команда или алиас)
  • Регистр важен: File.txt и file.txt — разные файлы.
  • -- означает «дальше опций нет»: rm -- -file.txt удалит файл с именем -file.txt.
  • Пробелы в именах экранируй: "My Docs" или My\ Docs.

0.3. «Всё есть файл»

В Linux файлом представлено почти всё: документы, папки, диски (/dev/sda), терминалы (/dev/tty), процессы (/proc/1234), даже «чёрная дыра» /dev/null. Поэтому одни и те же инструменты (cat, echo, >) работают со всем.

Символ в ls -lТипПример
-Обычный файл/etc/hosts
dКаталог/home
lСимволическая ссылка/bin → usr/bin
cСимвольное устройство/dev/tty, /dev/null
bБлочное устройство/dev/sda
sСокет/run/docker.sock
pИменованный канал (FIFO)создаётся mkfifo

Пути: абсолютный начинается с / (/var/log/syslog) и работает откуда угодно; относительный считается от текущей папки (../log/syslog). Расширений как обязательной части нет — тип определяется содержимым (file), а не суффиксом. Файлы, начинающиеся с точки (.bashrc), — скрытые.

0.4. Inode, жёсткие и символические ссылки

Имя файла — это лишь запись в каталоге, указывающая на inode — структуру с метаданными (владелец, права, размер, даты, адреса блоков данных). Сам inode имени не хранит. Номер inode: ls -i.

имя "report.txt" ──┐
                   ├──▶ inode #1234 ──▶ данные на диске
hardlink "copy" ───┘
symlink "link"  ──▶ "report.txt"   (хранит путь, а не inode)
Жёсткая ссылка (ln)Символическая ссылка (ln -s)
Указывает наinodeпуть (имя)
Удалили оригиналДанные живыСсылка «битая»
Между разделами❌✅
На каталоги❌✅

Данные удаляются, когда исчезает последнее имя и файл никем не открыт — поэтому удалённый лог может продолжать занимать место, пока процесс его держит (lsof +L1).

0.5. Пользователи, root и права

  • Каждый пользователь имеет UID, группа — GID. root = UID 0 и может всё.
  • Системные пользователи (www-data, postgres) нужны, чтобы службы работали с минимальными правами.
  • sudo выполняет одну команду от root и пишет это в лог; su полностью переключает пользователя. Работать постоянно под root — плохая практика.
  • Права проверяются по порядку: владелец → группа → остальные, срабатывает первая подходящая категория.
  • Для каталога права значат другое:
ПравоДля файлаДля каталога
rЧитать содержимоеВидеть список файлов
wИзменять содержимоеСоздавать, удалять, переименовывать файлы внутри
xЗапускать как программуВходить (cd) и обращаться к файлам

💡 Удалить файл можно, даже не имея прав на сам файл, — достаточно w на каталог. Именно от этого защищает sticky-бит на /tmp.

0.6. Процессы

Процесс — запущенная программа: свой PID, память, открытые файлы, владелец. Каждый процесс создаётся другим (родителем, PPID) через fork() + exec(). Прародитель всех — systemd с PID 1. Демон — фоновый процесс без терминала (sshd, nginx).

Состояние (ps STAT)Значение
RВыполняется или готов к выполнению
SСпит, ждёт события (нормальное состояние большинства)
DНепрерываемый сон — ждёт диск/сеть, kill -9 не поможет
TОстановлен (Ctrl+Z)
ZЗомби — завершился, но родитель не забрал код выхода

Приоритет (nice): от -20 (самый высокий) до 19 (самый низкий), по умолчанию 0. Понижать может любой, повышать — только root.

0.7. Потоки, пайпы и коды возврата

У каждого процесса три стандартных потока:

             ┌──────────┐ ──▶ 1 stdout (результат)
 0 stdin ──▶ │ команда  │
             └──────────┘ ──▶ 2 stderr (ошибки)

Пайп | соединяет stdout одной программы со stdin другой — так из маленьких утилит собираются мощные конвейеры (философия Unix: «делай одну вещь и делай её хорошо»).

Каждая команда возвращает код выхода (echo $?): 0 — успех, всё остальное — ошибка. На этом построены &&, || и if. Частые коды: 1 — общая ошибка, 2 — неверное использование, 126 — нет прав на запуск, 127 — команда не найдена, 128+N — убит сигналом N (130 = Ctrl+C, 137 = kill -9).

0.8. Как оболочка находит и запускает команду

Когда ты вводишь ls, bash по порядку проверяет: алиас → функция → встроенная команда (builtin) → файл в каталогах из $PATH. Посмотреть: type -a ls.

echo $PATH                        # /usr/local/bin:/usr/bin:/bin — поиск слева направо
./script.sh                       # текущая папка НЕ входит в PATH — нужен ./
export PATH="$HOME/.local/bin:$PATH"   # добавить свою папку (в ~/.bashrc)

До запуска оболочка сама раскрывает строку: ~ → домашняя папка, $VAR → значение, $(cmd) → вывод команды, *.txt → список файлов. Программа получает уже раскрытые аргументы.

Переменные окружения наследуются дочерними процессами (только после export). Важные: HOME, USER, PATH, SHELL, PWD, LANG, EDITOR.

Файлы настройки bash: ~/.bashrc — для каждого нового интерактивного терминала (алиасы, промпт); ~/.profile / ~/.bash_profile — при входе в систему (переменные окружения); /etc/profile — для всех пользователей.

0.9. Кавычки, glob и регулярные выражения

ЗаписьЧто происходитПример → результат
'...'Всё буквально, ничего не раскрываетсяecho '$HOME' → $HOME
"..."Раскрываются $VAR и $(...), но не * и пробелыecho "$HOME" → /home/user
без кавычекРаскрывается всё + разбиение по пробеламопасно для имён с пробелами
\Экранирует один символecho \$HOME → $HOME

💡 Правило: всегда бери переменные в двойные кавычки — "$file", а не $file.

Glob (маски файлов) раскрывает оболочка; regex (регулярные выражения) понимают grep, sed, awk. Выглядят похоже, но значат разное:

СмыслGlobRegex
Любая строка*.*
Один любой символ?.
Один из набора[abc][abc]
Начало / конец строки—^ / $
Повтор 1+ раз—+ (в grep -E)
Цифра[0-9][0-9] или \d (в grep -P)

0.10. Память и нагрузка

$ free -h
               total        used        free      shared  buff/cache   available
Mem:            15Gi       4.1Gi       1.2Gi       300Mi        10Gi        11Gi
  • free мало — это нормально: Linux занимает свободную память под кэш диска (buff/cache) и отдаёт её программам по первому требованию.
  • Смотри на available — сколько реально доступно для новых программ.
  • Swap — место на диске для выгрузки редко используемой памяти. Активный swap = нехватка RAM и тормоза.
  • OOM killer — когда память кончилась полностью, ядро убивает самый «тяжёлый» процесс (dmesg -T | grep -i oom).
  • Load average (uptime) — среднее число процессов, которые работают или ждут CPU/диск, за 1, 5 и 15 минут. Сравнивай с числом ядер (nproc): на 4 ядрах load 4.0 = 100% загрузка.

0.11. Как загружается Linux

Питание → UEFI/BIOS → загрузчик GRUB → ядро + initramfs → systemd (PID 1) → target → логин
          проверка     выбор ядра       драйверы, монтирует   запускает службы
          железа                        корневую ФС
systemd targetСтарый runlevelЧто это
poweroff.target0Выключение
rescue.target1Однопользовательский режим восстановления
multi-user.target3Сервер: сеть, без графики
graphical.target5Рабочий стол
reboot.target6Перезагрузка

Текущий: systemctl get-default, сменить: sudo systemctl set-default multi-user.target.

0.12. Файловые системы и монтирование

В Linux нет «дисков C: и D:» — есть одно дерево от /, а разделы и флешки монтируются в его папки (/home, /mnt/usb). Список при загрузке задаётся в /etc/fstab.

ФСГде применяетсяОсобенности
ext4Стандарт для большинства дистрибутивовНадёжная, журналируемая
XFSRHEL, большие серверыБыстрая на больших файлах, не уменьшается
BtrfsFedora, openSUSEСнапшоты, сжатие, copy-on-write
ZFSNAS, серверы храненияСнапшоты, RAID, контроль целостности
vfat / exFATФлешки, EFI-разделСовместимость с Windows/macOS, без прав Unix
NTFSДиски WindowsЧтение/запись через ntfs3
tmpfs/tmp, /runЖивёт в RAM, исчезает после перезагрузки

Журналирование — ФС сначала записывает намерение в журнал, поэтому после внезапного отключения питания она быстро восстанавливается без полной проверки.

0.13. Пакеты и репозитории

  • Пакет (.deb, .rpm) — архив с программой, метаданными и списком зависимостей.
  • Репозиторий — сервер с пакетами, подписанными ключом дистрибутива; список — в /etc/apt/sources.list.d/ или /etc/yum.repos.d/.
  • Пакетный менеджер (apt, dnf, pacman) сам скачивает пакет со всеми зависимостями, проверяет подпись и обновляет всё одной командой.
  • Низкоуровневые dpkg / rpm ставят один файл без зависимостей.
  • Snap / Flatpak / AppImage — пакеты со всеми зависимостями внутри: работают на любом дистрибутиве, но весят больше.

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

0.14. Сеть: минимум теории

ПонятиеСуть
IP-адресАдрес узла: 192.168.1.10 (IPv4), 2001:db8::1 (IPv6)
Маска / CIDRРазмер сети: /24 = 255.255.255.0 = 254 адреса
Шлюз (gateway)Роутер, через который идёт трафик во внешний мир
DNSПереводит имена (example.com) в IP-адреса
ПортНомер «двери» конкретной службы на узле (0–65535)
TCPС установкой соединения и гарантией доставки: веб, SSH, почта
UDPБез гарантий, но быстро: DNS, видео, игры, VPN
localhost127.0.0.1 — сам компьютер
Приватные сети10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 — не маршрутизируются в интернет

Частые порты:

ПортСлужбаПортСлужба
22SSH443HTTPS
25 / 587SMTP3306MySQL
53DNS5432PostgreSQL
80HTTP6379Redis
123NTP8080HTTP (альтернативный)

Порты ниже 1024 может открывать только root. Полный список — в /etc/services.

0.15. Как работают SSH-ключи

Твой компьютер                          Сервер
~/.ssh/id_ed25519      (приватный,      ~/.ssh/authorized_keys
                        НИКОМУ не отдавать)   (сюда кладут .pub)
~/.ssh/id_ed25519.pub  ─── ssh-copy-id ──▶

Сервер отправляет «задачу», которую может решить только владелец приватного ключа, — пароль по сети не передаётся. Поэтому ключи безопаснее паролей, а после их настройки вход по паролю можно отключить (PasswordAuthentication no в /etc/ssh/sshd_config).


🟢 1. Первые шаги и справка

КомандаЧто делает
man lsПолное руководство по команде (q — выход, /слово — поиск)
ls --helpКраткая справка по ключам
tldr tarКороткие примеры использования (нужно установить tldr)
whatis cpОднострочное описание команды
apropos archiveНайти команду по ключевому слову
type cd / which python3Что это: встроенная команда, алиас или файл, и где он лежит
historyИстория команд
clear или Ctrl+LОчистить экран
exit или Ctrl+DВыйти из терминала / сессии

💡 Не помнишь команду? Нажми Ctrl+R и начни вводить её часть — bash найдёт её в истории.


🟢 2. Навигация по файловой системе

КомандаЧто делает
pwdПоказать текущую директорию
cd /etcПерейти по абсолютному пути
cd ..На уровень выше
cd ~ или cdВ домашнюю папку
cd -Вернуться в предыдущую папку
lsСписок файлов
ls -laВсе файлы (включая скрытые) с подробностями
ls -lhРазмеры в человекочитаемом виде (K, M, G)
ls -ltСортировка по времени изменения
ls -lSСортировка по размеру
tree -L 2Дерево каталогов глубиной 2
pushd /var/log / popdПерейти, запомнив, и вернуться обратно

Специальные пути:

/     корень файловой системы
~     домашняя папка (/home/user)
.     текущая папка
..    родительская папка
-     предыдущая папка (для cd)

🟢 3. Работа с файлами и папками

КомандаЧто делает
touch file.txtСоздать пустой файл / обновить дату
mkdir dirСоздать папку
mkdir -p a/b/cСоздать вложенные папки
cp file.txt copy.txtКопировать файл
cp -r dir/ backup/Копировать папку рекурсивно
cp -a src/ dst/Копировать с сохранением прав, владельцев, дат
mv old.txt new.txtПереименовать
mv file.txt /tmp/Переместить
mv -n a bНе перезаписывать существующий файл
rm file.txtУдалить файл
rm -i file.txtУдалить с подтверждением
rm -r dir/🔴 Удалить папку со всем содержимым
rmdir dirУдалить пустую папку
ln -s /path/target linkСоздать символическую ссылку
ln target hardlinkСоздать жёсткую ссылку
stat file.txtПодробная информация о файле
file image.pngОпределить тип файла
du -sh dir/Размер папки
basename /a/b/c.txt → c.txtИмя файла из пути
dirname /a/b/c.txt → /a/bПапка из пути

Маски (glob):

ls *.log              # все .log
ls file?.txt          # file1.txt, fileA.txt
ls [abc]*             # начинается с a, b или c
cp {a,b,c}.txt /tmp/  # a.txt b.txt c.txt
mkdir -p project/{src,tests,docs}

🟢 4. Просмотр содержимого файлов

КомандаЧто делает
cat fileВывести файл целиком
cat -n fileС номерами строк
less fileПостраничный просмотр (/ поиск, n далее, q выход)
head -n 20 fileПервые 20 строк
tail -n 20 fileПоследние 20 строк
tail -f /var/log/syslogСледить за файлом в реальном времени
tail -F fileТо же, но переживает ротацию логов
wc -l fileЧисло строк (-w слова, -c байты)
diff a.txt b.txtСравнить файлы
diff -u a bСравнение в unified-формате (как в git)
cmp a bПобайтовое сравнение
md5sum file / sha256sum fileКонтрольная сумма
xxd file | headHex-дамп
strings binaryТекстовые строки внутри бинарника

🟢 5. Поиск: find, locate, grep

find — поиск файлов

find . -name "*.log"                  # по имени (с учётом регистра)
find . -iname "readme*"               # без учёта регистра
find /var -type f -size +100M         # файлы больше 100 МБ
find . -type d -name node_modules     # только папки
find . -mtime -1                      # изменены за последние сутки
find . -mmin -30                      # за последние 30 минут
find . -empty                         # пустые файлы и папки
find . -user alice                    # принадлежат пользователю
find . -perm 777                      # с правами 777
find . -name "*.tmp" -delete          # 🔴 найти и удалить
find . -name "*.sh" -exec chmod +x {} \;    # выполнить команду для каждого
find . -type f -name "*.js" | xargs wc -l   # посчитать строки во всех .js

locate — быстрый поиск по базе

sudo updatedb          # обновить базу
locate nginx.conf      # мгновенный поиск

grep — поиск текста внутри файлов

КомандаЧто делает
grep "error" file.logСтроки со словом
grep -i "error"Без учёта регистра
grep -r "TODO" .Рекурсивно по папке
grep -rn "TODO" .+ номера строк
grep -rl "TODO" .Только имена файлов
grep -v "debug"Строки без совпадения
grep -c "error"Количество совпадений
grep -w "cat"Целое слово (не category)
grep -E "err|warn"Расширенные регулярки (ИЛИ)
grep -A 3 -B 2 "panic"3 строки после и 2 до совпадения
grep -o "[0-9]\+"Только совпавшая часть
grep --include="*.py" -rn "import" .Только в .py файлах

💡 Для больших проектов используй ripgrep (rg) — он в разы быстрее и уважает .gitignore.


🟢 6. Права доступа: chmod, chown

Как читать ls -l

-rwxr-xr--  1  alice  devs  4096  Sep 23 10:00  script.sh
│└┬┘└┬┘└┬┘       └─┬─┘  └┬─┘
│ │  │  │          │     └── группа
│ │  │  │          └──────── владелец
│ │  │  └───────────────── остальные (others): r--
│ │  └──────────────────── группа (group):     r-x
│ └─────────────────────── владелец (user):    rwx
└───────────────────────── тип: - файл, d папка, l ссылка

Числовые права

ЦифраПраваЗначение
7rwxчтение + запись + выполнение
6rw-чтение + запись
5r-xчтение + выполнение
4r--только чтение
0---нет прав

r = 4, w = 2, x = 1 — просто складывай.

Частые комбинации

ПраваДля чего
644Обычные файлы (rw-r--r--)
755Скрипты и папки (rwxr-xr-x)
600Приватные файлы, SSH-ключи (rw-------)
700Приватные папки, ~/.ssh
777🔴 Всем всё — почти никогда не нужно

Команды

chmod 755 script.sh           # числовой способ
chmod +x script.sh            # добавить выполнение всем
chmod u+x,g-w,o-r file        # символьный способ (u,g,o,a / + - =)
chmod -R 755 dir/             # рекурсивно
chown alice file              # сменить владельца
chown alice:devs file         # владельца и группу
chown -R www-data:www-data /var/www
chgrp devs file               # сменить группу
umask                         # маска прав по умолчанию (обычно 022)

Специальные биты 🟡

БитЧислоЭффект
SUID4xxxФайл запускается с правами владельца (passwd)
SGID2xxxНа папке — новые файлы наследуют группу
Sticky1xxxВ папке удалять файлы может только владелец (/tmp)
chmod u+s file      chmod g+s dir      chmod +t dir
getfacl file                         # ACL-права
setfacl -m u:bob:rw file             # дать bob чтение/запись

🟢 7. Пользователи и группы, sudo

КомандаЧто делает
whoamiТекущий пользователь
idUID, GID и группы
who / wКто сейчас в системе
lastИстория входов
sudo командаВыполнить от root
sudo -iИнтерактивная root-сессия
su - aliceВойти как другой пользователь
sudo adduser aliceСоздать пользователя (Debian/Ubuntu, интерактивно)
sudo useradd -m -s /bin/bash aliceСоздать пользователя (везде)
sudo passwd aliceЗадать пароль
sudo usermod -aG sudo aliceДобавить в группу sudo (в RHEL — wheel)
sudo userdel -r alice🔴 Удалить пользователя с домашней папкой
groups aliceГруппы пользователя
sudo groupadd devsСоздать группу
sudo visudoБезопасно редактировать sudoers
sudo chage -l aliceСрок действия пароля

Важные файлы: /etc/passwd (пользователи), /etc/shadow (хэши паролей), /etc/group (группы), /etc/sudoers (права sudo).

💡 -aG — именно с a! Без неё пользователь будет удалён из всех других групп.


🟢 8. Процессы и сигналы

КомандаЧто делает
ps auxВсе процессы
ps aux | grep nginxНайти процесс
ps -ef --forestДерево процессов
pgrep -a nginxPID и команда по имени
topМонитор в реальном времени
htopУдобный top (нужно установить)
kill PIDВежливо завершить (SIGTERM)
kill -9 PID🔴 Убить принудительно (SIGKILL)
pkill -f "python app.py"Убить по шаблону командной строки
killall firefoxУбить все процессы с именем
nice -n 10 cmdЗапустить с пониженным приоритетом
renice -n 5 -p PIDИзменить приоритет
lsof -p PIDОткрытые файлы процесса
lsof -i :8080Кто занял порт 8080
strace -p PID🟡 Системные вызовы процесса

Фоновые задачи

cmd &            # запустить в фоне
Ctrl+Z           # приостановить текущую задачу
bg               # продолжить в фоне
fg %1            # вернуть задачу №1 на передний план
jobs             # список фоновых задач
nohup cmd &      # не завершать при выходе из терминала
disown           # отвязать задачу от терминала

💡 Для долгих задач на сервере используй tmux или screen — сессия переживёт обрыв SSH.

Сигналы

Сигнал№Назначение
SIGHUP1Перечитать конфиг / терминал закрыт
SIGINT2Ctrl+C
SIGKILL9Убить немедленно (нельзя перехватить)
SIGTERM15Корректное завершение (по умолчанию)
SIGSTOP19Пауза (Ctrl+Z — это SIGTSTP)
SIGCONT18Продолжить

tmux за 30 секунд

ДействиеКлавиши / команда
Новая сессияtmux new -s work
ОтключитьсяCtrl+B, затем D
Подключитьсяtmux attach -t work
Список сессийtmux ls
Разделить вертикально / горизонтальноCtrl+B % / Ctrl+B "
Переключить панельCtrl+B + стрелка

🟢 9. Информация о системе

КомандаЧто делает
uname -aЯдро и архитектура
cat /etc/os-releaseДистрибутив и версия
hostnamectlИмя хоста, ОС, ядро
uptimeВремя работы и нагрузка (load average)
free -hПамять и swap
nprocКоличество ядер CPU
lscpuПодробно о процессоре
lsblkДиски и разделы
lspci / lsusbPCI / USB-устройства
sudo dmidecode -t memoryПланки памяти
vmstat 1CPU, память, I/O каждую секунду
iostat -x 1Нагрузка на диски (пакет sysstat)
dmesg -T | tailСообщения ядра с датами
date / timedatectlДата, время, часовой пояс
envПеременные окружения
echo $SHELLТекущая оболочка

💡 Load average — три числа за 1, 5 и 15 минут. Если значение стабильно больше nproc, система перегружена.


🟡 10. Диски и файловые системы

КомандаЧто делает
df -hСвободное место на разделах
df -iСвободные inode
du -sh *Размер каждого элемента в папке
du -h --max-depth=1 / | sort -hЧто занимает место в корне
ncdu /Интерактивный анализ места (установить)
lsblk -fРазделы с ФС и UUID
sudo blkidUUID разделов
sudo fdisk -lТаблицы разделов
sudo mount /dev/sdb1 /mntСмонтировать
sudo umount /mntРазмонтировать
sudo mkfs.ext4 /dev/sdb1🔴 Отформатировать в ext4
sudo fsck /dev/sdb1Проверить ФС (только размонтированную!)
findmntДерево точек монтирования
cat /etc/fstabАвтомонтирование при загрузке

Создать swap-файл на 2 ГБ

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

🟢 11. Сеть

КомандаЧто делает
ip aIP-адреса интерфейсов
ip rТаблица маршрутизации
ip link set eth0 upВключить интерфейс
ping -c 4 8.8.8.8Проверка связи
traceroute google.com / mtr google.comМаршрут до хоста
ss -tulpnОткрытые порты и процессы (замена netstat)
curl -I https://example.comHTTP-заголовки
curl -O URLСкачать файл
wget -c URLСкачать с докачкой
curl ifconfig.meВнешний IP
dig example.comDNS-запрос
dig +short example.com MXMX-записи
nslookup example.comDNS (простой вариант)
host example.comDNS (ещё проще)
cat /etc/resolv.confИспользуемые DNS-серверы
cat /etc/hostsЛокальные имена хостов
nc -zv host 22Проверить, открыт ли порт
sudo tcpdump -i eth0 port 80🟡 Перехват трафика
nmcli device wifi listWi-Fi сети (NetworkManager)

🟢 12. SSH, SCP, rsync

ssh user@host                          # подключиться
ssh -p 2222 user@host                  # на другой порт
ssh -i ~/.ssh/key user@host            # с конкретным ключом
ssh-keygen -t ed25519 -C "me@mail"     # создать ключ (современный тип)
ssh-copy-id user@host                  # скопировать публичный ключ на сервер
ssh user@host 'df -h'                  # выполнить команду удалённо

scp file.txt user@host:/tmp/           # копировать на сервер
scp user@host:/var/log/app.log .       # скачать с сервера
scp -r dir/ user@host:~/               # папку

rsync -avz dir/ user@host:~/dir/       # синхронизация (только изменения)
rsync -avz --delete src/ dst/          # 🔴 удалить в dst то, чего нет в src
rsync -avzP big.iso user@host:~        # с прогрессом и докачкой

ssh -L 8080:localhost:80 user@host     # 🟡 проброс порта: локальный 8080 → удалённый 80
ssh -D 1080 user@host                  # 🟡 SOCKS-прокси
ssh -J jump@bastion user@internal      # 🟡 через промежуточный хост

~/.ssh/config — короткие алиасы

Host prod
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/prod_ed25519

Теперь достаточно ssh prod.

💡 У rsync важен слеш в конце: dir/ — содержимое папки, dir — сама папка.


🟢 13. Архивы и сжатие

КомандаЧто делает
tar -czvf arch.tar.gz dir/Создать .tar.gz
tar -xzvf arch.tar.gzРаспаковать .tar.gz
tar -xzvf arch.tar.gz -C /optРаспаковать в папку
tar -tzvf arch.tar.gzПосмотреть содержимое
tar -cJvf arch.tar.xz dir/.tar.xz (сильнее сжатие)
tar -xf archive.tar.*Распаковать любой tar (формат определится сам)
zip -r arch.zip dir/Создать zip
unzip arch.zip -d dir/Распаковать zip
gzip file / gunzip file.gzСжать / распаковать файл
zcat file.gzПрочитать сжатый файл без распаковки
7z x arch.7zРаспаковать 7z (пакет p7zip)

Как запомнить ключи tar: c — create, x — extract, t — list, z — gzip, J — xz, j — bzip2, v — verbose, f — file.


🟢 14. Пакетные менеджеры (apt, dnf, pacman)

ДействиеDebian / UbuntuFedora / RHELArch
Обновить спискиapt updatednf check-updatepacman -Sy
Обновить системуapt upgradednf upgradepacman -Syu
Установитьapt install pkgdnf install pkgpacman -S pkg
Удалитьapt remove pkgdnf remove pkgpacman -R pkg
Удалить с конфигамиapt purge pkg—pacman -Rns pkg
Поискapt search pkgdnf search pkgpacman -Ss pkg
Информацияapt show pkgdnf info pkgpacman -Si pkg
Установленныеapt list --installeddnf list installedpacman -Q
Чей это файлdpkg -S /bin/lsrpm -qf /bin/lspacman -Qo /bin/ls
Убрать лишнееapt autoremovednf autoremovepacman -Rns $(pacman -Qdtq)
Установить файлdpkg -i pkg.debdnf install ./pkg.rpmpacman -U pkg.tar.zst

Также: snap install pkg, flatpak install flathub app, zypper install pkg (openSUSE), apk add pkg (Alpine).


🟢 15. Systemd и службы

КомандаЧто делает
systemctl status nginxСтатус службы
sudo systemctl start nginxЗапустить
sudo systemctl stop nginxОстановить
sudo systemctl restart nginxПерезапустить
sudo systemctl reload nginxПеречитать конфиг без остановки
sudo systemctl enable --now nginxВключить автозапуск и запустить
sudo systemctl disable nginxВыключить автозапуск
systemctl is-active nginxРаботает ли служба
systemctl list-units --type=service --state=runningРаботающие службы
systemctl --failedУпавшие службы
sudo systemctl daemon-reloadПеречитать unit-файлы после правки
systemctl list-timersТаймеры (альтернатива cron)
systemd-analyze blameЧто тормозит загрузку
sudo reboot / sudo poweroffПерезагрузка / выключение

Своя служба: /etc/systemd/system/myapp.service

[Unit]
Description=My App
After=network.target

[Service]
User=app
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 app.py
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now myapp

🟢 16. Логи и journalctl

КомандаЧто делает
journalctl -u nginxЛоги службы
journalctl -u nginx -fСледить в реальном времени
journalctl -u nginx --since "1 hour ago"За последний час
journalctl --since todayЗа сегодня
journalctl -bС момента последней загрузки
journalctl -b -1Предыдущая загрузка (после сбоя)
journalctl -p errТолько ошибки
journalctl -n 100 --no-pagerПоследние 100 строк
journalctl --disk-usageСколько места занимают логи
sudo journalctl --vacuum-size=500MУрезать логи до 500 МБ

Классические логи в /var/log/:

ФайлЧто внутри
syslog / messagesОбщий системный лог (Debian / RHEL)
auth.log / secureВходы, sudo, SSH
kern.logЯдро
dpkg.logУстановка пакетов
nginx/, apache2/Веб-сервер

🟡 17. Обработка текста: sed, awk, cut, sort

sed — поиск и замена

sed 's/old/new/' file          # заменить первое вхождение в строке
sed 's/old/new/g' file         # все вхождения
sed -i 's/old/new/g' file      # 🔴 изменить файл на месте
sed -i.bak 's/old/new/g' file  # то же, но с резервной копией
sed -n '10,20p' file           # вывести строки 10–20
sed '/^#/d' file               # удалить комментарии
sed '/^$/d' file               # удалить пустые строки

awk — работа с колонками

awk '{print $1}' file                     # первая колонка
awk -F: '{print $1, $7}' /etc/passwd      # разделитель ":"
awk '$3 > 100' file                       # строки, где 3-я колонка > 100
awk '{sum += $2} END {print sum}' file    # сумма колонки
awk 'NR==5' file                          # 5-я строка
awk '{print NF}' file                     # число колонок в строке

Остальные инструменты

КомандаЧто делает
cut -d, -f1,3 file.csvКолонки 1 и 3 из CSV
sort fileСортировка
sort -n / sort -hЧисловая / по размерам (1K, 2M)
sort -rn -k2По 2-й колонке, по убыванию
uniqУбрать соседние дубли (сначала sort!)
sort | uniq -c | sort -rnЧастотный словарь
tr 'a-z' 'A-Z'Заменить символы (в верхний регистр)
tr -d '\r'Убрать Windows-переводы строк
paste a bСклеить файлы по колонкам
column -tВыровнять в таблицу
tee fileВывести на экран и записать в файл
jq '.items[].name' data.jsonРазбор JSON

🟢 18. Перенаправление, пайпы, xargs

СинтаксисЧто делает
cmd > filestdout в файл (перезаписать)
cmd >> filestdout в файл (дописать)
cmd 2> err.logstderr в файл
cmd > out.log 2>&1stdout и stderr в один файл
cmd &> out.logТо же, короче (bash)
cmd > /dev/null 2>&1Полностью заглушить вывод
cmd < fileФайл на вход
cmd1 | cmd2Вывод первой на вход второй
cmd1 && cmd2Вторая — только если первая успешна
cmd1 || cmd2Вторая — только если первая упала
cmd1 ; cmd2Выполнить по очереди в любом случае
$(cmd)Подставить вывод команды
<(cmd)Вывод команды как файл: diff <(ls a) <(ls b)
cat urls.txt | xargs -n1 curl -sO                 # по одному аргументу
find . -name "*.log" -print0 | xargs -0 rm         # безопасно с пробелами в именах
cat hosts | xargs -P4 -I{} ping -c1 {}             # 4 параллельных процесса

Потоки: 0 — stdin, 1 — stdout, 2 — stderr.


🟡 19. Bash: переменные и скрипты

Шаблон надёжного скрипта

#!/usr/bin/env bash
set -euo pipefail   # падать на ошибках, неопределённых переменных и в пайпах

NAME="${1:-world}"   # первый аргумент или значение по умолчанию
echo "Hello, $NAME!"
chmod +x script.sh && ./script.sh Linux

Переменные

СинтаксисЗначение
VAR=valueПрисвоить (без пробелов вокруг =!)
export VAR=valueСделать доступной дочерним процессам
$VAR / "${VAR}"Использовать (всегда в кавычках)
$0Имя скрипта
$1…$9Аргументы
$#Количество аргументов
$@Все аргументы
$?Код выхода последней команды (0 = успех)
$$PID текущего процесса
${VAR:-def}Значение по умолчанию
${#VAR}Длина строки
${FILE%.txt}Отрезать суффикс
$((a + b))Арифметика

Условия и циклы

if [[ -f /etc/passwd ]]; then
    echo "файл существует"
elif [[ -d /etc ]]; then
    echo "это папка"
else
    echo "нет"
fi

for f in *.jpg; do
    echo "Обрабатываю $f"
done

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

while read -r line; do
    echo "$line"
done < file.txt

case "$1" in
    start) echo "Запуск" ;;
    stop)  echo "Остановка" ;;
    *)     echo "Использование: $0 {start|stop}" ;;
esac

greet() { echo "Привет, $1"; }
greet Мир

Проверки в [[ ]]

ПроверкаИстинно, если
-f fileСуществует обычный файл
-d dirСуществует папка
-e pathСуществует что угодно
-x fileИсполняемый
-z "$s" / -n "$s"Строка пустая / не пустая
"$a" == "$b"Строки равны
$a -eq $bЧисла равны (-ne -lt -le -gt -ge)

Алиасы (в ~/.bashrc)

alias ll='ls -lah'
alias ..='cd ..'
alias update='sudo apt update && sudo apt upgrade -y'
alias ports='ss -tulpn'

Применить: source ~/.bashrc.

💡 Проверяй скрипты утилитой ShellCheck — она ловит типичные ошибки.


🟢 20. Горячие клавиши терминала

КлавишиДействие
TabАвтодополнение (дважды — варианты)
Ctrl+CПрервать команду
Ctrl+ZПриостановить команду
Ctrl+DВыход / конец ввода
Ctrl+LОчистить экран
Ctrl+RПоиск по истории
Ctrl+A / Ctrl+EВ начало / конец строки
Ctrl+U / Ctrl+KУдалить до начала / до конца строки
Ctrl+WУдалить слово перед курсором
Alt+B / Alt+FНа слово назад / вперёд
Ctrl+YВставить удалённое
Alt+.Вставить последний аргумент прошлой команды
!!Повторить прошлую команду (sudo !!)
!$Последний аргумент прошлой команды
!nginxПоследняя команда, начинавшаяся с nginx
^old^newПовторить прошлую команду с заменой

🟢 21. Vim — минимум для выживания

 Обычный режим ──i──▶ Режим вставки
      ▲                    │
      └──────── Esc ◀──────┘
      │
      └──:──▶ Командная строка (:w, :q, …)
КлавишиДействие
i / a / oВставка перед курсором / после / новая строка
EscВыйти в обычный режим
:wСохранить
:qВыйти
:wq или ZZСохранить и выйти
:q!Выйти без сохранения
h j k lВлево, вниз, вверх, вправо
gg / GВ начало / конец файла
:42На строку 42
0 / $В начало / конец строки
w / bСлово вперёд / назад
ddВырезать строку
yyКопировать строку
pВставить
u / Ctrl+RОтменить / повторить
/textПоиск (n — следующий)
:%s/old/new/gЗаменить во всём файле
v / VВыделение символов / строк
:set numberНомера строк

💡 Не хочешь Vim? Используй nano: Ctrl+O — сохранить, Ctrl+X — выйти.


🟢 22. Cron — планировщик задач

crontab -e        # редактировать свои задачи
crontab -l        # посмотреть
sudo crontab -u alice -l

Формат

┌───────── минута (0–59)
│ ┌─────── час (0–23)
│ │ ┌───── день месяца (1–31)
│ │ │ ┌─── месяц (1–12)
│ │ │ │ ┌─ день недели (0–7, 0 и 7 = воскресенье)
│ │ │ │ │
* * * * *  команда
РасписаниеКогда
*/5 * * * *Каждые 5 минут
0 * * * *Каждый час
0 3 * * *Каждый день в 03:00
0 9 * * 1-5По будням в 09:00
0 0 1 * *Первого числа каждого месяца
@rebootПри загрузке системы
0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1

💡 В cron минимальный PATH — указывай полные пути к командам. Проверить выражение: crontab.guru.


🟡 23. Файрвол: ufw, firewalld, iptables

Действиеufw (Ubuntu)firewalld (RHEL/Fedora)
Статусsudo ufw status verbosesudo firewall-cmd --list-all
Включитьsudo ufw enablesudo systemctl enable --now firewalld
Открыть портsudo ufw allow 443/tcpsudo firewall-cmd --add-port=443/tcp --permanent
Разрешить службуsudo ufw allow OpenSSHsudo firewall-cmd --add-service=http --permanent
Закрыть портsudo ufw delete allow 443/tcpsudo firewall-cmd --remove-port=443/tcp --permanent
Разрешить IPsudo ufw allow from 10.0.0.5sudo firewall-cmd --add-source=10.0.0.5 --permanent
Применить—sudo firewall-cmd --reload
sudo iptables -L -n -v        # правила iptables
sudo nft list ruleset         # правила nftables

🔴 Перед ufw enable на удалённом сервере обязательно выполни sudo ufw allow OpenSSH, иначе потеряешь доступ.


🟢 24. Структура каталогов Linux (FHS)

КаталогНазначение
/Корень всей файловой системы
/bin, /usr/binПрограммы пользователя
/sbin, /usr/sbinСистемные программы (для root)
/etcКонфигурационные файлы
/homeДомашние папки пользователей
/rootДомашняя папка root
/varИзменяемые данные: логи, кэш, БД, почта
/var/logЛоги
/tmpВременные файлы (очищается при перезагрузке)
/optСторонние программы
/usr/localПрограммы, собранные вручную
/devФайлы устройств (/dev/sda, /dev/null)
/procВиртуальная ФС: процессы и ядро
/sysВиртуальная ФС: устройства и драйверы
/bootЯдро и загрузчик
/lib, /usr/libБиблиотеки
/mnt, /mediaТочки монтирования
/srvДанные сервисов (сайты, FTP)

🚀 25. Полезные однострочники

# 10 самых больших файлов в системе
sudo find / -xdev -type f -printf '%s %p\n' 2>/dev/null | sort -rn | head -10 | numfmt --field=1 --to=iec

# 10 самых больших папок в текущей директории
du -ah --max-depth=1 . | sort -rh | head -10

# Топ-10 процессов по памяти / по CPU
ps aux --sort=-%mem | head -11
ps aux --sort=-%cpu | head -11

# Топ IP-адресов в логе nginx
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

# Самые частые команды из истории
history | awk '{print $2}' | sort | uniq -c | sort -rn | head

# Быстрый HTTP-сервер в текущей папке
python3 -m http.server 8000

# Сгенерировать надёжный пароль
openssl rand -base64 24

# Бэкап папки с датой в имени
tar -czf "backup-$(date +%F).tar.gz" ~/project

# Переименовать все .jpeg в .jpg
for f in *.jpeg; do mv -- "$f" "${f%.jpeg}.jpg"; done

# Найти и заменить текст во всех файлах проекта
grep -rl "old_text" . | xargs sed -i 's/old_text/new_text/g'

# Удалить файлы старше 30 дней
find /var/backups -type f -mtime +30 -delete

# Следить за командой каждые 2 секунды
watch -n 2 'df -h /'

# Проверить срок SSL-сертификата
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

# Узнать, кто занял порт
sudo ss -tulpn | grep :80

# Создать файл заданного размера
fallocate -l 1G test.img

# Прогресс копирования большого файла
rsync --progress big.iso /mnt/usb/

# Время выполнения команды
time ./script.sh

🟡 26. Bash для профи: массивы, раскрытие параметров, trap

Раскрытие параметров (без sed и awk)

Пусть f="/home/user/archive.tar.gz":

СинтаксисЧто делаетРезультат
${f##*/}Убрать самый длинный префикс по шаблонуarchive.tar.gz (как basename)
${f%/*}Убрать самый короткий суффикс/home/user (как dirname)
${f#*.}Убрать самый короткий префиксtar.gz
${f%%.*}Убрать самый длинный суффикс/home/user/archive
${f/user/root}Заменить первое вхождение/home/root/archive.tar.gz
${f//a/A}Заменить все вхождения/home/user/Archive.tAr.gz
${f:0:5}Подстрока: с 0, длина 5/home
${f^^} / ${f,,}В верхний / нижний регистр/HOME/USER/…
${v:=def}Если пусто — присвоить значение
${v:?нет значения}Если пусто — ошибка и выход
${v:+alt}Если НЕ пусто — подставить alt

💡 Запомнить: # стоит слева от $ на клавиатуре — режет слева, % справа — режет справа. Двойной символ — «жадно».

Массивы

arr=(one two "three four")      # обычный массив
echo "${arr[0]}"                # первый элемент
echo "${arr[@]}"                # все элементы (всегда в кавычках!)
echo "${#arr[@]}"               # количество
arr+=(five)                     # добавить
for x in "${arr[@]}"; do echo "$x"; done
mapfile -t lines < file.txt     # прочитать файл в массив построчно

declare -A port=([ssh]=22 [http]=80)   # ассоциативный массив (bash 4+)
port[https]=443
for k in "${!port[@]}"; do echo "$k → ${port[$k]}"; done

Надёжный скрипт: временные файлы, очистка, ошибки

#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

tmp=$(mktemp -d)                                   # безопасная временная папка
trap 'rm -rf "$tmp"' EXIT                          # удалится при любом выходе
trap 'echo "Ошибка в строке $LINENO: $BASH_COMMAND" >&2' ERR

log() { printf '[%(%F %T)T] %s\n' -1 "$*" >&2; }  # лог с временем, без вызова date
log "Старт"

Разбор опций: getopts

usage() { echo "Использование: $0 [-v] [-o файл] аргумент" >&2; exit 2; }
verbose=0; out=/dev/stdout
while getopts ":vo:h" opt; do
  case "$opt" in
    v) verbose=1 ;;
    o) out="$OPTARG" ;;
    h|*) usage ;;
  esac
done
shift $((OPTIND - 1))           # теперь $1 — первый позиционный аргумент
[[ $# -ge 1 ]] || usage

Here-doc, арифметика, параллельность, блокировки

cat <<EOF > /tmp/conf           # переменные раскрываются
user=$USER
EOF
cat <<'EOF'                     # в кавычках — всё буквально, $HOME не раскроется
$HOME
EOF

(( count++ ))                   # арифметика; (( a > b )) — числовое сравнение
if (( $(nproc) >= 4 )); then echo "много ядер"; fi

for h in web1 web2 web3; do ssh "$h" uptime & done; wait   # параллельно и дождаться всех
timeout 10 curl -s https://example.com                      # ограничить время выполнения

exec 9>/var/lock/backup.lock    # защита от двойного запуска (например, из cron)
flock -n 9 || { echo "Уже запущено"; exit 1; }

Отладка

КомандаЧто делает
bash -n script.shПроверить синтаксис, не выполняя
bash -x script.shПечатать каждую команду перед выполнением
set -x … set +xТрассировка только части скрипта
export PS4='+ ${BASH_SOURCE}:${LINENO}: 'Показывать файл и строку в трассировке
shellcheck script.shСтатический анализ — ловит большинство ошибок

Классические ловушки

❌ Плохо✅ ХорошоПочему
for f in $(ls *.txt)for f in *.txtИмена с пробелами разобьются
while read linewhile IFS= read -r lineИначе съест пробелы и \
cd dir; rm -rf *cd dir && rm -rf ./*Если cd не сработал — удалишь не то
rm -rf $DIR/rm -rf "${DIR:?}/"При пустой переменной — rm -rf /
[ $a == $b ][[ "$a" == "$b" ]]Пустые переменные ломают [ ]
echo $varprintf '%s\n' "$var"echo по-разному обрабатывает -n и \
переменная в функцииlocal varИначе она глобальная

⚠️ set -e не срабатывает внутри if, while, после && / || и в подстановке local x=$(cmd) — пиши local x; x=$(cmd).


🟡 27. LVM, RAID и снапшоты

LVM: гибкие разделы

 Диски (PV)     /dev/sdb      /dev/sdc
                    └─────┬───────┘
 Группа (VG)          vg_data (общий пул места)
                    ┌─────┴───────┐
 Тома (LV)       lv_www       lv_db      ← на них создаётся ФС

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

КомандаЧто делает
sudo pvcreate /dev/sdbПодготовить диск для LVM
sudo vgcreate vg_data /dev/sdbСоздать группу томов
sudo lvcreate -n lv_www -L 20G vg_dataСоздать том на 20 ГБ
sudo lvcreate -n lv_db -l 100%FREE vg_dataТом на всё оставшееся место
sudo mkfs.ext4 /dev/vg_data/lv_wwwСоздать ФС на томе
sudo pvs / vgs / lvsКраткий статус
sudo vgextend vg_data /dev/sdcДобавить диск в группу
sudo lvextend -r -L +10G /dev/vg_data/lv_wwwУвеличить том и ФС (-r) на 10 ГБ
sudo lvextend -r -l +100%FREE /dev/vg_data/lv_wwwОтдать тому всё свободное место
sudo lvcreate -s -n www_snap -L 5G /dev/vg_data/lv_wwwСнапшот (перед обновлением)
sudo lvconvert --merge vg_data/www_snapОткатиться к снапшоту
sudo lvremove vg_data/www_snapУдалить снапшот

💡 ext4 можно и увеличивать, и уменьшать (только размонтированной), XFS — только увеличивать.

Расширить диск в облаке (после увеличения в панели)

lsblk                              # убедиться, что диск стал больше
sudo growpart /dev/sda 1           # расширить раздел 1 (пакет cloud-guest-utils / cloud-utils-growpart)
sudo resize2fs /dev/sda1           # для ext4
sudo xfs_growfs /                  # для XFS (указывается точка монтирования)
# если на разделе LVM: sudo pvresize /dev/sda3 && sudo lvextend -r -l +100%FREE /dev/mapper/…

Программный RAID: mdadm

УровеньМинимум дисковПереживёт отказПолезный объём
RAID 02❌ ни одного100% (только скорость)
RAID 121 диск50% (зеркало)
RAID 531 диск(N−1)/N
RAID 642 диска(N−2)/N
RAID 104по 1 в каждой паре50%
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
cat /proc/mdstat                                   # состояние и прогресс синхронизации
sudo mdadm --detail /dev/md0
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf   # чтобы собрался после перезагрузки
sudo mdadm /dev/md0 --fail /dev/sdb --remove /dev/sdb            # заменить сбойный диск…
sudo mdadm /dev/md0 --add /dev/sdd                               # …и добавить новый

🔴 RAID — не бэкап: случайное rm или шифровальщик мгновенно отразится на всех дисках.

fstab без сюрпризов и здоровье дисков

# /etc/fstab — монтируй по UUID, а не /dev/sdX (буквы могут поменяться)
UUID=3f2a…  /data  ext4  defaults,noatime,nofail  0  2
sudo findmnt --verify              # проверить fstab до перезагрузки
sudo mount -a                      # смонтировать всё из fstab (ошибка = исправь до reboot!)
sudo smartctl -a /dev/sda          # SMART: перераспределённые сектора, ошибки (пакет smartmontools)
sudo nvme smart-log /dev/nvme0     # здоровье NVMe (пакет nvme-cli)

🟡 28. Продвинутая сеть

Диагностика снизу вверх

УровеньВопросКоманда
КанальныйКабель / интерфейс жив?ip -br link, ethtool eth0
IPЕсть адрес и маршрут?ip -br a, ip r, ip route get 8.8.8.8
ШлюзРоутер отвечает?ping -c3 $(ip r | awk '/default/{print $3}')
DNSИмена резолвятся?dig example.com, resolvectl status
ПортСлужба слушает / доступна?ss -tlnp, nc -zv host 443
ПриложениеЧто отвечает сервер?curl -v https://host

ip — полный контроль

ip -br a                                        # кратко: интерфейс, состояние, адреса
sudo ip addr add 192.168.1.50/24 dev eth0       # добавить адрес (до перезагрузки)
sudo ip route add 10.10.0.0/16 via 192.168.1.1  # статический маршрут
ip route get 1.1.1.1                            # каким маршрутом пойдёт пакет
ip -s link show eth0                            # счётчики, ошибки, дропы
ip neigh                                        # ARP-таблица (соседи)

ss — продвинутые фильтры

ss -s                                           # сводка по сокетам
ss -tan state established                       # установленные TCP-соединения
ss -tan state time-wait | wc -l                 # сколько TIME-WAIT
ss -tnp '( dport = :443 or sport = :443 )'      # соединения по порту 443
ss -tan | awk 'NR>1{print $1}' | sort | uniq -c # статистика по состояниям

Постоянная настройка сети

# Ubuntu: /etc/netplan/01-static.yaml → sudo netplan try (откатится сам, если связь пропадёт)
network:
  version: 2
  ethernets:
    eth0:
      addresses: [192.168.1.50/24]
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses: [1.1.1.1, 8.8.8.8]
# RHEL / Fedora / NetworkManager
nmcli con show
sudo nmcli con mod eth0 ipv4.method manual ipv4.addresses 192.168.1.50/24 \
     ipv4.gateway 192.168.1.1 ipv4.dns "1.1.1.1 8.8.8.8"
sudo nmcli con up eth0

HTTP, TLS и DNS изнутри

# Где тормозит запрос: DNS, TCP, TLS или сервер?
curl -o /dev/null -s -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://example.com

curl --resolve example.com:443:203.0.113.10 https://example.com   # проверить сайт на конкретном IP без правки hosts
openssl s_client -connect example.com:443 -servername example.com </dev/null   # цепочка сертификатов
dig +trace example.com                          # весь путь DNS от корневых серверов
dig @1.1.1.1 example.com +short                 # спросить конкретный DNS-сервер
dig -x 8.8.8.8 +short                           # обратная запись (PTR)

Трафик и пропускная способность

sudo tcpdump -i any -nn port 53                 # DNS-запросы
sudo tcpdump -i eth0 -nn host 10.0.0.5 and port 443
sudo tcpdump -i eth0 -w dump.pcap               # записать для Wireshark
sudo tcpdump -nn 'tcp[tcpflags] & tcp-syn != 0' # только SYN (новые соединения)
iperf3 -s                                       # на сервере
iperf3 -c server -P 4                           # на клиенте: скорость в 4 потока
sudo iftop -i eth0                              # кто грузит канал (или nethogs — по процессам)

Network namespaces — изолированные сети

sudo ip netns add lab                           # отдельный сетевой стек
sudo ip link add veth0 type veth peer name veth1
sudo ip link set veth1 netns lab
sudo ip addr add 10.99.0.1/24 dev veth0 && sudo ip link set veth0 up
sudo ip netns exec lab ip addr add 10.99.0.2/24 dev veth1
sudo ip netns exec lab ip link set veth1 up
ping -c2 10.99.0.2                              # так устроены сети контейнеров

🟡 29. Производительность и трассировка

Метод USE — чтобы не гадать

Для каждого ресурса проверь три вещи: Utilization (загрузка), Saturation (очередь / ожидание), Errors (ошибки).

РесурсЗагрузкаНасыщениеОшибки
CPUmpstat -P ALL 1, topvmstat 1 (колонка r > ядер), load averagedmesg
Памятьfree -hvmstat 1 (si/so ≠ 0), OOM в dmesgdmesg
Дискiostat -xz 1 (%util)iostat (aqu-sz, await)smartctl, dmesg
Сетьsar -n DEV 1ss -s, ретрансмиты sar -n ETCP 1ip -s link

Первые 60 секунд на тормозящем сервере

uptime                 # load average: растёт или падает?
dmesg -T | tail -20    # OOM, ошибки дисков, сети
vmstat 1 5             # r — очередь CPU, b — ждут I/O, wa — ожидание диска, st — «украдено» гипервизором
mpstat -P ALL 1 3      # одно ядро на 100%? — однопоточное узкое место
pidstat 1 3            # какие процессы едят CPU
iostat -xz 1 3         # await в мс и %util дисков
free -h                # available и swap
sar -n DEV 1 3         # трафик по интерфейсам
top                    # общая картина

Утилиты mpstat, pidstat, iostat, sar — из пакета sysstat.

Pressure Stall Information (ядро 4.20+)

cat /proc/pressure/cpu /proc/pressure/memory /proc/pressure/io
# some avg10=12.50 … — 12.5% времени за 10 секунд хотя бы одна задача ЖДАЛА ресурс

PSI честнее load average: сразу видно, какого ресурса не хватает.

Заглянуть внутрь процесса

КомандаЧто показывает
cat /proc/PID/statusСостояние, память (VmRSS), потоки
ls -l /proc/PID/fdОткрытые файлы и сокеты
cat /proc/PID/limitsЛимиты (открытые файлы и т.д.)
sudo cat /proc/PID/stackГде в ядре висит процесс (для состояния D)
pmap -x PIDКарта памяти процесса
sudo iotop -oКто сейчас пишет / читает диск
pidstat -d 1 / pidstat -r 1I/O / память по процессам

strace, ltrace, perf

strace -c -p PID                          # статистика системных вызовов (Ctrl+C — отчёт)
strace -f -tt -T -e trace=openat,connect ./app   # какие файлы и адреса трогает, со временем каждого вызова
strace -f -e trace=file -o trace.log cmd  # «почему не находит конфиг?» — ищи ENOENT
ltrace -c ./app                           # вызовы библиотечных функций
sudo perf top                             # горячие функции во всей системе
sudo perf record -g -p PID -- sleep 30    # записать профиль со стеком
sudo perf report                          # разобрать (или построить flame graph)

⚠️ strace сильно замедляет процесс — на проде используй кратко или бери eBPF.

eBPF — трассировка почти без замедления

Пакеты bpfcc-tools (Ubuntu, команды с суффиксом -bpfcc) или bcc-tools (RHEL, в /usr/share/bcc/tools/) и bpftrace.

УтилитаЧто показывает
execsnoopВсе запускаемые процессы (ловит короткоживущие)
opensnoopКто какие файлы открывает
biolatencyГистограмма задержек диска
tcpconnect / tcpacceptИсходящие / входящие TCP-соединения
tcpretransРетрансмиты TCP
runqlatСколько задачи ждут CPU
cachestatПопадания в page cache
# Какие процессы делают больше всего системных вызовов
sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'

Память: куда она делась

ps -eo pid,comm,rss --sort=-rss | head        # RSS — реально занятая RAM (КБ)
sudo slabtop -o | head -15                    # память ядра (dentry, inode cache)
grep -E 'MemAvailable|Dirty|Slab|HugePages_Total' /proc/meminfo
cat /proc/sys/vm/swappiness                   # склонность уходить в swap (0–200)
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches   # сбросить кэш (только для тестов!)

🟡 30. Systemd для профи

Правильно менять чужие службы

КомандаЧто делает
systemctl cat nginxПоказать unit и все drop-in файлы
sudo systemctl edit nginxСоздать override (переживёт обновление пакета)
sudo systemctl edit --full nginxСкопировать весь unit для правки
sudo systemctl revert nginxОтменить все свои изменения
systemctl show nginx -p MainPID,MemoryCurrent,NRestartsОтдельные свойства
systemctl list-dependencies nginxДерево зависимостей
systemd-analyze critical-chainЦепочка, задержавшая загрузку
systemd-analyze verify my.serviceПроверить unit на ошибки
systemd-cgls / systemd-cgtopДерево cgroups / «top» по службам

🔴 Не правь файлы в /usr/lib/systemd/system/ — обновление пакета их перезапишет. Твоё место — /etc/systemd/system/.

Боевой unit: перезапуск, лимиты, изоляция

[Unit]
Description=My App
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=5

[Service]
Type=simple
User=app
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/server
Restart=on-failure
RestartSec=5

# Ресурсы (cgroups)
MemoryMax=512M
CPUQuota=50%
TasksMax=200
LimitNOFILE=65536

# Изоляция
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ReadWritePaths=/var/lib/myapp
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

systemd-analyze security myapp оценит изоляцию службы от 0 (отлично) до 10 (небезопасно) и подскажет, что добавить.

Таймеры вместо cron

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/opt/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup nightly
[Timer]
OnCalendar=*-*-* 03:00:00
# выполнить пропущенный запуск, если сервер был выключен
Persistent=true
# не запускать все серверы одновременно
RandomizedDelaySec=10min
[Install]
WantedBy=timers.target
sudo systemctl enable --now backup.timer
systemctl list-timers
systemd-analyze calendar "Mon..Fri *-*-* 09:00"   # проверить выражение
sudo systemd-run --on-active=30m /opt/backup.sh   # одноразовый запуск через 30 минут
sudo systemd-run --scope -p MemoryMax=1G ./heavy  # запустить команду с лимитом памяти

Плюсы перед cron: логи в журнале, зависимости, лимиты ресурсов, Persistent, защита от параллельного запуска.

journalctl продвинутый

journalctl -u nginx -o json-pretty -n 1       # все поля записи
journalctl _PID=1234                          # по PID
journalctl _COMM=sshd --since "2 hours ago"   # по имени программы
journalctl -u nginx --grep "timeout" -p warning
journalctl -k -b                              # только ядро, текущая загрузка
sudo mkdir -p /var/log/journal && sudo systemctl restart systemd-journald   # хранить журнал между перезагрузками

Пользовательские службы (без root)

mkdir -p ~/.config/systemd/user            # сюда кладёшь свои .service
systemctl --user enable --now myapp
journalctl --user -u myapp
sudo loginctl enable-linger $USER          # чтобы службы работали, когда ты не залогинен

🟡 31. Ядро: sysctl, модули, лимиты, cgroups

sysctl — параметры ядра на лету

sysctl net.ipv4.ip_forward                          # прочитать
sudo sysctl -w net.ipv4.ip_forward=1                # изменить до перезагрузки
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-custom.conf
sudo sysctl --system                                # применить все файлы
ПараметрЗачем менять
net.ipv4.ip_forward1 — сервер работает роутером / NAT / для контейнеров
vm.swappinessМеньше (например, 10) — реже уходить в swap
vm.max_map_countElasticsearch / OpenSearch требуют 262144
fs.inotify.max_user_watchesIDE и сборщики пишут «System limit for number of file watchers reached»
fs.file-maxМаксимум открытых файлов в системе
net.core.somaxconnДлина очереди входящих соединений для нагруженных серверов
net.ipv4.ip_local_port_rangeДиапазон исходящих портов (много соединений от прокси)
kernel.panicЧерез сколько секунд перезагрузиться после kernel panic

Любой параметр — это файл: /proc/sys/net/ipv4/ip_forward = net.ipv4.ip_forward.

Модули ядра

КомандаЧто делает
lsmodЗагруженные модули
modinfo e1000eОписание, версия, параметры модуля
sudo modprobe br_netfilterЗагрузить с зависимостями
sudo modprobe -r pcspkrВыгрузить
echo br_netfilter | sudo tee /etc/modules-load.d/k8s.confЗагружать при старте
echo "blacklist nouveau" | sudo tee /etc/modprobe.d/blacklist-nouveau.confЗапретить модуль

Параметры загрузки ядра

cat /proc/cmdline                          # с какими параметрами загружено ядро
sudo nano /etc/default/grub                # GRUB_CMDLINE_LINUX="… новый_параметр"
sudo update-grub                           # Debian/Ubuntu
sudo grub2-mkconfig -o /boot/grub2/grub.cfg   # RHEL/Fedora (или: sudo grubby --update-kernel=ALL --args="…")

Лимиты процессов (ulimit)

ulimit -a                    # все лимиты текущей оболочки
ulimit -n                    # максимум открытых файлов (часто 1024 — мало для серверов)
cat /proc/PID/limits         # лимиты уже запущенного процесса
  • Для пользователей — /etc/security/limits.conf: app soft nofile 65536.
  • Для служб systemd limits.conf не действует — пиши LimitNOFILE=65536 в unit.

cgroups v2 — как ядро ограничивает ресурсы

stat -fc %T /sys/fs/cgroup                                     # cgroup2fs = используется v2
cat /sys/fs/cgroup/system.slice/nginx.service/memory.current   # сколько памяти ест служба
cat /sys/fs/cgroup/system.slice/nginx.service/cpu.stat
cat /proc/PID/cgroup                                           # в какой cgroup процесс

Cgroups — основа лимитов systemd (MemoryMax, CPUQuota), Docker (--memory, --cpus) и Kubernetes.

Capabilities — «кусочки» root

getcap /usr/bin/ping                                     # cap_net_raw=ep
sudo setcap cap_net_bind_service=+ep /opt/app/server     # слушать порт 80 без root
getpcaps PID                                             # возможности процесса

🟡 32. Безопасность и hardening

SSH-сервер: базовая защита

# /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
AllowUsers deploy admin
sudo sshd -t && sudo systemctl reload ssh      # проверить конфиг, затем применить (в RHEL служба — sshd)

💡 Имя начинается с 00-, потому что sshd берёт первое найденное значение параметра, а в облачных образах Ubuntu уже есть 50-cloud-init.conf с PasswordAuthentication yes. Итоговые настройки: sudo sshd -T.

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

fail2ban — бан за перебор паролей

# /etc/fail2ban/jail.local
[sshd]
enabled  = true
maxretry = 5
findtime = 10m
bantime  = 1h
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd              # забаненные IP
sudo fail2ban-client set sshd unbanip 1.2.3.4

Быстрый аудит сервера

sudo ss -tulpn                                        # что торчит наружу
sudo find / -xdev -perm -4000 -type f 2>/dev/null     # SUID-файлы (сравни с эталоном)
sudo find / -xdev -type f -perm -0002 2>/dev/null     # файлы, доступные на запись всем
awk -F: '$3 == 0 {print $1}' /etc/passwd              # у кого UID 0 (должен быть только root)
sudo awk -F: '$2 == "" {print $1}' /etc/shadow        # пользователи без пароля
sudo lastb | head                                     # неудачные попытки входа
sudo journalctl _COMM=sshd | grep -i "failed" | tail
sudo -l                                               # что разрешено тебе через sudo
sudo lynis audit system                               # комплексный аудит с рекомендациями

Автоматические обновления безопасности

ДистрибутивКак включить
Debian / Ubuntusudo apt install unattended-upgrades && sudo dpkg-reconfigure unattended-upgrades
RHEL / Fedorasudo dnf install dnf-automatic && sudo systemctl enable --now dnf-automatic.timer
Нужна ли перезагрузка?Ubuntu: ls /var/run/reboot-required, RHEL: sudo dnf needs-restarting -r

SELinux (RHEL, Fedora) и AppArmor (Ubuntu, Debian)

КомандаЧто делает
getenforce / sestatusРежим SELinux: Enforcing / Permissive / Disabled
ls -Z /var/wwwКонтексты файлов
sudo restorecon -Rv /var/wwwВернуть правильные контексты (после mv файлов)
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/site(/.*)?"Задать контекст для своей папки
sudo setsebool -P httpd_can_network_connect onРазрешить веб-серверу исходящие соединения
sudo semanage port -a -t http_port_t -p tcp 8081Разрешить службе новый порт
sudo ausearch -m avc -ts recentЧто SELinux заблокировал
sudo ausearch -m avc -ts recent | audit2whyПочему и как исправить
sudo aa-statusПрофили AppArmor
sudo aa-complain /etc/apparmor.d/usr.sbin.nginxПеревести профиль в режим «только логировать»

💡 «Permission denied», хотя права и владелец правильные? Почти всегда это SELinux / AppArmor. Не отключай его — исправь контекст.

auditd — кто и когда трогал файл

sudo auditctl -w /etc/passwd -p wa -k passwd_changes   # следить за записью и сменой атрибутов
sudo ausearch -k passwd_changes -i                    # кто менял (с именами пользователей)
sudo aureport --login --summary                       # сводка по входам

Шифрование и целостность

gpg -c secret.txt                        # зашифровать паролем → secret.txt.gpg
gpg -d secret.txt.gpg > secret.txt       # расшифровать
sha256sum -c SHA256SUMS                  # проверить скачанные образы по списку сумм
gpg --verify file.sig file               # проверить подпись
openssl x509 -in cert.pem -noout -subject -issuer -dates   # разобрать сертификат

Гигиена секретов

  • Пароли в аргументах команды видны всем через ps aux и остаются в ~/.bash_history. Передавай их через файл или переменную окружения.
  • Команда с пробелом в начале не попадёт в историю, если задано HISTCONTROL=ignorespace (или ignoreboth).
  • Приватные ключи и .env — права 600, никогда не в git.

🟡 33. Контейнеры изнутри: namespaces, Docker, Podman

Контейнер — это просто процесс

Контейнер = обычный процесс Linux
          + namespaces   (что процесс ВИДИТ: свои PID, сеть, файлы, hostname)
          + cgroups      (сколько процесс МОЖЕТ потребить: CPU, RAM, I/O)
          + overlayfs    (слоистая ФС образа)
          + capabilities / seccomp (что процессу ЗАПРЕЩЕНО)
NamespaceИзолирует
pidНомера процессов (внутри свой PID 1)
netИнтерфейсы, IP, порты, маршруты
mntТочки монтирования
utshostname
ipcОбщую память, очереди сообщений
userUID/GID (root внутри ≠ root снаружи)
cgroupВидимое дерево cgroups
sudo unshare --fork --pid --mount-proc bash     # «контейнер» за одну команду: ps покажет только себя
lsns                                            # список namespaces
sudo nsenter -t PID -n ip a                     # войти в сеть процесса/контейнера
sudo nsenter -t "$(docker inspect -f '{{.State.Pid}}' web)" -n ss -tlnp   # отладка сети контейнера без утилит внутри

Docker / Podman — шпаргалка

Podman — совместимая замена Docker без демона и с rootless-режимом: почти все команды ниже работают, если заменить docker на podman.

КомандаЧто делает
docker run -d --name web -p 8080:80 nginxЗапустить в фоне с пробросом порта
docker run --rm -it ubuntu bashВременный интерактивный контейнер
docker run -d -v data:/var/lib/mysql --restart unless-stopped mysqlС томом и автоперезапуском
docker run --memory 512m --cpus 1.5 appС ограничениями (cgroups)
docker ps -aВсе контейнеры
docker logs -f --tail 100 webЛоги
docker exec -it web shЗайти внутрь
docker inspect webВсё о контейнере (JSON)
docker statsCPU / RAM в реальном времени
docker cp web:/etc/nginx/nginx.conf .Скопировать файл из контейнера
docker build -t myapp:1.0 .Собрать образ
docker images / docker rmi imgОбразы / удалить образ
docker volume lsТома
docker system dfСколько места занимает Docker
docker system prune -a🔴 Удалить всё неиспользуемое
docker compose up -d / docker compose logs -f / docker compose downCompose-проект

Dockerfile: хорошие практики

# маленький базовый образ, фиксированная версия
FROM python:3.12-slim
WORKDIR /app
# сначала зависимости — слой закэшируется
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# не запускай от root
RUN useradd -r app
USER app
EXPOSE 8000
# exec-форма: сигналы доходят до процесса
CMD ["python", "app.py"]

💡 Добавь .dockerignore (.git, node_modules, .env) — образ станет меньше, а секреты не утекут.


🔴 34. Восстановление системы

Сбросить забытый пароль root

RHEL / Rocky / AlmaLinux / Fedora
  1. В меню GRUB нажми e, в строке, начинающейся с linux, допиши в конец rd.break, загрузись: Ctrl+X.
  2. Выполни:
mount -o remount,rw /sysroot
chroot /sysroot
passwd root
touch /.autorelabel      # обязательно при SELinux, иначе не сможешь войти
exit; exit
Ubuntu / Debian
  1. В GRUB нажми e, в строке linux замени ro quiet splash на rw init=/bin/bash, загрузись: Ctrl+X.
  2. Выполни:
mount -o remount,rw /    # если корень смонтирован только для чтения
passwd root              # или: passwd имя_пользователя
sync
exec /sbin/init          # продолжить загрузку (или перезагрузка кнопкой)

Починить систему через chroot с Live USB

lsblk -f                                        # найти корневой раздел
sudo mount /dev/sda2 /mnt                       # корень
sudo mount /dev/sda1 /mnt/boot/efi              # EFI-раздел (для UEFI)
for d in dev proc sys run; do sudo mount --rbind /$d /mnt/$d; done
sudo chroot /mnt
# теперь ты «внутри» сломанной системы:
grub-install /dev/sda && update-grub            # переустановить загрузчик (RHEL: grub2-mkconfig)
passwd user                                     # сменить пароль
apt install --reinstall linux-image-generic     # переустановить ядро

Частые аварии

СимптомЧто делать
Emergency mode после правки fstabmount -o remount,rw / → исправь /etc/fstab (или добавь nofail) → systemctl daemon-reload → reboot
Не грузится новое ядроВ GRUB: Advanced options → выбрать предыдущее ядро
ФС стала read-onlydmesg -T — ошибки диска; сделай бэкап, затем fsck с Live USB
Прервалось обновление (apt)sudo dpkg --configure -a && sudo apt -f install
Сломана база rpmsudo rpm --rebuilddb
Удалил файл, но процесс его держитls -l /proc/PID/fd → cp /proc/PID/fd/N ~/restored
Система зависла намертвоMagic SysRq: Alt+SysRq + по очереди R E I S U B — безопасная перезагрузка
Кончились inodedf -i → найти папку с миллионами мелких файлов: sudo du --inodes -x / 2>/dev/null | sort -n | tail
cat /proc/sys/kernel/sysrq              # 1 или битовая маска = SysRq включён
echo s | sudo tee /proc/sysrq-trigger   # сбросить буферы на диск (sync)
echo b | sudo tee /proc/sysrq-trigger   # 🔴 мгновенная перезагрузка без sync

💡 Лучшее восстановление — бэкап, который проверен: периодически восстанавливай из него на тестовую машину. Правило 3-2-1: 3 копии, 2 разных носителя, 1 — вне офиса.


🎯 35. Вопросы с собеседований

Что происходит, когда вводишь ls и жмёшь Enter?

Оболочка читает строку, раскрывает алиасы, переменные и маски, ищет ls среди функций, встроенных команд и в $PATH. Затем fork() создаёт копию процесса, в потомке execve() загружает /usr/bin/ls, тот вызывает getdents64() для чтения каталога и write() в stdout. Родитель ждёт через wait() и сохраняет код выхода в $?.

Диск заполнен на 100%, а du показывает намного меньше. Почему?
  1. Удалённый файл всё ещё открыт процессом (чаще всего лог) — sudo lsof +L1, перезапусти процесс или обнули файл через /proc/PID/fd/N. 2) Файлы спрятаны под точкой монтирования (записаны в папку до монтирования). 3) Место зарезервировано для root (5% на ext4, tune2fs -m). 4) Закончились не байты, а inode — df -i.
Чем отличаются kill -15 и kill -9?

SIGTERM (15) — просьба завершиться: процесс может перехватить сигнал, закрыть файлы, дописать данные. SIGKILL (9) — ядро убивает процесс немедленно, без очистки: возможна потеря данных и «осиротевшие» файлы блокировок. Сначала всегда 15, через несколько секунд — 9. Процесс в состоянии D не убьёт ни один сигнал.

Что такое зомби-процесс и как от него избавиться?

Процесс уже завершился, но родитель не вызвал wait() и не забрал код выхода. Ресурсов почти не ест, но занимает PID. Убить зомби нельзя — он уже мёртв. Нужно послать родителю SIGCHLD или завершить родителя: тогда зомби «усыновит» PID 1 и уберёт его.

Load average 8 на 4-ядерном сервере — это плохо?

В среднем 8 задач хотят выполняться при 4 ядрах, т.е. есть очередь. Но в Linux в load average входят и процессы в состоянии D (ожидание диска / NFS), поэтому высокая нагрузка при простаивающем CPU — признак проблемы с I/O. Смотри vmstat (r против b, wa) и /proc/pressure/*.

Почему cmd > file 2>&1 работает, а cmd 2>&1 > file — нет?

Перенаправления применяются слева направо. 2>&1 означает «сделай stderr копией того, куда сейчас указывает stdout». В первом случае stdout уже направлен в файл, во втором — ещё в терминал, поэтому ошибки останутся на экране.

Процесс и поток: в чём разница?

Процесс имеет своё адресное пространство, дескрипторы, PID. Потоки одного процесса делят память и файлы, но у каждого свой стек и регистры. В Linux и то и другое — «задачи» (task_struct), создаваемые clone() с разными флагами. Потоки видны через ps -eLf или top -H.

Что хранится в /etc/passwd и /etc/shadow?

/etc/passwd (читают все): логин, UID, GID, домашняя папка, оболочка. /etc/shadow (только root): хэши паролей и сроки их действия. Раньше хэши лежали в passwd, но их вынесли, чтобы обычные пользователи не могли подбирать пароли офлайн.

Чем опасен SUID-бит?

Программа с SUID запускается с правами владельца, обычно root. Уязвимость в ней или возможность запустить из неё оболочку = повышение привилегий. Поэтому список SUID-файлов регулярно проверяют, а /tmp и /home монтируют с nosuid. Справочник по таким программам — GTFOBins.

Что такое swap и нужен ли он при 64 ГБ RAM?

Swap — место на диске, куда ядро выгружает редко используемые страницы памяти. Даже при большом объёме RAM небольшой swap полезен: он позволяет убрать из памяти «холодные» данные в пользу кэша и даёт время среагировать до OOM killer. Склонность к swap регулирует vm.swappiness. Альтернатива — zram (сжатый swap в памяти).

Как найти, какой процесс слушает порт, и почему служба не видна снаружи?

sudo ss -tlnp | grep :8080 или sudo lsof -i :8080. Если служба слушает 127.0.0.1:8080 — она доступна только локально, нужно 0.0.0.0. Если слушает всё, проверь файрвол (ufw / firewalld / nft list ruleset), security group в облаке и SELinux.


🩺 36. Диагностика: что делать, если…

💾 Закончилось место на диске
df -h                                          # какой раздел заполнен
df -i                                          # может, кончились inode, а не байты
sudo du -xh --max-depth=1 / | sort -h | tail   # какая папка выросла (спускайся глубже)
sudo lsof +L1                                  # удалённые, но открытые файлы
sudo journalctl --vacuum-size=500M             # урезать журнал
sudo apt clean  # или: sudo dnf clean all      # кэш пакетов
docker system df                               # если на сервере Docker

Большой лог нельзя просто удалить, пока его держит процесс, — обнули его: sudo truncate -s 0 /var/log/big.log.

🔥 Сервер тормозит
uptime                          # load average против nproc
top                             # кто ест CPU (P) и память (M)
free -h                         # available и активный swap
vmstat 1 5                      # wa — ожидание диска, si/so — свопинг
iostat -xz 1 3                  # %util и await дисков
dmesg -T | tail                 # OOM killer, ошибки железа

Подробный разбор — в разделе 29. Производительность и трассировка.

🌐 Не работает сеть
ip -br a                        # есть ли IP-адрес и интерфейс UP
ip r                            # есть ли маршрут по умолчанию
ping -c3 192.168.1.1            # отвечает ли шлюз
ping -c3 8.8.8.8                # есть ли интернет по IP
dig google.com                  # работает ли DNS (если IP пингуется, а имя — нет)
cat /etc/resolv.conf            # какие DNS-серверы используются
curl -v https://example.com     # доходит ли HTTP

Пингуется IP, но не имя — проблема в DNS. Не пингуется шлюз — кабель, Wi-Fi или настройки интерфейса.

⚙️ Служба не запускается
systemctl status myapp                  # статус и последние строки лога
journalctl -u myapp -b --no-pager | tail -50   # полный лог с загрузки
sudo nginx -t                           # многие службы умеют проверять конфиг (nginx -t, sshd -t, apachectl configtest)
sudo ss -tulpn | grep :80               # не занят ли порт другим процессом
systemctl cat myapp                     # что реально запускается

Правил unit-файл — не забудь sudo systemctl daemon-reload.

🔑 Permission denied
ls -l file                      # владелец и права файла
namei -l /path/to/file          # права на КАЖДУЮ папку пути (нужен x на всех)
id                              # в каких ты группах
sudo -l                         # что разрешено через sudo
ls -Z file                      # контекст SELinux (RHEL/Fedora)
  • Скрипт не запускается — chmod +x script.sh или раздел смонтирован с noexec (findmnt -T .).
  • Добавили в группу — нужно перелогиниться (или newgrp group).
  • SSH-ключ не принимается — права: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys.
🧟 Зависший процесс не убивается
ps -o pid,stat,wchan:30,cmd -p PID    # состояние и где ждёт
sudo cat /proc/PID/stack              # стек в ядре
ps -o ppid= -p PID                    # родитель (для зомби)
  • Z (зомби) — убей или перезапусти родителя.
  • D (ждёт диск / NFS) — сигналы не помогут; ищи причину в dmesg (умерший диск, недоступный NFS: umount -f -l). Иногда поможет только перезагрузка.
  • T (остановлен) — kill -CONT PID.

⚠️ 37. Опасные команды 🔴

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

КомандаЧто произойдёт
rm -rf / или rm -rf /*Удалит всю систему
rm -rf ~Удалит все твои файлы
rm -rf $VAR/ при пустой $VARПревратится в rm -rf /
dd if=/dev/zero of=/dev/sdaЗатрёт весь диск
mkfs.ext4 /dev/sdaОтформатирует диск
chmod -R 777 /Сломает систему и безопасность
:(){ :|:& };:Fork-бомба — повесит систему
curl URL | sudo bashЗапустит неизвестный код от root
> /etc/passwdОбнулит файл пользователей

💡 Перед опасной операцией: сделай бэкап, проверь путь через ls, используй rm -i и set -u в скриптах.


🧰 38. Практические сценарии: пошаговые рецепты

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

Сценарий 1. Новый сервер Ubuntu за 10 минут

# 1. Обновить систему
sudo apt update && sudo apt full-upgrade -y

# 2. Создать пользователя с правами sudo
sudo adduser deploy
sudo usermod -aG sudo deploy

# 3. Скопировать SSH-ключ (выполнить на СВОЁМ компьютере) и проверить вход
ssh-copy-id deploy@SERVER_IP
ssh deploy@SERVER_IP

# 4. Запретить вход root и по паролю — только ПОСЛЕ успешного входа по ключу!
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
EOF
sudo sshd -t && sudo systemctl reload ssh

# 5. Файрвол: сначала SSH, потом включение
sudo ufw allow OpenSSH
sudo ufw enable

# 6. Защита от перебора паролей и автообновления безопасности
sudo apt install -y fail2ban unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

# 7. Часовой пояс и имя хоста
sudo timedatectl set-timezone Europe/Moscow
sudo hostnamectl set-hostname web-01

💡 Файл называется 00-hardening.conf не случайно: sshd берёт первое найденное значение параметра, а в облачных образах Ubuntu уже лежит 50-cloud-init.conf с PasswordAuthentication yes. Проверить итоговые настройки: sudo sshd -T | grep -Ei 'permitroot|passwordauth'.

Сценарий 2. Сайт на nginx с бесплатным HTTPS

Перед началом A-запись домена в DNS должна указывать на IP сервера.

sudo apt install -y nginx
sudo mkdir -p /var/www/example.com
echo '<h1>Работает!</h1>' | sudo tee /var/www/example.com/index.html

sudo tee /etc/nginx/sites-available/example.com <<'EOF'
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html;
    location / { try_files $uri $uri/ =404; }
}
EOF

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx     # всегда проверяй конфиг перед reload
sudo ufw allow 'Nginx Full'                     # порты 80 и 443

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com   # получит сертификат и настроит редирект на HTTPS
sudo certbot renew --dry-run                    # проверить автопродление

Сценарий 3. Бэкап с ротацией и проверкой

/usr/local/bin/backup.sh:

#!/usr/bin/env bash
set -euo pipefail

SRC=/var/www          # что бэкапим
DST=/backup           # куда
KEEP=7                # сколько последних архивов хранить

mkdir -p "$DST"
file="$DST/www-$(date +%F_%H%M).tar.gz"

tar -czf "$file" -C "$(dirname "$SRC")" "$(basename "$SRC")"
tar -tzf "$file" > /dev/null                     # архив читается целиком?

ls -1t "$DST"/www-*.tar.gz | tail -n +$((KEEP + 1)) | xargs -r rm --   # удалить старые
echo "OK: $file ($(du -h "$file" | cut -f1))"
sudo chmod 700 /usr/local/bin/backup.sh
sudo /usr/local/bin/backup.sh                    # проверить вручную
# базы данных — отдельным дампом, а не копией файлов:
pg_dump -Fc mydb > /backup/mydb-$(date +%F).dump                  # PostgreSQL
mysqldump --single-transaction mydb | gzip > /backup/mydb-$(date +%F).sql.gz   # MySQL / MariaDB
# копия вне сервера (правило 3-2-1):
rsync -az /backup/ backup@remote:/srv/backups/web-01/

Запуск по расписанию — через таймер systemd (раздел 30) или cron: 0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1.

Сценарий 4. Разбор логов nginx: кто, что и с какой ошибкой

Формат combined: $1 — IP, $4 — время, $7 — URL, $9 — код ответа, $10 — размер.

LOG=/var/log/nginx/access.log

awk '{print $1}' "$LOG" | sort | uniq -c | sort -rn | head          # топ IP
awk '{print $9}' "$LOG" | sort | uniq -c | sort -rn                 # сколько каких кодов
awk '$9 >= 500 {print $7}' "$LOG" | sort | uniq -c | sort -rn | head   # URL с ошибками 5xx
awk '{print $7}' "$LOG" | sort | uniq -c | sort -rn | head          # популярные страницы
awk -F'"' '{print $6}' "$LOG" | sort | uniq -c | sort -rn | head    # топ User-Agent (боты видно сразу)
awk '{print substr($4, 2, 17)}' "$LOG" | uniq -c | tail             # запросов в минуту
awk '{s += $10} END {printf "%.1f MB\n", s/1024/1024}' "$LOG"       # отданный трафик
zcat -f "$LOG"* | awk '$9 == 404' | wc -l                           # 404 с учётом старых .gz-логов
tail -f "$LOG" | grep --line-buffered '" 5[0-9][0-9] '              # следить за 5xx в реальном времени

Сценарий 5. Подключить новый диск навсегда

lsblk                                                    # найти новый диск, например /dev/sdb
sudo parted /dev/sdb --script mklabel gpt mkpart primary ext4 0% 100%   # 🔴 проверь букву диска!
sudo mkfs.ext4 -L data /dev/sdb1
sudo mkdir -p /data
echo "UUID=$(sudo blkid -s UUID -o value /dev/sdb1) /data ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
sudo systemctl daemon-reload
sudo mount -a && df -h /data                             # ошибок нет — можно перезагружаться

Сценарий 6. Переезд данных на новый сервер

# 1. Первый проход — пока всё работает (можно гонять сколько угодно раз)
rsync -aHAX --numeric-ids --info=progress2 /var/www/ root@new:/var/www/

# 2. Посмотреть, что изменится, не копируя
rsync -aHAX --numeric-ids --delete --dry-run /var/www/ root@new:/var/www/

# 3. Окно переключения: остановить запись и быстро догнать разницу
sudo systemctl stop myapp
rsync -aHAX --numeric-ids --delete /var/www/ root@new:/var/www/
# 4. Переключить DNS / IP на новый сервер

💡 За сутки до переезда уменьши TTL DNS-записи до 300 секунд — переключение разойдётся за минуты, а не за часы.

Сценарий 7. Уведомления в Telegram из скриптов

Создай бота у @BotFather, узнай свой chat_id, сохрани их в /etc/default/notify (права 600):

# /etc/default/notify
TG_TOKEN=123456:ABC...
TG_CHAT_ID=123456789
#!/usr/bin/env bash
# /usr/local/bin/healthcheck.sh — запускать по таймеру каждые 5 минут
source /etc/default/notify

notify() {
  curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
       -d chat_id="${TG_CHAT_ID}" --data-urlencode text="$1" > /dev/null
}

systemctl is-active --quiet nginx || notify "🔥 $(hostname): nginx не работает"
use=$(df --output=pcent / | tail -1 | tr -dc '0-9')
(( use > 85 )) && notify "💾 $(hostname): диск / заполнен на $use%"
load=$(cut -d' ' -f1 /proc/loadavg)
awk -v l="$load" -v n="$(nproc)" 'BEGIN {exit !(l > n * 2)}' && notify "🔥 $(hostname): load average $load"
exit 0

Сценарий 8. Ротация логов своего приложения

/etc/logrotate.d/myapp:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}
sudo logrotate -d /etc/logrotate.d/myapp    # пробный прогон: что будет сделано
sudo logrotate -f /etc/logrotate.d/myapp    # выполнить принудительно

copytruncate нужен, если приложение не умеет переоткрывать лог по сигналу; иначе используй postrotate с systemctl reload myapp.


🎓 39. Практикум: задачи с решениями

Лучший способ запомнить команды — решать задачи. Сначала подготовь учебный полигон, потом решай сам и только после этого открывай решение.

Подготовка полигона

Скрипт создаёт в ~/lab файлы, лог веб-сервера, CSV и конфиг. Ничего вне этой папки не трогает — ломай смело.

mkdir -p ~/lab && cd ~/lab
mkdir -p data logs trash "folder with space"

# 50 файлов случайного размера, первые 10 — «старые»
for i in $(seq 1 50); do head -c $((RANDOM * 10)) /dev/urandom > "data/file_$i.bin"; done
touch -d '40 days ago' data/file_{1..10}.bin
touch "folder with space/report 2025.txt" data/notes.txt data/photo.jpg data/script.sh

# Лог веб-сервера в формате nginx combined (1000 строк, по времени)
awk -v now="$(date +%s)" 'BEGIN {
  srand(42)
  split("200 200 200 200 200 301 404 404 500 502", codes)
  split("/ /login /api/users /api/orders /static/app.js /admin", urls)
  split("Mozilla/5.0 curl/8.5 Googlebot/2.1 python-requests/2.31", uas)
  for (i = 1000; i >= 1; i--) {
    t = now - i * 60
    printf "192.168.1.%d - - [%s] \"GET %s HTTP/1.1\" %s %d \"-\" \"%s\"\n",
      int(rand() * 20) + 1, strftime("%d/%b/%Y:%H:%M:%S %z", t),
      urls[int(rand() * 6) + 1], codes[int(rand() * 10) + 1],
      int(rand() * 50000), uas[int(rand() * 4) + 1]
  }
}' > logs/access.log

# Таблица сотрудников
cat > staff.csv <<'EOF'
name,dept,salary
Anna,IT,120000
Boris,Sales,80000
Vera,IT,150000
Gleb,HR,70000
Dina,Sales,95000
Egor,IT,110000
Zhanna,HR,72000
EOF

# Конфиг с комментариями
cat > app.conf <<'EOF'
# Основные настройки
port=8080
debug=true

host=0.0.0.0
# Производительность
workers=4
EOF

ls -la ~/lab

💡 strftime есть в GNU awk (gawk). Если скрипт ругается — установи его: sudo apt install gawk.

🟢 Уровень 1: основы

1. Создай в ~/lab папку project с подпапками src, tests и docs одной командой
mkdir -p project/{src,tests,docs}
tree project        # или: ls -R project
2. Найди в data все файлы больше 200 КБ
find data -type f -size +200k
find data -type f -size +200k -exec ls -lh {} +     # с размерами
3. Перенеси файлы старше 30 дней из data в trash
find data -type f -mtime +30                          # сначала посмотри, что найдётся
find data -type f -mtime +30 -exec mv -t trash/ {} +
ls trash | wc -l                                      # должно быть 10

Правило: перед любым массовым действием запусти find без действия и проверь список.

4. Сколько строк в логе и сколько в нём уникальных IP-адресов?
wc -l logs/access.log
awk '{print $1}' logs/access.log | sort -u | wc -l
5. Выведи app.conf без комментариев и пустых строк
grep -Ev '^\s*(#|$)' app.conf

-E — расширенные регулярки, -v — инвертировать: убрать строки, которые начинаются с # или пустые.

6. Сделай data/script.sh исполняемым только для владельца, а остальным запрети всё
chmod 700 data/script.sh          # или: chmod u=rwx,go= data/script.sh
ls -l data/script.sh              # -rwx------
7. Выведи всех пользователей системы, у которых оболочка bash
awk -F: '$7 ~ /bash$/ {print $1}' /etc/passwd
grep 'bash$' /etc/passwd | cut -d: -f1      # то же самое
8. Покажи размер каждой подпапки ~/lab, от меньшей к большей
du -sh ~/lab/*/ | sort -h
9. Упакуй папку logs в архив с сегодняшней датой в имени и посмотри содержимое, не распаковывая
tar -czf "logs-$(date +%F).tar.gz" logs
tar -tzvf logs-*.tar.gz
10. Удали файл «report 2025.txt» из папки с пробелом в имени
rm "folder with space/report 2025.txt"
# или с экранированием: rm folder\ with\ space/report\ 2025.txt
# или: нажми Tab — bash сам подставит правильно экранированное имя

🟡 Уровень 2: обработка данных

11. Топ-5 IP по количеству запросов
awk '{print $1}' logs/access.log | sort | uniq -c | sort -rn | head -5

Классический конвейер «частотный словарь»: вытащить поле → отсортировать → посчитать одинаковые → отсортировать по числу.

12. Сколько было ответов каждого кода (200, 404, 500…)?
awk '{print $9}' logs/access.log | sort | uniq -c | sort -rn
13. Какие URL чаще всего отдают ошибки 5xx?
awk '$9 >= 500 {print $7}' logs/access.log | sort | uniq -c | sort -rn
14. Посчитай общий объём отданных данных в мегабайтах
awk '{s += $10} END {printf "%.2f MB\n", s / 1024 / 1024}' logs/access.log
15. Построй гистограмму запросов по часам
awk -F: '{print $2}' logs/access.log | sort | uniq -c
# с «графиком» из звёздочек:
awk -F: '{h[$2]++} END {for (k in h) {printf "%s ", k; for (i = 0; i < h[k] / 5; i++) printf "*"; print ""}}' logs/access.log | sort

Разделитель : режет строку так, что второе поле — это час из [23/Sep/2026:14:05:01.

16. Средняя зарплата по отделам из staff.csv
awk -F, 'NR > 1 {sum[$2] += $3; n[$2]++}
         END {for (d in sum) printf "%-6s %d\n", d, sum[d] / n[d]}' staff.csv

NR > 1 пропускает заголовок, массивы sum и n индексируются названием отдела.

17. Кто получает больше всех? Выведи имя и зарплату
tail -n +2 staff.csv | sort -t, -k3 -rn | head -1 | cut -d, -f1,3
18. Замени в app.conf debug=true на debug=false, сохранив резервную копию, и покажи разницу
sed -i.bak 's/^debug=true$/debug=false/' app.conf
diff -u app.conf.bak app.conf
19. Переименуй все .bin в data в .dat
for f in data/*.bin; do mv -- "$f" "${f%.bin}.dat"; done
ls data | head

${f%.bin} отрезает суффикс, -- защищает от имён, начинающихся с дефиса.

20. Посчитай файлы в ~/lab по расширениям
find ~/lab -type f -name '*.*' | sed 's/.*\.//' | sort | uniq -c | sort -rn

🔴 Уровень 3: скрипты и система

21. Напиши скрипт check_disk.sh: предупреждение, если любой раздел заполнен больше чем на N% (по умолчанию 80), и код выхода 1
#!/usr/bin/env bash
set -euo pipefail

limit=${1:-80}
status=0

while read -r pcent target; do
  use=${pcent%\%}
  if (( use > limit )); then
    echo "⚠️  $target заполнен на $use%"
    status=1
  fi
done < <(df --output=pcent,target -x tmpfs -x devtmpfs | tail -n +2)

exit "$status"
chmod +x check_disk.sh
./check_disk.sh 10; echo "код выхода: $?"

⚠️ Ловушка: если написать df … | while read …, цикл выполнится в подоболочке и переменная status после него будет снова 0. Поэтому используется < <(…).

22. Запускай check_disk.sh каждые 15 минут через таймер systemd
sudo cp check_disk.sh /usr/local/bin/

sudo tee /etc/systemd/system/check-disk.service <<'EOF'
[Unit]
Description=Check disk usage
[Service]
Type=oneshot
ExecStart=/usr/local/bin/check_disk.sh 85
EOF

sudo tee /etc/systemd/system/check-disk.timer <<'EOF'
[Unit]
Description=Check disk usage every 15 minutes
[Timer]
OnCalendar=*:0/15
Persistent=true
[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now check-disk.timer
systemctl list-timers check-disk.timer
journalctl -u check-disk.service      # результаты проверок
23. Оставь в папке только 7 самых свежих бэкапов
# подготовка: 12 «бэкапов» с разными датами
mkdir -p ~/lab/backups && cd ~/lab/backups
for i in $(seq 1 12); do touch -d "$i days ago" "backup-$i.tar.gz"; done

ls -1t backup-*.tar.gz | tail -n +8                     # сначала — что будет удалено
ls -1t backup-*.tar.gz | tail -n +8 | xargs -r rm --
ls -1t

ls -1t сортирует от новых к старым, tail -n +8 берёт всё начиная с восьмого, xargs -r ничего не делает, если список пуст.

24. Проверь параллельно список хостов и выведи только недоступные
printf '%s\n' 8.8.8.8 1.1.1.1 10.255.255.1 192.0.2.1 > hosts.txt
xargs -P 10 -I{} sh -c 'ping -c1 -W2 {} > /dev/null 2>&1 || echo "DOWN {}"' < hosts.txt

-P 10 — до 10 проверок одновременно, -W2 — ждать ответ не больше 2 секунд.

25. Найди процессы, которые держат удалённые файлы, и посчитай, сколько места они занимают
# воспроизвести проблему:
python3 -c 'import time; f = open("/tmp/big.log", "w"); f.write("x" * 100_000_000); f.flush(); time.sleep(600)' &
sleep 1; rm /tmp/big.log
df -h /tmp                                             # место не освободилось

sudo lsof -nP +L1                                      # вот он — (deleted)
sudo lsof -nP +L1 | awk 'NR > 1 {s += $7} END {printf "%.1f MB\n", s / 1024 / 1024}'
kill %1                                                # место вернётся после завершения процесса
26. Запусти программу с лимитом памяти 100 МБ и убедись, что её убьёт ядро
sudo systemd-run --scope -p MemoryMax=100M -p MemorySwapMax=0 \
  python3 -c 'a = bytearray(500 * 1024 * 1024); print("выжил")'
echo "код выхода: $?"                                  # 137 = убит сигналом 9 (128 + 9)
sudo dmesg -T | grep -i "killed process" | tail -1

Так работают лимиты MemoryMax в systemd и --memory в Docker — это одни и те же cgroups.

27. Создай «контейнер» без Docker: свои PID и hostname
sudo unshare --fork --pid --mount-proc --uts bash
hostname lab-container
ps aux                 # видно только bash и ps — у тебя PID 1
hostname               # lab-container
exit
hostname               # на хосте имя не изменилось
28. Узнай, какие системные вызовы делает ls и какие файлы он открывает
strace -c ls > /dev/null                       # сводка по вызовам
strace -e trace=openat ls 2>&1 | head -20      # какие файлы открываются (библиотеки, локали)
strace -e trace=openat ls /nonexistent 2>&1 | tail -3   # как выглядит ошибка ENOENT

🏁 Задачи для самостоятельной работы (без решений)

  1. Напиши скрипт, который раз в минуту дописывает в CSV время, load average, свободную память и заполнение /. Потом построй по нему отчёт через awk: максимум и среднее за день.
  2. Создай LVM на двух «виртуальных дисках» из файлов (truncate -s 1G d1.img && sudo losetup -fP d1.img), сделай на нём ФС, наполни данными и расширь том, не размонтируя.
  3. Подними в docker compose nginx и простое приложение, настрой nginx как reverse proxy и ограничь приложению память.
  4. В виртуальной машине специально сделай опечатку в /etc/fstab, перезагрузись и почини систему из emergency mode.
  5. Настрой вход по SSH только по ключу, включи fail2ban и проверь, что после 5 неверных паролей с другой машины IP попадает в бан.
  6. Напиши свою службу systemd для любого скрипта с Restart=on-failure, убей процесс через kill -9 и убедись, что systemd его поднял (NRestarts в systemctl show).
  7. Пройди первые 15 уровней OverTheWire: Bandit.

📘 Глоссарий

ТерминКоротко
ShellОболочка — программа, которая читает и выполняет команды (bash, zsh)
RootСуперпользователь с UID 0, может всё
PID / PPIDНомер процесса / номер его родителя
DaemonФоновая служба без терминала (sshd, cron)
InodeЗапись с метаданными файла; имя — лишь ссылка на неё
Mount pointПапка, к которой подключён раздел или устройство
UnitОбъект systemd: служба (.service), таймер (.timer), точка монтирования (.mount)
Pipe| — передача вывода одной команды на вход другой
Exit codeКод завершения команды: 0 — успех
EnvironmentПеременные окружения, наследуемые процессами
RepositoryСервер с пакетами дистрибутива
Kernel moduleДрайвер, подгружаемый в ядро на лету (lsmod, modprobe)
SwapОбласть на диске, расширяющая оперативную память
TTYТерминал; tty покажет текущий
FHSСтандарт структуры каталогов Linux
cgroupМеханизм ядра для лимитов CPU, памяти и I/O группы процессов
NamespaceИзоляция того, что видит процесс: PID, сеть, ФС, hostname — основа контейнеров
LVMЛогические тома: гибкие разделы поверх дисков, расширение на лету, снапшоты
RAIDОбъединение дисков для скорости и/или отказоустойчивости (mdadm)
SELinux / AppArmorМандатный контроль доступа поверх обычных прав
CapabilitiesОтдельные привилегии root, которые можно выдать программе точечно
eBPFБезопасные программы внутри ядра для трассировки, сети и безопасности
PSIPressure Stall Information — сколько времени задачи ждут CPU, память или диск
Drop-inФайл-дополнение к unit systemd (systemctl edit), не трогающий оригинал
chrootЗапуск команд с другим корнем ФС — используется при восстановлении системы

📖 Полезные ресурсы

  • The Linux Command Line — бесплатная книга Уильяма Шоттса
  • explainshell.com — разбор любой команды по частям
  • tldr pages — короткие примеры для тысяч команд
  • ShellCheck — проверка bash-скриптов
  • crontab.guru — редактор cron-выражений
  • OverTheWire: Bandit — игра для практики Linux
  • Arch Wiki — лучшая документация, полезна для любого дистрибутива
  • Brendan Gregg: Linux Performance — всё о производительности и eBPF
  • GTFOBins — как стандартные утилиты используют для повышения привилегий

🤝 Как помочь проекту

Нашёл ошибку или знаешь полезную команду?

  1. Сделай Fork репозитория
  2. Добавь или исправь команду (коротко, с понятным описанием)
  3. Открой Pull Request

Идеи и вопросы — в Issues.

Если шпаргалка помогла — поставь ⭐, это помогает другим найти её!

Распространяется по лицензии MIT.

linux шпаргалка · команды linux · linux cheat sheet · bash шпаргалка · терминал linux для начинающих · команды терминала ubuntu · linux commands · shell cheatsheet · devops · sysadmin · chmod · grep · sed · awk · ssh · systemctl · journalctl · cron · vim · lvm · raid · cgroups · namespaces · selinux · docker · podman · ebpf · strace · perf · sysctl · hardening · собеседование linux

关于 About

Linux полная шпаргалка по командам на русском

语言 Languages

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
2
Total Commits
峰值: 2次/周
Less
More

核心贡献者 Contributors