Skip to the content.

Вернуться к главной странице, списку всех тем

1. Linux, Bash-скрипты и текстовые редакторы

Что ты узнаешь: как устроен сервер, на котором работают программы, как отдавать ему команды через терминал, как запускать программу в фоне и как автоматизировать рутину bash-скриптом

Что нужно знать заранее: ничего — это первая тема курса

Сколько времени займёт: 5 часов видео + 6–8 часов практики

Твой шаг в сквозном проекте: запустишь сервис «Заметки» на своей машине и сделаешь так, чтобы он поднимался сам после перезагрузки


Зачем всё это: как появляются программы и при чём тут DevOps

IT — это работа с информацией: её хранение, изменение, извлечение пользы или распространение. Помогают нам в этом программы — инструменты, которые принимают данные (вход), обрабатывают их и выдают результат (выход)

Вот несколько примеров программ:

По своей сути все сайты, банки, игры — это набор таких маленьких приложений, каждое из которых делает свою функцию. Тебе не нужно держать в голове всю картину их взаимодействия сразу

Программы появляются в результате этапов:

  1. Анализ требований — бизнес объясняет, какая ему нужна программа, сайт или сервис
  2. Проектирование — архитектор продумывает, как всё будет работать
  3. Написание кода — разработчики создают программы
  4. Тестирование — тестировщики (их ещё называют QA) проверяют, что все программы работают вместе как нужно
  5. Внедрение и поддержка — инженеры мониторинга смотрят, чтобы программы не ломались, инженеры SRE чинят программы в случае поломки

DevOps автоматизирует этапы с 3-го по 5-й, что ускоряет и упрощает создание и поддержку программ. Кроме того, DevOps улучшает взаимодействие между теми, кто проектирует, пишет код и тестирует

Где ты будешь в этой картине. Твоя работа начинается там, где код разработчика должен превратиться в работающий сервис: собрать, упаковать, выкатить, следить, чинить. Весь курс — это девять слоёв над одной и той же маленькой программой, и первый слой мы кладём прямо сейчас

Сквозной проект курса: сервис «Заметки»

Чтобы теория не осталась теорией, через весь курс мы ведём одно приложение — простой веб-сервис «Заметки» (notes). Он отдаёт по HTTP список заметок из файла. Программа намеренно крошечная: интерес не в ней, а в том, что мы вокруг неё построим

Что произойдёт с «Заметками» по темам курса:

Тема Что добавляем
1. Linux Запускаем на своей машине, оформляем как systemd-сервис
2. Сеть Ставим спереди nginx, включаем HTTPS, разбираем путь запроса
3. Git Кладём код в репозиторий, настраиваем автоматическую проверку
4. Docker Упаковываем в контейнер, поднимаем вместе с базой через Compose
5. Kubernetes Запускаем в трёх копиях, переживаем падение одной из них
6. Облака Выносим на арендованный сервер в интернете
7. Ansible/Terraform Описываем инфраструктуру кодом, разворачиваем с нуля одной командой
8. Мониторинг Добавляем метрики, дашборд, алерты и SLO
9. Vault/Flux Убираем пароли из кода, деплоим автоматически из git

Заводить приложение будем в задании 8 этой темы

Подготовка места для запуска программ, Linux

Сервера, на которых мы будем запускать программы, работают на ядре Linux. Это специальная программа, которую устанавливают на сервер в первую очередь. Она помогает нашим программам общаться с «железками» компьютера при помощи драйверов (программа, в которой описано, как общаться с тем или иным устройством). Например, ядро объясняет нашей программе, как записать данные на диск или вывести картинку на экран

Основные «железные» ресурсы сервера, с которыми работают наши программы:

Эти три ресурса будут преследовать тебя весь курс: контейнеру мы будем ставить лимит по CPU и памяти, Kubernetes будет решать, на какой сервер поместится приложение, а мониторинг — кричать, что память кончается

Ядро, системные вызовы и процессы

Программа не умеет сама писать на диск или отправлять данные в сеть — «железо» ей недоступно напрямую. Вместо этого она просит ядро: «открой файл», «прочитай из него», «отправь эти байты в сеть». Такая просьба называется системный вызов (syscall)

Запущенная программа называется процессом. У каждого процесса есть:

Посмотреть процессы можно командой ps aux (список) или top / htop (живая картина, обновляется каждую секунду)

