С чего начать Первые шаги трек · 15 ступеней
Linux Labs

Постмортем — разбор сбоя без поиска виноватых

8 мин Ubuntu 24.04 · systemd 255

Постмортем — письменный разбор сбоя: хронология, влияние, причина и действия, чтобы сбой не повторился.

Шпаргалка

6 команд Версия для печати
  • cd ~/incident
  • окно сбоя: -S с какого времени, -U до какого (сегодня, UTC)
  • sudo journalctl -S 12:00 -U 12:10 -o short-iso -t sudo > raw.txt
  • служба — отдельным вызовом: -t и -u вместе дают пустой вывод
  • sudo journalctl -S 12:00 -U 12:10 -o short-iso -u nginx >> raw.txt
  • по времени, в формат «ЧЧ:ММ:СС событие»
  • sort raw.txt | cut -c12-19,26- > timeline.txt
  • первая и последняя ошибка, которую видели пользователи
  • awk '$9 >= 500' /var/log/nginx/access.log | sed -n '1p;$p'
  • unix-время из $msec — в часы
  • date -u -d @1792677901 +%T

Обзор

Постмортем (postmortem, разбор сбоя) — документ, который пишут после инцидента (incident-response), когда сервис уже работает. В нём четыре части: что происходило по минутам, что почувствовали пользователи, почему так вышло и что команда изменит. Цель — чтобы тот же сбой не повторился и чтобы его опыт достался всем, кто не был на смене.

markdown
# Разбор: сайт не отвечал 22.10

### Хронология
12:00:40 выкладка поменяла конфиг сайта; reload nginx не прошёл
12:00:52 плановый перезапуск nginx — не запустился:
         unknown directive "proxy_pas"
12:00:53 lab-sitecheck: сайт не отвечает — начало сбоя
12:01:21 lab-sitecheck: сайт 200 — конец сбоя

### Влияние
28 с сайт не отвечал никому: 0,2 % бюджета ошибок за 30 дней
при SLO 99,5 %.

### Причина
Опечатка в конфиге сайта. Выкладка не запускала `nginx -t`,
неудачный reload никто не заметил, перезапуск остановил сайт.

### Действия
- Выкладка запускает `nginx -t` и останавливается при ошибке.
- Алерт на неудачный reload nginx.

По-английски разделы называются Timeline, Impact, Root cause и Action items.

Хронология

Хронология — события сбоя по времени, строка на событие: время в UTC первым, затем факт. Формат тот же, что у хронологии по ходу инцидента (incident-response):

text
ЧЧ:ММ:СС событие

Если по ходу её не вели, хронологию собирают из журналов. Каждый источник знает своё:

Источник Что в нём видно
journalctl -t sudo действия людей: кто, когда, какую команду
journalctl -u <служба> что делала программа: старт, ошибка, остановка
проверка сайта, access.log что видели пользователи: коды и время ответа
алерты когда команда узнала о сбое

Начало и конец сбоя берут по тому, что видели пользователи: первая ошибка в access.log или в проверке сайта, первый успешный ответ после них. Время правки — отдельная строка. Между правкой и началом сбоя бывают секунды, а бывают дни: опечатка лежит в файле, пока службу не перезапустят. Строки журнала годятся в хронологию как есть (-o short-iso), их только сокращают до факта.

Без поиска виноватых

Разбор без поиска виноватых (blameless) исходит из того, что люди ошибаются всегда, а система должна ловить ошибку раньше пользователей. Вопрос разбора — что позволило ошибке дойти до них: какой проверки не было, чего не было видно, почему откат занял десять минут.

Поэтому в разборе роли вместо имён: «выкладка», «дежурный», deploy. Человек, которого назвали виноватым, в следующий раз промолчит о своей ошибке, и сбой будут искать дольше.

Причина

Причина сбоя редко одна. Обычно это пара:

  • скрытая поломка — то, что было сломано заранее и ждало: опечатка в конфиге, полный на 95 % диск, просроченный сертификат;
  • спусковой крючок — событие, после которого поломка стала видна: перезапуск, рост нагрузки, ночная ротация.

Дойти до них помогает цепочка «почему»: сайт не отвечал — nginx не запустился — в конфиге опечатка — выкладка не проверила конфиг — проверки в выкладке нет. Цепочку останавливают на том, что команда может изменить. В раздел «Причина» пишут сломанные компоненты по именам: конфиг сайта nginx, pg_hba.conf, правило алерта.

Влияние

