Пара 9 / ноябрь
systemd, граф запуска и журналы Запустить пользовательскую службу, проверить её статус и найти причину сбоя в journal.
Запустить пользовательскую службу, проверить её статус и найти причину сбоя в journal. systemd управляет службами через unit-файлы. ExecStart задаёт команду, WorkingDirectory — рабочую папку, Environment — настройки. Для курса используем пользовательскую службу: она не требует редактирования системных unit-файлов. absolute path интерпретатора надёжнее зависимости от активированного venv. systemctl --user daemon-reload перечитывает описание, start запускает, status показывает состояние. enable настраивает запуск согласно unit, но сам по себе не стартует без --now. Пользовательская служба зависит от пользовательского менеджера; не обещаем работу после выключения ноутбука или завершения WSL.
Контекст kernel journal, journal службы и файл приложения — разные потоки.
Запустить пользовательскую службу, проверить её статус и найти причину сбоя в journal.
Dmesg читает сообщения ring buffer ядра, доступ может ограничиваться политикой системы. Journald собирает записи с metadata, включая службу, PID, boot и время; journalctl умеет фильтрацию по этим признакам. Journal хранится в бинарном формате: его не читают cat как текст. /run/log/journal предназначен для временного хранения; /var/log/journal используется для постоянного согласно Storage и конфигурации. Текстовые /var/log/syslog и /var/log/auth.log существуют при соответствующей syslog-конфигурации, а не обязаны присутствовать в каждой Ubuntu/container. Приложение может писать свой файл или stdout; Docker logs показывает stdout/stderr контейнера, но не любой файл внутри него. Ротация и retention ограничивают размер и срок хранения. Для расследования сохраняют контекст времени, версии и request_id, не раскрывая секреты. Смена timezone или неверные часы усложняет сопоставление.
Менеджер служб Запуск, остановка и журнал должны иметь одного понятного владельца.
01 Unit-файл
→ 02 systemd --user
→ 03 Процесс
→ 04 Журнал
Аналогия: заведующий сменой знает, кого запустить и где искать отчёт.
systemd управляет службами через unit-файлы. ExecStart задаёт команду, WorkingDirectory — рабочую папку, Environment — настройки. Для курса используем пользовательскую службу: она не требует редактирования системных unit-файлов. absolute path интерпретатора надёжнее зависимости от активированного venv. systemctl --user daemon-reload перечитывает описание, start запускает, status показывает состояние. enable настраивает запуск согласно unit, но сам по себе не стартует без --now. Пользовательская служба зависит от пользовательского менеджера; не обещаем работу после выключения ноутбука или завершения WSL.
Работает и готов — разные состояния active не заменяет запрос к /healthz.
01 Запущен
→ 02 Слушает порт
→ 03 Готов
→ 04 Ответ проверен
Аналогия: сотрудник пришёл на смену, но касса ещё не открыта.
Процесс может существовать и не принимать запросы: ещё загружает модель, слушает другой порт или застрял. После systemctl status проверяем curl и ss. Restart=on-failure помогает после аварийного выхода, но не устраняет причину. Неправильная конфигурация может вызвать цикл рестартов; нужны пауза и ограничение попыток. На демонстрации ошибочный MODEL_PATH вызывает ранний отказ. Рестарт — инструмент восстановления, а журнал помогает понять, почему он понадобился. Не оцениваем сдачу только скриншотом active (running).
journalctl: временная линия Причину ищем рядом с моментом отказа.
01 Время
→ 02 Служба
→ 03 Событие
→ 04 Причина / действие
Аналогия: бортовой журнал объясняет последовательность, а не только итог.
journalctl --user -u studypulse выводит записи конкретной службы. -n ограничивает количество, -f показывает новые события. Полезны время, имя службы, сообщение об ошибке и код завершения. Наше приложение пишет структурированные JSON-строки в stdout: их собирает менеджер процессов. Не сохраняем содержимое чувствительных запросов в лог. Перед исправлением запишите точное наблюдение: не «не работает», а «служба завершилась, MODEL_PATH не найден». В WSL сначала проверьте, используется ли systemd; отсутствие менеджера — ограничение среды, а не ошибка приложения.
Что делает systemd и что остаётся ядру systemd организует пользовательские службы, ядро управляет ресурсами.
systemd — пользовательский менеджер, ядро продолжает управлять CPU и памятью systemd · PID 1 Запускает и наблюдает units sshd.service Процесс и его потомки studypulse.service Процесс и его потомки user@UID.service Менеджер пользователя cgroups помогают учитывать группу процессов; PID 1 не является ядром Linux. Планировщик ядра. systemd задаёт организацию служб и может использовать ограничения ресурсов.
В Ubuntu systemd обычно является PID 1 системы: он запускает и наблюдает объекты пользовательской среды, собирает завершения процессов и организует остановку. Он не заменяет ядро и не планирует инструкции на CPU вместо Linux. Ядро предоставляет процессы, сигналы, файловые системы и cgroups; менеджер использует эти механизмы. Через cgroups можно учитывать не только один MainPID, но и потомков службы. Отдельный systemd --user управляет units конкретного пользователя. PID 1 имеет особую роль, поэтому не демонстрируем на нём kill. На схеме показаны связи управления, а не обещание, что каждый рабочий процесс навсегда остаётся прямым ребёнком PID 1: приложения могут создавать потомков и промежуточные процессы. Сервис запускать через менеджер удобнее, когда нужны наблюдение, журнал, политика остановки и воспроизводимая конфигурация.
Аналогия: диспетчер организует смены, инженерная система здания обеспечивает ресурсы. Менеджер не является электрической сетью.
Планировщик ядра. systemd задаёт организацию служб и может использовать ограничения ресурсов.
Unit — объект управления; service — процессная работа target группирует, timer активирует, mount подключает файловую систему.
Unit описывает объект, service — только один тип unit multi-user.target Группирует units Wants studypulse.service ExecStart запускает процесс journal stdout / stderr backup.timer Наступило время активация backup.service Однократная задача data.mount Монтирование FS Другие типы: socket, path, device, slice, scope. Target сам не обязан иметь процесс. Нет. Это группирующий объект менеджера, а не обязательный процесс.
Unit — общий формат описания управляемого объекта. Service задаёт способ запуска и наблюдения процесса или задачи, target объединяет units в логическую группу, timer планирует активацию, mount представляет монтирование. Есть также socket, path, device, slice и scope. Target не является отдельной программой, которая должна висеть в ps. Журнал — отдельная инфраструктура: stdout и stderr службы могут поступать в journal согласно её настройкам. В нашем сервисе оставляем процесс в foreground: менеджеру не нужен самодельный фон через &. Секция [Unit] содержит общие связи, [Service] — параметры выполнения, [Install] — инструкции создания связей при enable. Показать эти три секции полезнее, чем просить запомнить десятки директив без их роли.
Аналогия: расписание включает отделы, дежурства и события, но не каждое поле расписания — отдельный работник.
Нет. Это группирующий объект менеджера, а не обязательный процесс.
Requires и After отвечают на разные вопросы Нужен ли другой unit — и в каком порядке выполнять задания.
Зависимость запуска и порядок запуска — разные рёбра api.service Requires=db.service активация db db.service Запросить запуск db вместе с api db.service Сначала завершается start job After=db.service api.service Затем выполняется start job api After не запускает db. Requires без After не задаёт последовательность. Нет. Ordering ограничивает порядок присутствующих заданий; активация задаётся отдельно.
Requires=db.service включает db в транзакцию активации; After=db.service задаёт порядок, если оба unit участвуют. After сам по себе не запускает db. Requires без ordering не требует сначала закончить запуск db, поэтому обе службы могут стартовать параллельно. Для учебного обязательного подготовительного шага используем Requires вместе с After. Если подготовительный unit не сможет активироваться, упорядоченная зависимая служба не стартует; однако автоматическое обнаружение последующего «зависания» внешней БД этими директивами не обеспечивается. Wants слабее: запросить другую службу, но не делать её неуспешный запуск достаточной причиной провала своего старта. Реальное поведение также зависит от типа службы и условий; не превращаем две строки в обещание полной health-оркестрации. На доске рисуем разные цвета для включения в граф и для порядка.
Аналогия: «есть только после приготовления» не означает, что кто-то уже поручил повару приготовить.
Нет. Ordering ограничивает порядок присутствующих заданий; активация задаётся отдельно.
Загрузка — граф, а не один длинный shell-скрипт Независимые работы можно выполнять одновременно.
systemd исполняет граф заданий; независимые ветви могут идти параллельно basic.target Базовое окружение network.service Своя ветвь local-worker.service Без сетевой зависимости multi-user.target Группа нужных units Граф учебный: реальный состав и ordering смотрим systemctl и systemd-analyze. Нет. Нужны зависимости и критический путь, а работа могла выполняться параллельно.
При запросе target менеджер собирает транзакцию заданий из зависимостей. Ordering задаёт допустимый порядок; независимые ветви могут выполняться параллельно. Поэтому полезно различать общую длительность запуска и критическую цепочку. systemd-analyze critical-chain показывает цепь задержек согласно данным менеджера, blame ранжирует длительности активации units, но не является автоматическим доказательством причины общей медленной загрузки. Служба может стартовать долго параллельно и не задерживать интересующий target. Граф на слайде намеренно учебный: состав реальных targets зависит от дистрибутива, режима и настроек. Уточняйте systemctl list-dependencies и эффективные unit-файлы вместо заучивания универсальной последовательности. Для WSL результаты не равны времени холодной загрузки физического ноутбука.
Аналогия: ремонт кухни и уборка кабинета идут одновременно; общий срок зависит от необходимых зависимостей, а не суммы всех работ.
Нет. Нужны зависимости и критический путь, а работа могла выполняться параллельно.
active ещё не значит «готов отвечать» Событие старта зависит от Type; готовность проверяется по контракту.
Запуск процесса ещё не доказывает готовность API Создан процесс Type=simple: fork exec выполнен Type=exec: программа запущена Инициализация Файлы, порт, подключения READY=1 Type=notify + sd_notify GET /healthz Проверка конкретного контракта Реальный запрос Проверка пути пользователя active, READY и HTTP 200 — разные доказательства. Type=notify требует поддержки приложением. Нет. Это свидетельство состояния менеджера; нужен запрос, который проверяет выбранный контракт.
Для Type=simple менеджер считает службу запущенной после создания основного процесса, до подтверждения успешного exec. Type=exec ждёт успешного выполнения exec, поэтому лучше обнаруживает ошибки запуска исполняемого файла. Ни один из этих типов не доказывает, что приложение закончило инициализацию и открыло порт. Type=notify ждёт уведомления READY=1 от поддерживающего это протокол приложения; нельзя просто поменять Type на notify у произвольного Python и ожидать успеха. Даже готовность менеджера не гарантирует правильный ответ на пользовательский запрос. В лабораторной используем статус, журнал, затем curl /healthz и реальный запрос /predict. Аналогично network-online.target зависит от настроенного wait-online механизма и не обещает бесконечную доступность внешнего API или Интернет-соединения.
Аналогия: работник пришёл, инструмент запущен и заказ успешно выполнен — три разные проверки.
Нет. Это свидетельство состояния менеджера; нужен запрос, который проверяет выбранный контракт.
start и enable не взаимозаменяемы Сейчас работать и участвовать в будущей активации — разные свойства.
start меняет текущее состояние, enable меняет связи будущей активации systemctl start demo Запустить сейчас Процесс сейчас работает Без enable после следующей загрузки может не стартовать systemctl enable demo Создать связи из [Install] target.wants → demo.service Без --now текущее состояние может не измениться enable --now сочетает операции; disabled-службу всё ещё может активировать зависимость. Нет. Без --now установка связей не равна немедленному start; смотрим статус и журнал.
Start запросит запуск unit сейчас. Enable использует [Install], чтобы создать необходимые связи, например target.wants/demo.service. Без --now enable не обязан запустить процесс немедленно, а start без enable не обеспечивает автоматический запуск после следующей обычной загрузки. Enable --now совмещает действия. Disabled не означает «невозможно запустить»: unit может быть запущен явно, через зависимость, socket или timer. Disable удаляет связи установки, но не обязан остановить уже работающую службу; --now дополнительно запрашивает остановку. После редактирования файла нужен daemon-reload, чтобы менеджер перечитал описание; это не рестарт приложения. В курсе избегаем изменения системного default target: достаточно пользовательского сервиса и проверки связей.
Аналогия: записать работника в завтрашнее расписание и вызвать его сейчас — отдельные операции.
Нет. Без --now установка связей не равна немедленному start; смотрим статус и журнал.
Restart не лечит причину сбоя Пауза и лимит защищают от бесконечного быстрого цикла.
Менеджер службы связывает сбой, журнал и политику перезапуска ExecStart: Python Процесс работает exit ≠ 0 failed / журнал Код завершения и сообщение Restart=on-failure Пауза RestartSec Затем новая попытка start StartLimit Ограничить частые старты Рестарт не исправляет плохую конфигурацию. systemctl stop обычно не запускает автоперезапуск. Нет. Это может быть цикл падений; журнал и пользовательский путь покажут причину.
Restart=on-failure позволяет повторный запуск после заданных категорий неуспешного завершения. RestartSec задаёт задержку, а start rate limiting ограничивает слишком частые попытки. Если ExecStart указывает на несуществующий файл или конфигурация неверна, повторение не делает файл правильным. Сначала читаем journal и код завершения. Штатный systemctl stop обычно не активирует автоматический Restart даже при Restart=always. При остановке systemd обычно посылает TERM, ждёт TimeoutStopSec и при необходимости применяет финальный KILL согласно настройкам; KillMode определяет охват процессов, обычно control-group. Приложение обязано реализовать собственное корректное завершение. Не демонстрируем общий restart сервера: останавливаем только свой учебный unit. Восстановление должно подтверждаться запросом, а не только новым PID.
Аналогия: диспетчер снова вызывает мастера, но одинаково неверный адрес продолжит приводить к отказу.
Нет. Это может быть цикл падений; журнал и пользовательский путь покажут причину.
Состояние → журнал → конкретная проверка Собираем доказательства одной причины, затем проверяем исправление.
Одна служба связывает состояние, процессы и журнал systemctl status active / failed, PID, причина systemctl show MainPID, ExecMainStatus journalctl -u Сообщения этой службы Одна гипотеза Путь? права? порт? config? Сначала причина в журнале; затем исправление и проверка HTTP, а не только зелёный status. Окружение, cwd, пользователь и способы разбора команды отличаются; нужно сравнить именно эти факты.
Systemctl status даёт удобный снимок, но его короткий журнал может обрезать важную строку. Systemctl show позволяет получить MainPID, ExecMainStatus, Result и другие свойства. Journalctl -u отбирает сообщения системной службы, для user-unit используем journalctl --user -u. -b ограничивает текущую загрузку, -n количество записей, --no-pager удобно для короткой демонстрации. Причины старта часто прозаичны: неверный абсолютный путь, отсутствие WorkingDirectory, права на файл, занятый порт или окружение, которое раньше задавал интерактивный shell. ExecStart не является обычной строкой Bash: pipe, > и && без shell не работают как ожидает новичок. Не добавляем sh -c без необходимости; конфигурируем рабочую папку и окружение явно. Перед публикацией журнала удаляем секреты и личные пути.
Аналогия: письменная инструкция должна включать то, что в привычной мастерской делалось молча.
Окружение, cwd, пользователь и способы разбора команды отличаются; нужно сравнить именно эти факты.
systemctl и systemctl --user управляют разными менеджерами Системный сервер, сеанс пользователя и контейнер — разные области.
Система, пользователь и контейнер имеют разные области управления Системный systemd PID 1; системные units systemd --user Units выбранного пользователя Контейнер Свой PID namespace systemctl status Системный менеджер systemctl --user status Пользовательский менеджер PID 1: app / init Не обязательно systemd Пользовательский сервис не равен постоянному серверу; время жизни сеанса/WSL проверяем отдельно. Проверяется системный manager; для пользовательской службы нужен --user.
Пользовательский manager запускает units пользователя из ~/.config/systemd/user; systemctl --user обращается к нему. Системный manager использует системные пути и другой набор units. Перепутанный флаг часто даёт unit not found, хотя файл существует. Время жизни user-manager связано с сеансом и настройками lingering; включение lingering меняет поведение и не требуется бездумно для каждой лабораторной. В WSL дополнительно учитываем время жизни самой среды. В контейнере PID 1 может быть приложение или маленький init; Docker restart policy относится к контейнеру, а не автоматически к systemd-unit внутри него. В macOS аналог задач постоянных служб — launchd с plist и launchctl, в Windows — SCM с Windows service; обычный shell-скрипт ещё не превращается в нативную Windows service.
Аналогия: диспетчер здания и координатор вашей команды ведут разные расписания, даже когда называют задания одинаково.
Проверяется системный manager; для пользовательской службы нужен --user.
Логи нужно искать по источнику kernel journal, journal службы и файл приложения — разные потоки.
Журналы имеют разные источники и способы хранения Ядро Ring buffer → dmesg / journal Служба stdout / stderr → journal Приложение Файл JSON / syslog / stdout /run/log/journal Временное хранение /var/log/journal Постоянное, если настроено /var/log/* Текстовые логи, если есть journal бинарный: читаем journalctl. /var/log/syslog и auth.log зависят от установленной конфигурации. journalctl -k -b; journalctl -u имя.service -b; journalctl --user -u studypulse.service; ls /var/log — каждый инструмент смотрит свою область.
Dmesg читает сообщения ring buffer ядра, доступ может ограничиваться политикой системы. Journald собирает записи с metadata, включая службу, PID, boot и время; journalctl умеет фильтрацию по этим признакам. Journal хранится в бинарном формате: его не читают cat как текст. /run/log/journal предназначен для временного хранения; /var/log/journal используется для постоянного согласно Storage и конфигурации. Текстовые /var/log/syslog и /var/log/auth.log существуют при соответствующей syslog-конфигурации, а не обязаны присутствовать в каждой Ubuntu/container. Приложение может писать свой файл или stdout; Docker logs показывает stdout/stderr контейнера, но не любой файл внутри него. Ротация и retention ограничивают размер и срок хранения. Для расследования сохраняют контекст времени, версии и request_id, не раскрывая секреты. Смена timezone или неверные часы усложняет сопоставление.
journalctl -k -b; journalctl -u имя.service -b; journalctl --user -u studypulse.service; ls /var/log — каждый инструмент смотрит свою область.
Наблюдение механизмов ps -p 1 -o pid,comm,args
systemctl --user cat studypulse.service
systemctl --user show studypulse.service -p MainPID -p Result -p ExecMainStatus
journalctl --user -u studypulse.service -n 20 --no-pager
curl --fail http://127.0.0.1:8000/healthz
# Optional dependency exercise
python3 lab/experiments/systemd_graph.py
journalctl -k -b -n 20 --no-pager
journalctl --user -u studypulse.service -n 20 --no-pager
ls -lah /var/logПолный разбор команд в конспекте → Используйте исходный unit StudyPulse из lab/README.md. Покажите [Unit], [Service], [Install] и объясните каждую уже использованную директиву. Сравните start с enable; после ошибки прочитайте journal, исправьте путь и подтвердите HTTP. Дополнительный опыт systemd_graph.py создаёт только уникальные временные user-units, сравнивает After с Requires+After и удаляет их после завершения. Запускается только в Ubuntu с доступным systemd --user. На Mac обсуждаем схему и изучаем launchctl list; чужие plist не меняем.
Найдите сообщение запуска StudyPulse по unit и времени, затем request_id в JSON-логе. Укажите, что переживёт reboot в текущей конфигурации, а не в предполагаемом универсальном Linux.
Команды и наблюдения Ubuntu / Bash с systemd
ps -p 1 -o comm=
mkdir -p ~/.config/systemd/user
cp ~/devops-course/lab/studypulse.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user start studypulse
systemctl --user status studypulse --no-pager
journalctl --user -u studypulse -n 20 --no-pager
curl -i http://127.0.0.1:8000/healthzПример unit использует %h/devops-course/lab; путь к скопированному проекту должен совпасть. Предыдущий ручной запуск остановите, чтобы освободить порт. Ожидаемое наблюдение: PID 1 = systemd; служба active; HTTP healthz = 200. Если systemd недоступен, сначала исправляется конфигурация WSL.
Разбор результата PID 1 = systemd; служба active; HTTP healthz = 200. Если systemd недоступен, сначала исправляется конфигурация WSL.
Пример unit использует %h/devops-course/lab; путь к скопированному проекту должен совпасть. Предыдущий ручной запуск остановите, чтобы освободить порт.
При отсутствии systemd следуйте официальной инструкции WSL: в /etc/wsl.conf секция [boot], systemd=true; затем wsl --shutdown в PowerShell останавливает все WSL-дистрибутивы, поэтому сначала сохраните работу. Для этой пары допускается демонстрация преподавателя, если среда не готова. После исправления unit: systemctl --user daemon-reload; systemctl --user restart studypulse; journalctl --user -u studypulse -n 20; curl .../healthz. В завершение systemctl --user stop studypulse.
На macOS macOS использует launchd, не systemd. Unit-файл .service и journalctl не переносимы; у launchd plist, LaunchAgents/LaunchDaemons и другой lifecycle. На схеме сравниваем механизмы, а обязательную лабораторную systemd выполняем в Ubuntu. Учебный launchd-пример с проверкой приведён в отдельной странице сравнения ОС.
launchctl print gui/$(id -u)
# Linux-specific exercise: use an Ubuntu VM or the partner WSL2 setupКоманды macOS необходимо проверить на конкретном устройстве. macOS использует launchd, не systemd. Unit-файл .service и journalctl не переносимы; у launchd plist, LaunchAgents/LaunchDaemons и другой lifecycle. На схеме сравниваем механизмы, а обязательную лабораторную systemd выполняем в Ubuntu. Учебный launchd-пример с проверкой приведён в отдельной странице сравнения ОС.
Сломанный запуск Запустите предоставленный user-unit и подтвердите ответ HTTP. В учебной копии unit задайте MODEL_PATH=/missing/model.json. Выполните daemon-reload и restart, найдите причину в журнале. Восстановите значение, повторите запуск и проверку healthz; затем stop. Работа в парах: один оператор, второй проверяет гипотезу. Смена ролей в середине. При отсутствии systemd следуйте официальной инструкции WSL: в /etc/wsl.conf секция [boot], systemd=true; затем wsl --shutdown в PowerShell останавливает все WSL-дистрибутивы, поэтому сначала сохраните работу. Для этой пары допускается демонстрация преподавателя, если среда не готова. После исправления unit: systemctl --user daemon-reload; systemctl --user restart studypulse; journalctl --user -u studypulse -n 20; curl .../healthz. В завершение systemctl --user stop studypulse.
Что должно получиться Ошибка из журнала, исправление и HTTP-доказательство восстановления.
Служба восстанавливается без root; студент различает start, restart и daemon-reload.
При отсутствии systemd следуйте официальной инструкции WSL: в /etc/wsl.conf секция [boot], systemd=true; затем wsl --shutdown в PowerShell останавливает все WSL-дистрибутивы, поэтому сначала сохраните работу. Для этой пары допускается демонстрация преподавателя, если среда не готова. После исправления unit: systemctl --user daemon-reload; systemctl --user restart studypulse; journalctl --user -u studypulse -n 20; curl .../healthz. В завершение systemctl --user stop studypulse.
Ошибка для диагностики После правки unit забыли daemon-reload или порт занят ручным запуском.
Симптом → Гипотеза → Проверка
При отсутствии systemd следуйте официальной инструкции WSL: в /etc/wsl.conf секция [boot], systemd=true; затем wsl --shutdown в PowerShell останавливает все WSL-дистрибутивы, поэтому сначала сохраните работу. Для этой пары допускается демонстрация преподавателя, если среда не готова. После исправления unit: systemctl --user daemon-reload; systemctl --user restart studypulse; journalctl --user -u studypulse -n 20; curl .../healthz. В завершение systemctl --user stop studypulse.
Основные выводы Нет, нужен реальный запрос и проверка результата. Перечитывает описания unit, но не перезапускает автоматически приложение. Нет, нужен реальный запрос и проверка результата.
Перечитывает описания unit, но не перезапускает автоматически приложение.
После пары Добавить в README управление user-службой и диагностику занятого порта.
Конспект, команды и разбор → Проверьте критерии сдачи и дайте возможность повторной попытки. Первоисточники: https://ubuntu.com/server/docs/ https://learn.microsoft.com/en-us/windows/wsl/systemd
Пара 10 / ноябрь
Диагностика и ремонт Linux Диагностировать отказ по цепочке наблюдений и составить короткий отчёт.
Диагностировать отказ по цепочке наблюдений и составить короткий отчёт. Начните с симптома, затем формулируйте гипотезу и проверку. «Занят порт» предсказывает слушающий другой процесс в ss. «Неверный путь» предсказывает ошибку запуска и отсутствующий файл. «Неправильный URL» предсказывает исправный процесс и 404 на запрошенном пути. Случайная смена нескольких настроек одновременно лишает нас причинной связи. Перед изменением фиксируем состояние, после проверяем тот же запрос. Это учебная версия работы по инциденту, а не конкурс на количество команд. В парах один человек формулирует гипотезу, второй выполняет проверку; затем меняются ролями.
Контекст Исправление должно изменить причину и быть проверено тем же пользовательским действием.
Диагностировать отказ по цепочке наблюдений и составить короткий отчёт.
Command not found: проверить имя, command -v и PATH. Permission denied: проверить пользователя, rwx/ACL каждого родительского каталога, executable bit и noexec; sudo не исправляет неверный путь. Existing file + no such file: проверить interpreter shebang и PT_INTERP ELF, включая CRLF. Address already in use: найти собственный слушающий PID через ss/lsof, затем выбрать свободный порт или штатно остановить нужный процесс. Connection refused часто означает отсутствие слушателя в выбранной точке, timeout имеет больше возможных причин; HTTP 500 уже относится к ответу приложения. No space left: проверить df -h, df -i и du, затем deleted-open files; свободные байты не решают исчерпанные inode. Killed: проверить OOM и ограничения, не объявлять любую остановку нехваткой RAM. Missing .so: выяснить dependencies и совместимый пакет. После исправления повторить исходную команду и HTTP-запрос, сохранить минимальный runbook. Не использовать reboot/reinstall как способ стереть диагностические данные.
Гипотеза должна предсказывать наблюдение Команда выбирается для проверки причины.
01 Симптом
→ 02 Гипотеза
→ 03 Проверка
→ 04 Вывод
Аналогия: врач проверяет версию анализом, а не назначает все лекарства сразу.
Начните с симптома, затем формулируйте гипотезу и проверку. «Занят порт» предсказывает слушающий другой процесс в ss. «Неверный путь» предсказывает ошибку запуска и отсутствующий файл. «Неправильный URL» предсказывает исправный процесс и 404 на запрошенном пути. Случайная смена нескольких настроек одновременно лишает нас причинной связи. Перед изменением фиксируем состояние, после проверяем тот же запрос. Это учебная версия работы по инциденту, а не конкурс на количество команд. В парах один человек формулирует гипотезу, второй выполняет проверку; затем меняются ролями.
Диагностическая лестница Идём от адреса и процесса к журналу и конфигурации.
01 Среда / URL
→ 02 Процесс / порт
→ 03 HTTP / журнал
→ 04 Конфигурация / ресурсы
Нет универсальной команды, которая докажет исправность всех слоёв.
Сначала уточняем среду: Windows или WSL, какой путь, адрес и порт. Проверяем процесс, слушающий сокет и HTTP-ответ. Затем читаем журнал и сравниваем конфигурацию с README. Ресурсные проверки нужны, если признаки указывают на них, а не механически на каждый 404. Запишите команды и короткие результаты, не весь личный терминал. Не выводим env целиком: там могут быть секреты. Если нужен порт, читаем конкретное значение настройки. Не повышаем права без доказательства проблемы доступа.
Отчёт о восстановлении Исправление должно воспроизводиться и проверяться.
01 Факты
→ 02 Причина
→ 03 Исправление
→ 04 Проверка / профилактика
Аналогия: акт ремонта нужен следующей смене, а не только тому, кто крутил гайку.
Хороший мини-отчёт содержит симптом, факты, причину, изменение и проверку. Пример: curl на 8000 возвращал connection refused; служба слушала 8001; README содержал старый порт; исправили документированный URL; healthz вернул ожидаемую версию. Если доказательства причины недостаточно, пишем «гипотеза», а не «точно». На защиту выносится и предотвращение повторения: проверка конфигурации, инструкция запуска или тест. Восстановление доступности и окончательное исправление причины могут быть разными действиями, это будет важно в декабре.
Диагностика: от симптома к причине Исправление должно изменить причину и быть проверено тем же пользовательским действием.
От симптома к исправлению: конкретная проверка каждого слоя Нет команды в PATH command -v, PATH Не запускается файл file, shebang, права Нет ответа API ss, curl, адрес/порт Сбой приложения journal, config, version Диск заполнен df -h, df -i, du RAM / зависание free, vmstat, ps Permission denied id, путь, ACL DNS / маршрут getent, ip route, curl Исправление выбирают после подтверждения причины. sudo, reboot и reinstall не являются универсальной диагностикой. Подтвердите причину, исправьте её и повторите исходный запрос.
Command not found: проверить имя, command -v и PATH. Permission denied: проверить пользователя, rwx/ACL каждого родительского каталога, executable bit и noexec; sudo не исправляет неверный путь. Existing file + no such file: проверить interpreter shebang и PT_INTERP ELF, включая CRLF. Address already in use: найти собственный слушающий PID через ss/lsof, затем выбрать свободный порт или штатно остановить нужный процесс. Connection refused часто означает отсутствие слушателя в выбранной точке, timeout имеет больше возможных причин; HTTP 500 уже относится к ответу приложения. No space left: проверить df -h, df -i и du, затем deleted-open files; свободные байты не решают исчерпанные inode. Killed: проверить OOM и ограничения, не объявлять любую остановку нехваткой RAM. Missing .so: выяснить dependencies и совместимый пакет. После исправления повторить исходную команду и HTTP-запрос, сохранить минимальный runbook. Не использовать reboot/reinstall как способ стереть диагностические данные.
Подтвердите причину, исправьте её и повторите исходный запрос.
Наблюдение механизмов command -v python3
file app.py
pwd
id
ls -ld . data
df -h .
df -i .
ss -lntp
curl --max-time 3 -i http://127.0.0.1:8000/healthzПолный разбор команд в конспекте → Для каждого отказа запишите симптом, проверку, причину, минимальное исправление и проверочный запрос. Используйте только собственные процессы и файлы.
Команды и наблюдения Ubuntu / Bash
cd ~/devops-course/lab
PORT=8001 .venv/bin/python app.py
# In another terminal
curl --connect-timeout 2 http://127.0.0.1:8000/healthz
ss -ltnp | grep -E ":8000|:8001"
curl -i http://127.0.0.1:8001/healthzЭто воспроизводимая авария без изменения системных служб. После демонстрации Ctrl+C. Ожидаемое наблюдение: На 8000 отказ соединения, на 8001 — 200; причина в несоответствии порта запроса и запуска.
Разбор результата На 8000 отказ соединения, на 8001 — 200; причина в несоответствии порта запроса и запуска.
Это воспроизводимая авария без изменения системных служб. После демонстрации Ctrl+C.
A: ss и curl к реальному порту. B: сообщение об ошибке конфигурации, проверка ls models/model.json, корректный MODEL_PATH. C: работающий healthz плюс 404 неверного пути; исправить URL. Итоговый POST /predict с hours=4 должен вернуть score=0.5 для базового коэффициента 0.125. Оценивать аргументацию, а не скорость и число команд.
На macOS Сценарии порта, пути, HTTP и Python одинаковы; замените ss на lsof. Не используйте systemctl для launchd. Все исследования остаются на своём localhost.
lsof -nP -iTCP:8000 -sTCP:LISTEN
lsof -nP -iTCP:8001 -sTCP:LISTEN
curl -i http://127.0.0.1:8001/healthzКоманды macOS необходимо проверить на конкретном устройстве. Сценарии порта, пути, HTTP и Python одинаковы; замените ss на lsof. Не используйте systemctl для launchd. Все исследования остаются на своём localhost.
Станции диагностики Станция A: преподаватель запускает сервис на другом порту. Найдите его и исправьте клиентский URL. Станция B: MODEL_PATH ссылается на отсутствующий артефакт. Восстановите путь. Станция C: запрос отправлен на /healtz. Определите различие между 404 и отказом соединения. На каждой станции оформите пять строк: симптом, проверка, причина, исправление, доказательство. Работа в парах: один оператор, второй проверяет гипотезу. Смена ролей в середине. A: ss и curl к реальному порту. B: сообщение об ошибке конфигурации, проверка ls models/model.json, корректный MODEL_PATH. C: работающий healthz плюс 404 неверного пути; исправить URL. Итоговый POST /predict с hours=4 должен вернуть score=0.5 для базового коэффициента 0.125. Оценивать аргументацию, а не скорость и число команд.
Что должно получиться Три мини-отчёта и рабочий README проекта.
Каждая причина подтверждена наблюдением; healthz и predict работают после восстановления.
A: ss и curl к реальному порту. B: сообщение об ошибке конфигурации, проверка ls models/model.json, корректный MODEL_PATH. C: работающий healthz плюс 404 неверного пути; исправить URL. Итоговый POST /predict с hours=4 должен вернуть score=0.5 для базового коэффициента 0.125. Оценивать аргументацию, а не скорость и число команд.
Ошибка для диагностики Студент перезапускает всё, не сохранив доказательства.
Симптом → Гипотеза → Проверка
A: ss и curl к реальному порту. B: сообщение об ошибке конфигурации, проверка ls models/model.json, корректный MODEL_PATH. C: работающий healthz плюс 404 неверного пути; исправить URL. Итоговый POST /predict с hours=4 должен вернуть score=0.5 для базового коэффициента 0.125. Оценивать аргументацию, а не скорость и число команд.
Основные выводы Неясно, какое изменение действительно исправило причину. Повтор исходного пользовательского запроса с ожидаемым статусом и содержимым. Неясно, какое изменение действительно исправило причину.
Повтор исходного пользовательского запроса с ожидаемым статусом и содержимым.
После пары Сдать Linux-чекпоинт: паспорт среды, README, скрипт сводки и один отчёт об аварии.
Конспект, команды и разбор → Проверьте критерии сдачи и дайте возможность повторной попытки. Первоисточники: https://ubuntu.com/server/docs/ https://roadmap.sh/devops