Файловая система: всё есть файл

В Linux нет дисков C: и D:. Есть одно дерево, которое начинается с корня — /. Всё остальное растёт из него

Основные каталоги, которые встретятся тебе в работе:

Каталог Что в нём
/etc Конфигурационные файлы всех программ
/var/log Логи — записи о том, что программы делали
/home/имя Домашний каталог пользователя, сокращённо ~
/usr/bin, /usr/local/bin Исполняемые файлы программ
/tmp Временные файлы, очищаются при перезагрузке
/proc Не настоящие файлы, а окно в состояние ядра и процессов
/opt Софт, установленный вручную, не через пакетный менеджер

/proc — особый случай, о нём часто спрашивают на собеседовании. Этих файлов нет на диске: ядро придумывает их содержимое в момент, когда ты пытаешься прочитать. Например, cat /proc/cpuinfo покажет процессор, а cat /proc/1/status — состояние процесса с PID 1

Путь бывает абсолютный (/var/log/syslog — от корня, всегда однозначен) и относительный (log/syslog — от каталога, в котором ты сейчас). . означает текущий каталог, .. — на уровень выше

Пользователи, права и sudo

У каждого файла есть владелец и права: кто может читать (r), писать (w) и запускать (x). Посмотреть их — ls -l:

-rwxr-xr-- 1 eugene devops 512 Aug  1 10:00 run.sh
 │└┬┘└┬┘└┬┘   └──┬─┘ └──┬─┘
 │ │  │  │       │      └── группа
 │ │  │  │       └───────── владелец
 │ │  │  └───────────────── права для всех остальных: только чтение
 │ │  └──────────────────── права для группы: чтение и запуск
 │ └─────────────────────── права для владельца: чтение, запись, запуск
 └───────────────────────── тип: «-» файл, «d» каталог, «l» ссылка

Права удобно задавать числом: чтение = 4, запись = 2, запуск = 1. Складываем и получаем цифру для каждой из трёх групп. chmod 750 run.sh — владельцу всё (4+2+1), группе чтение и запуск (4+1), остальным ничего

root — пользователь с неограниченными правами. Работать под ним постоянно опасно: одна опечатка в команде удаления — и сервера нет. Поэтому обычно работают под своим пользователем, а когда нужны права root, пишут sudo перед командой. Кому что разрешено делать через sudo, описано в файле /etc/sudoers, который правят только командой visudo (она проверяет синтаксис — ошибка в этом файле может отрезать тебе доступ)

Сигналы: как правильно останавливать программы

Чтобы попросить процесс завершиться, ему посылают сигнал:

Сигнал Номер Что означает
SIGTERM 15 «Пожалуйста, завершись» — программа успевает дописать файлы и закрыть соединения. Это поведение kill по умолчанию
SIGINT 2 То же, что нажать Ctrl+C в терминале
SIGHUP 1 Часто используется как «перечитай конфиг, не перезапускаясь»
SIGKILL 9 Убить немедленно. Процесс не может его перехватить и ничего не успевает сохранить

Правило: сначала SIGTERM, и только если через 10–30 секунд процесс не умер — SIGKILL. Привычка сразу писать kill -9 приводит к битым данным. Ровно эта же логика позже встретится в Docker (docker stop шлёт SIGTERM, потом SIGKILL) и в Kubernetes (terminationGracePeriodSeconds)

systemd: как программы работают в фоне

Если запустить программу в терминале и закрыть терминал, программа умрёт. А сервис должен работать всегда: подниматься при старте сервера, перезапускаться после падения, писать логи. Этим занимается systemd — первый процесс системы (PID 1), который запускает и присматривает за всеми остальными

Описание одной программы для systemd называется юнит и лежит в файле /etc/systemd/system/имя.service. Основные команды:

systemctl start notes      # запустить
systemctl stop notes       # остановить
systemctl restart notes    # перезапустить
systemctl status notes     # посмотреть состояние: работает ли, когда упал, последние строки логов
systemctl enable notes     # включать автоматически при загрузке сервера
journalctl -u notes -f     # смотреть логи сервиса в реальном времени

Разница между start и enable — частая путаница: start запускает сейчас, enable включает автозапуск после перезагрузки. Обычно нужны обе

Сокеты и порты