Сколько длился сбой (по пользователям), сколько запросов упало, какую долю бюджета ошибок он съел (sli-slo). Цифры берут из access.log за окно сбоя — рецепт ниже.

Действия

Действия (action items) — что команда изменит, чтобы сбой не повторился или был найден раньше. Каждое — конкретное и проверяемое, с владельцем и сроком:

Расплывчато Проверяемо
быть внимательнее при выкладке выкладка запускает nginx -t и останавливается при ошибке
следить за диском алерт при заполнении /var больше 80 %
лучше тестировать тест на конфиг в CI репозитория конфигов

Действие «быть внимательнее» проверить нельзя, и через месяц сбой повторится.

Рецепты

3

Хронология из журналов

bash
cd ~/incident
since='2026-10-22 12:00'; until='2026-10-22 12:10'
sudo journalctl --since "$since" --until "$until" -o short-iso \
  -t sudo -t lab-sitecheck > raw.txt
sudo journalctl --since "$since" --until "$until" -o short-iso \
  -u lab-app >> raw.txt
sort raw.txt | cut -c12-19,26- > timeline.txt

Два вызова: -t и -u в одной команде отбирают записи, которые подходят под оба условия сразу, и вывод пустеет. -o short-iso печатает дату и время с поясом (2026-10-22T12:00:41+00:00), по ним sort сводит два списка. cut оставляет время (знаки 12–19) и всё после пояса: имя машины, программу и сообщение.

text
12:00:41 node1 sudo[1237]:  deploy : … COMMAND=/usr/bin/sed -i …
12:00:43 node1 lab-sitecheck[812]: site answers 502

Дальше файл правят руками: лишнее (строки pam_unix у sudo) — вон, роль вместо имени, отметки «начало сбоя» и «конец сбоя».

Начало и конец сбоя по access.log

bash
awk '$9 >= 500' /var/log/nginx/access.log | sed -n '1p;$p'

Первая и последняя строка с 5xx. Если в конце строки $msec (sli-slo), время переводит date -u -d @1792677901 +%T (date). Конец сбоя — первый успешный ответ после последней ошибки.

Сколько запросов упало

bash
f=$(date -d '2026-10-22 12:00:53' +%s)
t=$(date -d '2026-10-22 12:01:21' +%s)
awk -v f="$f" -v t="$t" '$NF >= f && $NF < t {n++; if ($9 >= 500) b++}
  END {print n, b}' /var/log/nginx/access.log

Все запросы окна сбоя и ответы 5xx среди них. Доля бюджета — b ÷ бюджет окна SLO (sli-slo).

Неполадки

3

В хронологии дыры

  • Журнал уже очищен: journalctl --disk-usage и самая ранняя запись (journalctl | head -n 1) покажут, что осталось.
  • Служба пишет в свой файл, а не в журнал: смотри /var/log/<служба>/.
  • Часы машин расходятся или пояса разные: сводя журналы двух машин, переводи всё в UTC (journalctl --utc).

Разбор свёлся к «человек ошибся»

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

Действия не выполняются

У действия нет владельца или срока. Каждое действие — задача в трекере с именем и датой; на следующем разборе проверяют, что сделано.

Опасно

1

Имена в разделе «Причина»

Разбор с виноватым учит команду прятать ошибки. Следующий сбой расследуют дольше: никто не скажет, что правил конфиг за минуту до него. Роль вместо имени, вопрос о системе вместо вопроса о человеке.

Термины

3
хронология (timeline)
События сбоя по времени, строка на событие: «ЧЧ:ММ:СС событие» в UTC. Ведут по ходу инцидента или собирают после из журналов. Ещё встречается в: Инцидент, journalctl
без поиска виноватых (blameless)
Правило разбора: люди ошибаются всегда, вопрос — что позволило ошибке дойти до пользователей. В разборе роли вместо имён. Ещё встречается в: Инцидент
действие (action item)
Что команда изменит после сбоя: конкретная проверяемая задача с владельцем и сроком — «nginx -t в выкладке», а «быть внимательнее» сюда не годится. Ещё встречается в: chage, find, rsyslog: текстовые логи и пересылка на сборщик, sed и awk и ещё 17

См. также

  • incident-response — первые минуты, ранбук, хронология по ходу.
  • sli-slo — бюджет ошибок для раздела «Влияние».
  • journalctl — отбор по времени, -t, -u, -o short-iso.
  • nginx — access.log: коды и время ответа.
  • date — unix-время в часы и обратно.
  • sed-awk — поля и подсчёт в awk.
Загрузка…