🐧 Linux Cheat Sheet — шпаргалка по командам Linux
Самая удобная шпаргалка по Linux и Bash на русском: теория простым языком (как устроены файлы, процессы, права, память, загрузка и сеть), команды терминала, права доступа, процессы, сеть, SSH, systemd, grep/sed/awk, Vim и готовые однострочники — с примерами. А для тех, кто идёт дальше, — продвинутый уровень: Bash для профи, LVM и RAID, трассировка и производительность, ядро, безопасность, контейнеры, восстановление системы и вопросы с собеседований. И практикум: 8 пошаговых сценариев из реальной работы и 28 задач с решениями на учебном полигоне.
⭐ Поставь звезду, чтобы шпаргалка всегда была под рукой!
Для кого: начинающие пользователи 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-ресурсов для прокачки.
📚 Содержание
- 🧠 Теория: как устроен Linux — ядро, файлы, inode, права, процессы, потоки, PATH, кавычки, память, загрузка, ФС, пакеты, сеть, SSH-ключи
- Первые шаги и справка
- Навигация по файловой системе
- Работа с файлами и папками
- Просмотр содержимого файлов
- Поиск: find, locate, grep
- Права доступа: chmod, chown
- Пользователи и группы, sudo
- Процессы и сигналы
- Информация о системе
- Диски и файловые системы
- Сеть
- SSH, SCP, rsync
- Архивы и сжатие
- Пакетные менеджеры
- Systemd и службы
- Логи и journalctl
- Обработка текста: sed, awk, cut, sort
- Перенаправление, пайпы, xargs
- Bash: переменные и скрипты
- Горячие клавиши терминала
- Vim — минимум для выживания
- Cron — планировщик задач
- Файрвол: ufw, firewalld, iptables
- Структура каталогов Linux (FHS)
- Полезные однострочники
- 🟡 Bash для профи: массивы, раскрытие параметров, trap
- 🟡 LVM, RAID и снапшоты
- 🟡 Продвинутая сеть
- 🟡 Производительность и трассировка
- 🟡 Systemd для профи
- 🟡 Ядро: sysctl, модули, лимиты, cgroups
- 🟡 Безопасность и hardening
- 🟡 Контейнеры изнутри: namespaces, Docker, Podman
- 🔴 Восстановление системы
- 🎯 Вопросы с собеседований
- Диагностика: что делать, если…
- Опасные команды
- 🧰 Практические сценарии: пошаговые рецепты
- 🎓 Практикум: задачи с решениями
- Глоссарий
🧠 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. Выглядят похоже, но значат разное:
| Смысл | Glob | Regex |
|---|---|---|
| Любая строка | * | .* |
| Один любой символ | ? | . |
| Один из набора | [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.target | 0 | Выключение |
rescue.target | 1 | Однопользовательский режим восстановления |
multi-user.target | 3 | Сервер: сеть, без графики |
graphical.target | 5 | Рабочий стол |
reboot.target | 6 | Перезагрузка |
Текущий: systemctl get-default, сменить: sudo systemctl set-default multi-user.target.
0.12. Файловые системы и монтирование
В Linux нет «дисков C: и D:» — есть одно дерево от /, а разделы и флешки монтируются в его папки (/home, /mnt/usb). Список при загрузке задаётся в /etc/fstab.
| ФС | Где применяется | Особенности |
|---|---|---|
| ext4 | Стандарт для большинства дистрибутивов | Надёжная, журналируемая |
| XFS | RHEL, большие серверы | Быстрая на больших файлах, не уменьшается |
| Btrfs | Fedora, openSUSE | Снапшоты, сжатие, copy-on-write |
| ZFS | NAS, серверы хранения | Снапшоты, 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 |
| localhost | 127.0.0.1 — сам компьютер |
| Приватные сети | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 — не маршрутизируются в интернет |
Частые порты:
| Порт | Служба | Порт | Служба |
|---|---|---|---|
| 22 | SSH | 443 | HTTPS |
| 25 / 587 | SMTP | 3306 | MySQL |
| 53 | DNS | 5432 | PostgreSQL |
| 80 | HTTP | 6379 | Redis |
| 123 | NTP | 8080 | HTTP (альтернативный) |
Порты ниже 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 | head | Hex-дамп |
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 # посчитать строки во всех .jslocate — быстрый поиск по базе
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 ссылка
Числовые права
| Цифра | Права | Значение |
|---|---|---|
| 7 | rwx | чтение + запись + выполнение |
| 6 | rw- | чтение + запись |
| 5 | r-x | чтение + выполнение |
| 4 | r-- | только чтение |
| 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)Специальные биты 🟡
| Бит | Число | Эффект |
|---|---|---|
| SUID | 4xxx | Файл запускается с правами владельца (passwd) |
| SGID | 2xxx | На папке — новые файлы наследуют группу |
| Sticky | 1xxx | В папке удалять файлы может только владелец (/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 | Текущий пользователь |
id | UID, 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 nginx | PID и команда по имени |
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.
Сигналы
| Сигнал | № | Назначение |
|---|---|---|
SIGHUP | 1 | Перечитать конфиг / терминал закрыт |
SIGINT | 2 | Ctrl+C |
SIGKILL | 9 | Убить немедленно (нельзя перехватить) |
SIGTERM | 15 | Корректное завершение (по умолчанию) |
SIGSTOP | 19 | Пауза (Ctrl+Z — это SIGTSTP) |
SIGCONT | 18 | Продолжить |
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 / lsusb | PCI / USB-устройства |
sudo dmidecode -t memory | Планки памяти |
vmstat 1 | CPU, память, 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 blkid | UUID разделов |
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 a | IP-адреса интерфейсов |
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.com | HTTP-заголовки |
curl -O URL | Скачать файл |
wget -c URL | Скачать с докачкой |
curl ifconfig.me | Внешний IP |
dig example.com | DNS-запрос |
dig +short example.com MX | MX-записи |
nslookup example.com | DNS (простой вариант) |
host example.com | DNS (ещё проще) |
cat /etc/resolv.conf | Используемые DNS-серверы |
cat /etc/hosts | Локальные имена хостов |
nc -zv host 22 | Проверить, открыт ли порт |
sudo tcpdump -i eth0 port 80 | 🟡 Перехват трафика |
nmcli device wifi list | Wi-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 / Ubuntu | Fedora / RHEL | Arch |
|---|---|---|---|
| Обновить списки | apt update | dnf check-update | pacman -Sy |
| Обновить систему | apt upgrade | dnf upgrade | pacman -Syu |
| Установить | apt install pkg | dnf install pkg | pacman -S pkg |
| Удалить | apt remove pkg | dnf remove pkg | pacman -R pkg |
| Удалить с конфигами | apt purge pkg | — | pacman -Rns pkg |
| Поиск | apt search pkg | dnf search pkg | pacman -Ss pkg |
| Информация | apt show pkg | dnf info pkg | pacman -Si pkg |
| Установленные | apt list --installed | dnf list installed | pacman -Q |
| Чей это файл | dpkg -S /bin/ls | rpm -qf /bin/ls | pacman -Qo /bin/ls |
| Убрать лишнее | apt autoremove | dnf autoremove | pacman -Rns $(pacman -Qdtq) |
| Установить файл | dpkg -i pkg.deb | dnf install ./pkg.rpm | pacman -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.targetsudo 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 > file | stdout в файл (перезаписать) |
cmd >> file | stdout в файл (дописать) |
cmd 2> err.log | stderr в файл |
cmd > out.log 2>&1 | stdout и 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 verbose | sudo firewall-cmd --list-all |
| Включить | sudo ufw enable | sudo systemctl enable --now firewalld |
| Открыть порт | sudo ufw allow 443/tcp | sudo firewall-cmd --add-port=443/tcp --permanent |
| Разрешить службу | sudo ufw allow OpenSSH | sudo firewall-cmd --add-service=http --permanent |
| Закрыть порт | sudo ufw delete allow 443/tcp | sudo firewall-cmd --remove-port=443/tcp --permanent |
| Разрешить IP | sudo ufw allow from 10.0.0.5 | sudo 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 ]] || usageHere-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 line | while 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 $var | printf '%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 0 | 2 | ❌ ни одного | 100% (только скорость) |
| RAID 1 | 2 | 1 диск | 50% (зеркало) |
| RAID 5 | 3 | 1 диск | (N−1)/N |
| RAID 6 | 4 | 2 диска | (N−2)/N |
| RAID 10 | 4 | по 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 eth0HTTP, 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 (ошибки).
| Ресурс | Загрузка | Насыщение | Ошибки |
|---|---|---|---|
| CPU | mpstat -P ALL 1, top | vmstat 1 (колонка r > ядер), load average | dmesg |
| Память | free -h | vmstat 1 (si/so ≠ 0), OOM в dmesg | dmesg |
| Диск | iostat -xz 1 (%util) | iostat (aqu-sz, await) | smartctl, dmesg |
| Сеть | sar -n DEV 1 | ss -s, ретрансмиты sar -n ETCP 1 | ip -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 1 | I/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.targetsystemd-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.targetsudo 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_forward | 1 — сервер работает роутером / NAT / для контейнеров |
vm.swappiness | Меньше (например, 10) — реже уходить в swap |
vm.max_map_count | Elasticsearch / OpenSearch требуют 262144 |
fs.inotify.max_user_watches | IDE и сборщики пишут «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 adminsudo 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 = 1hsudo 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 / Ubuntu | sudo apt install unattended-upgrades && sudo dpkg-reconfigure unattended-upgrades |
| RHEL / Fedora | sudo 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 | Точки монтирования |
uts | hostname |
ipc | Общую память, очереди сообщений |
user | UID/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 stats | CPU / 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 down | Compose-проект |
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
- В меню GRUB нажми
e, в строке, начинающейся сlinux, допиши в конецrd.break, загрузись:Ctrl+X. - Выполни:
mount -o remount,rw /sysroot
chroot /sysroot
passwd root
touch /.autorelabel # обязательно при SELinux, иначе не сможешь войти
exit; exitUbuntu / Debian
- В GRUB нажми
e, в строкеlinuxзамениro quiet splashнаrw init=/bin/bash, загрузись:Ctrl+X. - Выполни:
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 после правки fstab | mount -o remount,rw / → исправь /etc/fstab (или добавь nofail) → systemctl daemon-reload → reboot |
| Не грузится новое ядро | В GRUB: Advanced options → выбрать предыдущее ядро |
| ФС стала read-only | dmesg -T — ошибки диска; сделай бэкап, затем fsck с Live USB |
| Прервалось обновление (apt) | sudo dpkg --configure -a && sudo apt -f install |
| Сломана база rpm | sudo rpm --rebuilddb |
| Удалил файл, но процесс его держит | ls -l /proc/PID/fd → cp /proc/PID/fd/N ~/restored |
| Система зависла намертво | Magic SysRq: Alt+SysRq + по очереди R E I S U B — безопасная перезагрузка |
| Кончились inode | df -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 показывает намного меньше. Почему?
- Удалённый файл всё ещё открыт процессом (чаще всего лог) —
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 project2. Найди в 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 -l5. Выведи 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 -h9. Упакуй папку logs в архив с сегодняшней датой в имени и посмотри содержимое, не распаковывая
tar -czf "logs-$(date +%F).tar.gz" logs
tar -tzvf logs-*.tar.gz10. Удали файл «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 -rn13. Какие URL чаще всего отдают ошибки 5xx?
awk '$9 >= 500 {print $7}' logs/access.log | sort | uniq -c | sort -rn14. Посчитай общий объём отданных данных в мегабайтах
awk '{s += $10} END {printf "%.2f MB\n", s / 1024 / 1024}' logs/access.log15. Построй гистограмму запросов по часам
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.csvNR > 1 пропускает заголовок, массивы sum и n индексируются названием отдела.
17. Кто получает больше всех? Выведи имя и зарплату
tail -n +2 staff.csv | sort -t, -k3 -rn | head -1 | cut -d, -f1,318. Замени в app.conf debug=true на debug=false, сохранив резервную копию, и покажи разницу
sed -i.bak 's/^debug=true$/debug=false/' app.conf
diff -u app.conf.bak app.conf19. Переименуй все .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 -1tls -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🏁 Задачи для самостоятельной работы (без решений)
- Напиши скрипт, который раз в минуту дописывает в CSV время, load average, свободную память и заполнение
/. Потом построй по нему отчёт черезawk: максимум и среднее за день. - Создай LVM на двух «виртуальных дисках» из файлов (
truncate -s 1G d1.img && sudo losetup -fP d1.img), сделай на нём ФС, наполни данными и расширь том, не размонтируя. - Подними в
docker composenginx и простое приложение, настрой nginx как reverse proxy и ограничь приложению память. - В виртуальной машине специально сделай опечатку в
/etc/fstab, перезагрузись и почини систему из emergency mode. - Настрой вход по SSH только по ключу, включи fail2ban и проверь, что после 5 неверных паролей с другой машины IP попадает в бан.
- Напиши свою службу systemd для любого скрипта с
Restart=on-failure, убей процесс черезkill -9и убедись, что systemd его поднял (NRestartsвsystemctl show). - Пройди первые 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 | Безопасные программы внутри ядра для трассировки, сети и безопасности |
| PSI | Pressure 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 — как стандартные утилиты используют для повышения привилегий
🤝 Как помочь проекту
Нашёл ошибку или знаешь полезную команду?
- Сделай Fork репозитория
- Добавь или исправь команду (коротко, с понятным описанием)
- Открой 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