Сокет — «розетка», через которую два процесса обмениваются данными. Сокеты бывают сетевые (общение по сети, адресуются парой IP-адрес + порт) и локальные, файловые (общение процессов на одной машине, выглядят как файл, например /var/run/docker.sock)

Порт — номер от 1 до 65535, который отличает одну программу на сервере от другой. Веб-сервер обычно слушает 80 (HTTP) и 443 (HTTPS), база PostgreSQL — 5432, наш сервис «Заметки» будет слушать 8080. Посмотреть, кто какой порт занял: ss -tulpn

Текстовые редакторы и форматы конфигов

Почти вся работа DevOps — это правка текстовых файлов. Редакторы, которые нужно знать:

Форматы, в которых пишут конфигурацию:

JSON — машиночитаемый, строгий, без комментариев. На нём общаются программы между собой:

{
  "service": "notes",
  "port": 8080,
  "replicas": 3
}

YAML — то же самое, но для людей: вложенность задаётся отступами, есть комментарии. На нём написаны Docker Compose, Kubernetes, Ansible, GitLab CI — то есть почти весь остаток курса:

service: notes   # имя сервиса
port: 8080
replicas: 3

Главное правило YAML: отступы только пробелами, никаких табов, и на одном уровне вложенности одинаковое число пробелов. Это источник примерно половины ошибок новичков

Markdown — разметка для текста: # заголовок, **жирный**, - список, `код`. На нём написан этот курс и почти все README в мире

Bash-скрипты

Bash-скрипт — текстовый файл с набором команд, которые выполняются одна за другой. Он превращает «я каждый раз делаю эти шесть команд» в «я запускаю одну»

Скелет любого приличного скрипта:

#!/usr/bin/env bash
# Строка выше называется shebang: она говорит системе, чем запускать этот файл

set -euo pipefail
# -e  — прервать скрипт при первой же ошибке, а не идти дальше как ни в чём не бывало
# -u  — считать ошибкой обращение к несуществующей переменной (защита от опечаток)
# -o pipefail — считать ошибкой падение любой команды в конвейере a | b | c

NAME="${1:-мир}"          # первый аргумент скрипта, а если его нет — слово «мир»
echo "Привет, ${NAME}!"

Без set -euo pipefail скрипт, у которого не получилось скачать файл, спокойно продолжит работу и «задеплоит» пустоту. Пиши эту строку всегда

Полезные конструкции:

if [ -f /etc/hosts ]; then echo "файл есть"; fi     # проверка существования файла
if ! command -v jq >/dev/null; then echo "нет jq"; fi  # проверка, установлена ли программа
for f in *.log; do echo "нашёл ${f}"; done          # цикл по файлам
DATE="$(date '+%Y-%m-%d %H:%M:%S')"                 # результат команды в переменную

Кавычки вокруг "${NAME}" — не украшение: без них имя файла с пробелом развалится на два аргумента

Уроки для просмотра и конспектирования

  1. Уроки с 3-го по 20-й4 часа
  2. Уроки с 3-го по 5-й1 час

Начало работы в IT: готовим рабочее место

  1. Нужен ноутбук с Ubuntu. Если у тебя Windows — установи WSL и в нём Ubuntu. Если macOS — терминал есть, но часть команд отличается, поэтому лучше тоже поставить Ubuntu в виртуальной машине или WSL-аналоге
  2. Установи Visual Studio Code и запусти, посмотри, как выглядит. Эта программа нужна для редактирования конфигов и написания кода
  3. Установи браузер, которым будешь пользоваться для работы — например, Яндекс Браузер или Chrome. Пригодятся инструменты разработчика (F12), в теме 2 мы будем смотреть в них сетевые запросы
  4. Установи и пока не трогай, понадобится в темах 4 и 5: Docker Desktop и Lens
  5. Заведи привычку спрашивать у ИИ-ассистента то, что непонятно — например, у GigaChat. Хороший запрос: Объясни как ребёнку, зачем DevOps нужен Kubernetes. Плохой: копировать ответ в задание, не поняв его
  6. Зарегистрируйся на сайтах:
    • GitHub — место, где разработчики бесплатно размещают код своих программ; там же лежит этот курс
    • Habr — русскоязычный сайт со статьями по DevOps, разработке и автоматизации

Теоретические вопросы

Ответь своими словами, не подглядывая. Ответы ниже — для самопроверки

  1. Что такое ядро Linux и зачем оно нужно? Ответ: Программа, которая загружается на сервере первой и управляет «железом»: процессором, памятью, диском, сетью. Обычные программы не работают с железом напрямую — они просят об этом ядро

  2. Что такое системный вызов? Ответ: Обращение программы к ядру с просьбой сделать то, что ей самой недоступно: открыть файл, выделить память, отправить данные в сеть. Примеры: open, read, write, fork, execve

  3. Что такое sudo и как им пользоваться? Ответ: Команда, которая выполняет другую команду от имени root (администратора). Пишется перед командой: sudo apt update. Права, кому что можно, описаны в /etc/sudoers

  4. Как сделать, чтобы sudo не спрашивал пароль каждый раз? Ответ: Открыть sudo visudo и добавить строку имя_пользователя ALL=(ALL) NOPASSWD: ALL. Править только через visudo — он проверяет синтаксис. На рабочих серверах так делать не стоит, это дыра в безопасности; уместно на своей учебной машине

  5. Что такое systemd-сервис? Ответ: Описание программы, которой systemd управляет: чем её запускать, под каким пользователем, что делать при падении, когда стартовать. Лежит в файле /etc/systemd/system/имя.service

  6. Как проверить состояние systemd-сервиса? Ответ: systemctl status имя — активен ли, с каким PID, когда запущен, последние строки логов. Полные логи — journalctl -u имя

  7. Чем systemctl start отличается от systemctl enable? Ответ: start запускает сервис прямо сейчас, enable включает автозапуск при загрузке сервера. Это независимые вещи, обычно нужны обе

  8. Что такое сокет? Ответ: Точка соединения для обмена данными между процессами. Сетевой сокет адресуется парой «IP-адрес + порт», локальный (unix-сокет) выглядит как файл, например /var/run/docker.sock

  9. Какие есть kill-сигналы и чем они отличаются? Ответ: SIGTERM (15) — вежливая просьба завершиться, процесс успевает прибраться; SIGINT (2) — то же, что Ctrl+C; SIGHUP (1) — часто «перечитай конфиг»; SIGKILL (9) — убийство без предупреждения, перехватить нельзя

  10. Как правильно завершить запущенный процесс? Ответ: Найти PID (ps aux | grep имя или pgrep имя), послать kill PID (это SIGTERM), подождать. Если не умер — kill -9 PID. Для сервисов правильнее systemctl stop имя

  11. Что такое корень файловой системы? Ответ: Каталог / — начало единого дерева каталогов. В Linux нет отдельных дисков C:/D:, все накопители подключаются в какую-то точку внутри этого дерева

  12. Чем /proc отличается от остальных каталогов? Ответ: Это виртуальная файловая система: файлов в ней физически нет на диске, их содержимое ядро формирует в момент чтения. Через неё видно состояние ядра и каждого процесса

  13. Что такое load average в выводе uptime? Ответ: Среднее число процессов, которые хотят работать (выполняются или ждут диск), за 1, 5 и 15 минут. Ориентир: значение примерно равное числу ядер — полная загрузка, заметно больше — очередь, система не справляется

  14. В чём разница между JSON и YAML? Ответ: Одни и те же данные. JSON строгий, без комментариев, удобен машинам. YAML читаемее для человека, вложенность задаётся отступами, комментарии есть. Конфиги DevOps-инструментов почти всегда YAML

  15. Почему в YAML нельзя использовать табы? Ответ: Спецификация запрещает табы для отступов, парсер их не примет. Вложенность строится только пробелами, и на одном уровне их должно быть одинаковое количество

  16. Что делает set -euo pipefail в начале скрипта? Ответ: -e прерывает скрипт на первой ошибке, -u ругается на необъявленные переменные, -o pipefail замечает падение команды внутри конвейера. Без этого скрипт продолжает работать после ошибки и делает не то, что задумано

  17. Что такое shebang? Ответ: Первая строка скрипта вида #!/usr/bin/env bash. Указывает, какой программой запускать файл. Без неё скрипт можно запустить только явно: bash script.sh

  18. Как сделать файл исполняемым и почему ./script.sh, а не script.sh? Ответ: chmod +x script.sh. Точка со слешем означает «файл в текущем каталоге»; без неё оболочка ищет команду только в каталогах из переменной PATH, а текущего каталога там нет — из соображений безопасности

  19. Что такое cron? Ответ: Планировщик: запускает команды по расписанию. Расписание задаётся пятью полями — минута, час, день месяца, месяц, день недели. * * * * * — каждую минуту, 0 3 * * * — каждый день в 03:00

  20. Что такое SSH и зачем нужны клиент и сервер? Ответ: Протокол защищённого удалённого доступа к серверу. На сервере работает sshd (принимает подключения), на твоём ноутбуке — клиент ssh (подключается). Весь трафик шифруется, вход обычно по ключу, а не по паролю

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

Это то, что реально спрашивают на собеседованиях сверх основного списка выше

  1. Какие основные поля есть в конфигурации systemd-юнита? Ответ: Три секции. [Unit]: Description, After (после чего запускать), Requires. [Service]: ExecStart (чем запускать), User, WorkingDirectory, Environment, Restart, RestartSec, Type (simple по умолчанию, forking для процессов, уходящих в фон). [Install]: WantedBy — на каком этапе загрузки включать

  2. Как посмотреть версию ядра Linux? Ответ: uname -r — только версия, uname -a — вся информация о системе. Дистрибутив — lsb_release -a или cat /etc/os-release

  3. Как передать права на файл или каталог другому пользователю? Ответ: chown пользователь:группа файл, рекурсивно — chown -R. Только группу меняет chgrp. Права доступа при этом не меняются, за них отвечает chmod

  4. Как посмотреть список уже запланированных задач cron? Ответ: crontab -l — задачи текущего пользователя, sudo crontab -l -u имя — конкретного пользователя. Системные задачи лежат в /etc/crontab и каталогах /etc/cron.d/, /etc/cron.daily/

  5. Что нужно, чтобы подключиться к серверу по SSH? Ответ: Адрес сервера, имя пользователя и способ аутентификации — ключ или пароль. При входе по ключу открытая часть должна лежать на сервере в ~/.ssh/authorized_keys, закрытая — у тебя в ~/.ssh/id_ed25519 с правами 600

  6. Как проверить, запущен ли SSH-сервер, и где его конфигурация? Ответ: systemctl status ssh (в некоторых системах sshd) либо ss -tulpn | grep :22. Конфигурация сервера — /etc/ssh/sshd_config, конфигурация клиента — /etc/ssh/ssh_config и ~/.ssh/config. После правки нужен systemctl reload ssh

  7. Где хранятся SSH-ключи текущего пользователя? Ответ: В каталоге ~/.ssh/. Закрытый ключ — id_ed25519 (или id_rsa), открытый — с расширением .pub. Права на каталог должны быть 700, на закрытый ключ 600, иначе SSH откажется его использовать

  8. Как посмотреть информацию о команде или программе? Ответ: man команда — полное руководство, команда --help — краткая справка, apt show пакет — сведения о пакете, which команда — путь к исполняемому файлу, type команда — чем она является: файлом, встроенной командой или псевдонимом

  9. Как заменить одно слово на другое в файле? Ответ: sed -i 's/старое/новое/g' файл. Здесь -i правит файл на месте, g заменяет все вхождения в строке, а не только первое. Перед правкой важного файла делают резервную копию: sed -i.bak

  10. Что такое файловый дескриптор? Ответ: Число, которым процесс обозначает открытый файл, сокет или канал. Три всегда открыты: 0 — стандартный ввод, 1 — стандартный вывод, 2 — поток ошибок. Отсюда привычные конструкции: 2>/dev/null (спрятать ошибки), 2>&1 (объединить ошибки с обычным выводом). Список открытых процессом дескрипторов — ls -l /proc/PID/fd/

  11. Чем > отличается от >>? Ответ: > перезаписывает файл с нуля, >> дописывает в конец. Одна из самых дорогих опечаток новичка: > вместо >> в скрипте, который ведёт журнал, стирает всю историю при каждом запуске

  12. Что такое inode и чем жёсткая ссылка отличается от символической? Ответ: Inode — структура с метаданными файла: права, владелец, размер, расположение данных на диске. Имя файла — лишь запись в каталоге, указывающая на inode. Жёсткая ссылка (ln) — ещё одно имя того же inode: файл исчезнет, только когда удалят последнее имя; работает лишь в пределах одной файловой системы и не применяется к каталогам. Символическая (ln -s) — отдельный маленький файл с путём внутри: может указывать куда угодно, но «повисает», если цель переместили

  13. Диск заполнен, но крупных файлов du не находит. В чём дело? Ответ: Два типичных случая. Первый: файл удалили, но его держит открытым работающий процесс — место освободится только после его перезапуска, найти виновника можно через lsof +L1. Второй: кончились не байты, а inode — так бывает при миллионах крошечных файлов; проверяется командой df -i

  14. Что означают коды возврата 0, 1, 127, 137 и 143? Ответ: 0 — успех, 1 — общая ошибка, 126 — файл найден, но не исполняемый, 127 — команда не найдена. Коды больше 128 означают завершение по сигналу: 128 + номер сигнала. Отсюда 130 — прервали через Ctrl+C (SIGINT), 143 — корректная остановка (SIGTERM), 137 — убит SIGKILL, чаще всего это нехватка памяти. Код 137 у контейнера в теме 4 читается именно так

  15. Что такое OOM killer? Ответ: Механизм ядра: когда память кончилась, оно выбирает процесс с наибольшей «оценкой» и убивает его, чтобы спасти систему. Следы ищут в dmesg или journalctl -k по слову Out of memory. Коварство в том, что жертвой становится не обязательно виновник — обычно это самый прожорливый процесс, а им часто оказывается база данных

  16. Что такое ulimit и когда о нём вспоминают? Ответ: Ограничения на процесс: число открытых файлов, процессов, размер стека. Вспоминают при ошибке Too many open files — по умолчанию лимит дескрипторов часто мал для нагруженного сервера. Смотрят ulimit -n, меняют в /etc/security/limits.conf, а для сервисов — директивой LimitNOFILE в systemd-юните

  17. Что такое umask? Ответ: Маска, которая убирает права у создаваемых файлов. При umask 022 новые файлы получают 644, каталоги — 755: маска вычитается из 666 и 777 соответственно. Это объясняет, почему созданный файл не является исполняемым сам по себе

  18. Что делают биты setuid и sticky? Ответ: setuid заставляет программу работать с правами владельца файла, а не запустившего — так passwd меняет системный файл паролей от имени обычного пользователя. Sticky-бит на каталоге (как у /tmp) разрешает удалять файлы только их владельцу, иначе любой стёр бы чужие

  19. Как посмотреть логи сервиса и не дать им забить диск? Ответ: journalctl -u имя — логи сервиса, -f следить, --since "1 hour ago" за период, -p err только ошибки, -k сообщения ядра. Размер журнала — journalctl --disk-usage, очистка — journalctl --vacuum-time=7d. Для обычных файлов в /var/log за ротацию отвечает logrotate с настройками в /etc/logrotate.d/

  20. Как найти все файлы больше 100 МБ, изменённые за последнюю неделю? Ответ: find /var -type f -size +100M -mtime -7. Добавив -exec ls -lh {} \; или | xargs ls -lh, получим подробности. xargs нужен, потому что многие команды читают аргументы, а не стандартный ввод; для имён с пробелами безопасна связка find ... -print0 | xargs -0

  21. Что произойдёт, если ошибиться в /etc/fstab? Ответ: Файл описывает, что монтировать при загрузке. Ошибка в нём способна оставить сервер в аварийном режиме без сети — а это в облаке означает поход в консоль восстановления. Поэтому после правки проверяют mount -a до перезагрузки, а необязательным разделам добавляют опцию nofail

  22. Чем nohup и tmux отличаются от systemd-сервиса? Ответ: nohup и tmux позволяют процессу пережить закрытие терминала — это удобно для разовой долгой команды. Но они не поднимут программу после перезагрузки сервера и не перезапустят её после падения. Всё, что должно работать постоянно, оформляют systemd-юнитом

Практическая часть

Задания идут по нарастанию. Для каждого записывай результат: скриншот или скопированный вывод команды — это твой конспект и отчёт

Задание 1. Навигация по файловой системе

Цель: свободно перемещаться по дереву каталогов и понимать, где находишься

Шаги:

pwd                 # показать полный путь к текущему каталогу
cd /tmp             # перейти в /tmp
pwd
cd -                # вернуться в предыдущий каталог
cd ~                # перейти в домашний каталог пользователя
cd ..               # подняться на уровень выше
cd /                # перейти в корень
ls -la              # посмотреть содержимое, включая скрытые файлы

Ожидаемый вывод: после cd ~ команда pwd печатает /home/твоё_имя; после cd / — просто /

Ответь письменно: куда именно ведёт cd ~? Какие основные каталоги ты видишь в корне и за что отвечает каждый?

Типичные ошибки:

Задание 2. Файлы и каталоги

Цель: создавать, перемещать и удалять — без этого дальше никуда

Шаги:

cd ~
touch config binary          # создать два пустых файла
mkdir app                    # создать каталог
mv config binary app/        # переместить оба файла в каталог
ls -l app/
mkdir -p app/temp/info/users # создать вложенные каталоги одной командой
ls -R app                    # посмотреть дерево целиком
cd ~
rm -r app                    # удалить каталог со всем содержимым

Ожидаемый вывод: ls -R app показывает binary, config и цепочку temp/info/users

Типичные ошибки:

Задание 3. Ресурсы сервера

Цель: уметь за минуту ответить на вопрос «что с сервером»

Шаги:

top          # живая картина процессов, выход — клавиша q
htop         # то же, но нагляднее (устанавливается отдельно)
free -h      # сколько оперативной памяти занято и свободно
df -h /      # сколько места на диске в корневом разделе
du -sh ~/*   # что именно занимает место в домашнем каталоге
uptime       # сколько работает сервер и load average
ss -tulpn    # какие порты слушаются и какими процессами

Ответь письменно: что означают колонки %CPU, %MEM, RES в top? Что такое load average и когда его значение считается плохим?

Типичные ошибки:

Задание 4. Установка программ

Цель: пользоваться пакетным менеджером apt

Шаги:

sudo apt update                                  # обновить список доступных пакетов
sudo apt upgrade -y                              # обновить установленные программы
sudo apt install -y git htop curl nano jq        # установить нужные нам программы

Проверь каждую:

git --version
htop --version
curl --version
nano --version
jq --version
curl -s https://api.github.com/repos/kubernetes/kubernetes | jq .stargazers_count

Ожидаемый вывод: последняя команда скачивает данные из интернета в формате JSON и печатает одно число — количество звёзд у репозитория Kubernetes. Так связка curl + jq используется в реальной работе постоянно

Типичные ошибки:

Задание 5. Первый bash-скрипт

Цель: написать скрипт, который проверяет и доустанавливает нужные программы

Шаги: создай файл ~/bin/setup.sh:

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

# Программы, без которых нам дальше не обойтись
PACKAGES=(curl git jq)

for pkg in "${PACKAGES[@]}"; do
  # command -v ищет программу в PATH; вывод отправляем в никуда, нас интересует только код возврата
  if command -v "${pkg}" >/dev/null 2>&1; then
    echo "✓ ${pkg} уже установлен"
  else
    echo "→ ставлю ${pkg}"
    sudo apt install -y "${pkg}"
  fi
done

echo "Готово"

Сделай исполняемым только для себя и запусти:

mkdir -p ~/bin
chmod 700 ~/bin/setup.sh    # 7 владельцу (rwx), 0 группе, 0 остальным
~/bin/setup.sh
ls -l ~/bin/setup.sh        # убедись, что права выглядят как -rwx------

Ожидаемый вывод: три строки с галочками (программы уже стоят после задания 4) и Готово

Типичные ошибки:

Задание 6. Запуск по расписанию через cron

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

Шаги: создай ~/bin/timestamp.sh:

#!/usr/bin/env bash
set -euo pipefail
date '+%Y-%m-%d %H:%M:%S' >> "${HOME}/current_time.txt"
chmod +x ~/bin/timestamp.sh
crontab -e                  # откроется редактор списка задач

Добавь строку (подставь своё имя пользователя):

* * * * * /home/твоё_имя/bin/timestamp.sh

Подожди три минуты и проверь:

cat ~/current_time.txt

Ожидаемый вывод: файл растёт на одну строку в минуту

Типичные ошибки:

Задание 7. Изучаем фоновые сервисы

Цель: понять, как в системе живут фоновые процессы

Шаги:

systemctl list-units --type=service          # список всех сервисов
systemctl status ssh                         # состояние конкретного (может называться sshd)
sudo apt install -y openssh-server           # установить SSH-сервер
sudo systemctl restart ssh
sudo systemctl enable ssh
ss -tulpn | grep :22                         # убедиться, что порт 22 слушается
journalctl -u ssh -n 20                      # последние 20 строк логов сервиса

Ответь письменно: выбери любой сервис из списка и разберись, что он делает. Что такое SSH, какую роль играют клиент и сервер?

Типичные ошибки:

Задание 8. Сквозной проект: запускаем сервис «Заметки»

Цель: запустить первую версию приложения, которое мы будем вести через весь курс, и заставить его подниматься автоматически

Шаги:

  1. Создай каталог проекта и файл приложения ~/notes/app.py:

    #!/usr/bin/env python3
    """Сервис «Заметки» — сквозной проект курса DevOps."""
    import os
    from http.server import BaseHTTPRequestHandler, HTTPServer
    
    # Настройки берём из переменных окружения — так принято у всех сервисов,
    # это позволит потом менять их не трогая код (пригодится в темах 4, 5 и 9)
    NOTES_FILE = os.environ.get("NOTES_FILE", "/home/notes/notes.txt")
    PORT = int(os.environ.get("PORT", "8080"))
    
    
    class Handler(BaseHTTPRequestHandler):
        def do_GET(self):
            if self.path == "/healthz":
                # Эндпоинт проверки здоровья: по нему Docker и Kubernetes
                # будут понимать, живо ли приложение
                self.respond(200, "ok\n")
            elif self.path == "/":
                self.respond(200, self.read_notes())
            else:
                self.respond(404, "Такой страницы нет\n")
    
        def read_notes(self):
            if not os.path.exists(NOTES_FILE):
                return "Заметок пока нет\n"
            with open(NOTES_FILE, encoding="utf-8") as f:
                return f.read()
    
        def respond(self, code, body):
            data = body.encode("utf-8")
            self.send_response(code)
            self.send_header("Content-Type", "text/plain; charset=utf-8")
            self.send_header("Content-Length", str(len(data)))
            self.end_headers()
            self.wfile.write(data)
    
        def log_message(self, fmt, *args):
            # flush=True — чтобы логи появлялись сразу, а не копились в буфере.
            # Без этого в контейнере (тема 4) логи будут «пропадать»
            print(f"{self.address_string()} {fmt % args}", flush=True)
    
    
    if __name__ == "__main__":
        print(f"«Заметки» слушают порт {PORT}", flush=True)
        HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
    
  2. Проверь вручную:

    mkdir -p ~/notes
    cd ~/notes
    echo "Первая заметка: выучить Linux" > notes.txt
    NOTES_FILE=~/notes/notes.txt python3 app.py
    

    В другом терминале:

    curl http://localhost:8080/
    curl http://localhost:8080/healthz
    curl -i http://localhost:8080/такой-страницы-нет
    

    Останови приложение через Ctrl+C — это тот самый SIGINT

  3. Оформи как systemd-сервис. Создай /etc/systemd/system/notes.service:

    [Unit]
    Description=Сервис «Заметки»
    After=network.target
    
    [Service]
    # Под каким пользователем работать — не под root, у сервиса должно быть минимум прав
    User=твоё_имя
    WorkingDirectory=/home/твоё_имя/notes
    Environment=NOTES_FILE=/home/твоё_имя/notes/notes.txt
    Environment=PORT=8080
    ExecStart=/usr/bin/python3 /home/твоё_имя/notes/app.py
    # Поднимать заново, если процесс упал
    Restart=always
    RestartSec=3
    
    [Install]
    WantedBy=multi-user.target
    
  4. Запусти и проверь:

    sudo systemctl daemon-reload      # перечитать файлы юнитов после изменения
    sudo systemctl enable --now notes # включить автозапуск и запустить сейчас
    systemctl status notes
    curl http://localhost:8080/
    journalctl -u notes -f            # логи в реальном времени, выход Ctrl+C
    
  5. Проверь самовосстановление — убей процесс и убедись, что systemd поднял его заново:

    pgrep -f app.py                   # узнать PID
    sudo kill $(pgrep -f app.py)      # послать SIGTERM
    sleep 5
    systemctl status notes            # должен снова быть active (running), но с новым PID
    

Ожидаемый вывод: curl http://localhost:8080/ печатает текст заметки; systemctl status notes показывает active (running); после kill сервис возвращается сам

Типичные ошибки:

Оставь всё запущенным — в теме 2 мы поставим перед этим сервисом nginx и включим HTTPS

Проверь себя: тема освоена, если ты можешь

Следующая тема: сеть, Nginx, TLS, HTTP, DNS →