Что именно «зависает» при shutdown/reboot
Ситуации вида linux reboot hangs или shutdown hangs обычно выглядят одинаково: вы запускаете shutdown/reboot, консоль показывает «Stopping…», «A stop job is running…», «Unmounting…», а дальше тишина. Важно понимать: в systemd выключение — это такой же набор юнитов и зависимостей, как и запуск. Если какой-то шаг не завершился, менеджер будет ждать до таймаута (или бесконечно, если зависло ядро/драйвер).
Типовые точки «залипания»:
- Остановка сервисов: демон не завершает воркеры, завис на I/O, держит сокеты/файлы.
- Размонтирование ФС: umount target is busy, открытые дескрипторы,
cwdпроцесса внутри mountpoint, nested/bind-mount. - Сетевые ФС: nfs umount timeout — клиент ждёт сервер, а сеть уже «уехала».
- Контейнеры: docker shutdown hang — долгий stop контейнеров, зависшие overlay-mount, тома.
- Процессы в D state: tasks in D state (uninterruptible sleep) — такие процессы сигналами не убиваются и могут держать выключение.
Ниже — практический чеклист: быстро понять, где зависло; найти конкретного виновника; исправить причину; и только в самом конце применять аварийные меры.
Быстро понять, на каком шаге остановка
1) Смотрим предыдущую загрузку: journalctl -b -1
Если машина «не выключилась» и вы перезапустили её аппаратно (или через панель), самый полезный артефакт — журнал предыдущей загрузки. Он часто содержит строку, где зависли stop jobs и на каком юните.
journalctl -b -1 -e
Ищите по словам: A stop job is running, Unmounting, umount, nfs, docker, timed out, failed, killed.
Полезно точечно фильтровать:
journalctl -b -1 -g "A stop job is running" -e
journalctl -b -1 -g "Unmounting" -e
2) Во время зависания: что показывает systemd прямо сейчас
Когда система ещё жива (есть SSH/консоль) и «висит» на stop job, сначала посмотрите текущие задания systemd и выясните, какой юнит блокирует остановку.
systemctl list-jobs
systemctl status --no-pager
Если видно конкретный юнит со статусом «Stopping…» — сразу переходите к диагностике этого сервиса и его ресурсов (файлы, сокеты, примонтированные ФС, сеть).
3) Контекст зависимостей: что от чего зависит
systemd-analyze critical-chain формально показывает критическую цепочку для загрузки, но в реальной жизни помогает понять «архитектуру» зависимостей: какие сервисы сцеплены, и где можно получить неправильный порядок остановки (например, сеть падает раньше NFS).
systemd-analyze critical-chain

Разбираем «umount target is busy» и почему это стопорит shutdown
Классика: systemd пытается размонтировать файловую систему, но получает umount target is busy. Это означает, что внутри mountpoint кто-то держит:
- открытые файлы (лог, база, PID-файл, сокет);
- текущую рабочую директорию процесса (
cwd); - nested/bind-mount внутри;
- активный loop device, overlay, fuse.
1) Находим, кто держит mountpoint
Самые практичные инструменты — lsof и fuser.
lsof +f -- /mnt/data
fuser -vm /mnt/data
Если lsof слишком тяжёлый (большие системы, тысячи файлов), можно быстро проверить, чья cwd находится внутри каталога:
find /proc -maxdepth 2 -type l -name cwd -exec readlink -f {} \; 2>/dev/null | grep -F "/mnt/data"
Если система уже частично «развалила» ФС, часть /proc/*/cwd может читаться с ошибками — это ожидаемо.
2) Что делать с найденными процессами
Если это штатный сервис — останавливайте его корректно через systemd, чтобы он сам закрыл файлы и отпустил рабочие каталоги:
systemctl stop your-service
Дальше — быстро понять, где он завис:
systemctl status your-service --no-pager
journalctl -u your-service -e
Если нужно добить руками (осознанно понимая последствия для данных):
kill -TERM 1234
kill -KILL 1234
Если даже SIGKILL не помогает — это сильный сигнал, что процесс в D state (ниже) или ядро ждёт I/O.
3) «Лечебные» варианты размонтирования
Иногда, чтобы закончить обслуживание, помогает «ленивое» размонтирование: точка монтирования исчезает из дерева, а реальное освобождение произойдёт, когда процессы отпустят ссылки.
umount -l /mnt/data
Для некоторых сетевых ФС применяют форс-размонтирование:
umount -f /mnt/nfs
umount -fиumount -l— это аварийный выход, а не лечение причины. После таких действий проверьте приложения на консистентность и корректную остановку.
Процессы в D state: почему не убиваются и ломают выключение
tasks in D state — частая причина «магических» зависаний. Процесс находится в uninterruptible sleep, обычно ожидая завершения I/O (диск, сеть, NFS, iSCSI, зависший device-mapper, проблемы со сториджем/драйвером). В этом состоянии SIGKILL не действует: процесс не исполняется, он «заморожен» в ожидании ядра.
1) Быстро найти D-state и понять, чего он ждёт
ps axo pid,stat,comm,wchan:32 | awk '$2 ~ /D/ {print}'
Колонка wchan подсказывает, на чём именно ждёт процесс (часто можно увидеть намёки на блоковый слой, ФС или NFS). Если нужно углубиться:
cat /proc/1234/stack
Если стек/ожидание указывает на NFS или блоковые операции, проблема почти всегда «ниже» приложения: сеть, диск, драйвер, хранилище, деградация RAID, timeouts.
2) Что смотреть по диску и ядру
Первым делом — сообщения ядра: они часто прямо говорят про таймауты, reset устройства, I/O error или «hung task».
dmesg -T | tail -n 200
Если доступны утилиты мониторинга I/O, посмотрите, не упёрся ли диск в ожидания:
iostat -xz 1
При постоянных таймаутах сториджа выключение может «никогда» не завершиться корректно: systemd ждёт остановки демонов, демоны ждут fsync, fsync ждёт диск.
NFS и сетевые файловые системы: типичная причина nfs umount timeout
При выключении порядок критичен: если сеть/маршрутизация падают раньше, чем NFS успевает размонтироваться, вы получаете nfs umount timeout, stop jobs и зависание. Это особенно заметно на серверах, где NFS используется для бэкапов, медиа или общих каталогов приложений.
1) Диагностика NFS
Посмотрите, что примонтировано и с какими опциями:
findmnt -t nfs,nfs4
И проверьте журнал (включая предыдущую загрузку, если выключение закончилось аппаратным ребутом):
journalctl -b -1 -g "nfs" -e
2) Практические меры, чтобы выключение не висло
- Сеть должна жить до конца: убедитесь, что NFS размонтируется до остановки сетевых сервисов. На «чистом» systemd это обычно учтено, но кастомные юниты и ручные mount-скрипты часто ломают зависимости.
- Используйте automount там, где возможно: меньше активных зависимостей на момент shutdown.
- Планируйте недоступность NFS: приложения должны переживать ситуацию «сервер NFS недоступен», иначе даже обычный ребут после обновления ядра может превратиться в аварийный.
Если у вас много контейнеров и сетевых томов, дополнительно посмотрите практику из статьи про изоляцию контейнеров и окружения: про gVisor/Firecracker и границы изоляции контейнеров.
Docker shutdown hang: почему контейнеры держат reboot
Docker/containerd добавляют несколько слоёв: контейнерные процессы, сеть/неймспейсы, overlay-mount, тома. На shutdown systemd останавливает docker.service, а docker пытается корректно остановить контейнеры, ожидая graceful shutdown по таймауту. Если контейнеры зависли (или внутри D-state из-за storage/NFS), выключение тянется.
1) Найти «упёртый» контейнер и остановить его
docker ps
Попробуйте дать контейнеру адекватный таймаут на завершение:
docker stop --time 10 container_name
Если не помогло:
docker kill container_name
Если контейнер «умер», но монтирования остаются, проверьте D-state у процессов на хосте и активные overlay-mount:
findmnt | grep -E "overlay|docker"
2) На будущее: снизить риск зависаний
- Давайте приложениям корректно завершаться: правильные сигналы (PID 1), корректные
stop-timeout, graceful shutdown. - Не храните критичные данные контейнеров на нестабильных сетевых ФС без продуманной деградации.
- Следите за диском, inode и ошибками ФС: overlay довольно быстро упирается в проблемы сториджа.
Если на хосте есть сложности с правилами фильтрации трафика и после ребута сеть поднимается «не так», это тоже может влиять на сетевые ФС и остановку сервисов. По теме — как Docker взаимодействует с iptables/nftables.

systemd: как включить более подробный debug shutdown
Если проблема воспроизводится, лучший подход — собрать подробный лог выключения, а не гадать. Начать можно с увеличения уровня логирования systemd-менеджера, чтобы в журнале было больше деталей.
1) Временное повышение логирования systemd
На работающей системе можно поднять уровень логирования (до следующей перезагрузки или до изменения обратно):
systemd-analyze log-level debug
После попытки обычного reboot анализируйте журнал предыдущей загрузки:
journalctl -b -1 -e
2) Журналы юнитов, которые чаще всего «держат» shutdown
Соберите хвосты логов по подозрительным сервисам:
journalctl -b -1 -u docker -e
journalctl -b -1 -u nfs-client.target -e
И посмотрите список mount-юнитов (часто именно они висят на размонтировании):
systemctl list-units --type mount
Когда нужно быстро восстановить управление: безопасные и аварийные варианты
Иногда задача не «идеально завершить», а вернуть сервер в строй. Важно различать меры, которые обычно безопасны, и меры, после которых нужна проверка ФС/приложений.
Относительно безопасно
- Остановить зависший сервис через
systemctl stop, затем проверить логи и перезапустить. - Найти процессы, держащие mount, и корректно завершить именно их (а не «рубить» всё подряд).
- Осознанно снизить таймаут graceful stop для конкретного сервиса, чтобы он не держал shutdown бесконечно.
Аварийно (использовать осознанно)
umount -lилиumount -fдля размонтирования проблемного mountpoint.- Принудительная перезагрузка, если система не реагирует, и вы принимаете риск потери данных в кеше.
Если причина — D-state из-за диска или сетевого хранилища, «жёсткая» перезагрузка может быстрее вернуть сервис, но повышает риск повреждения данных. По возможности сначала выясните источник I/O-зависания.
Профилактика: чтобы shutdown/reboot не превращались в лотерею
- Порядок остановки: проверьте, что сетевые сервисы не убивают сеть раньше размонтирования NFS.
- Мониторинг D-state и hung tasks: если периодически появляются D-процессы — это почти всегда проблема storage/сети/драйвера.
- Разделяйте роли: когда на одной машине и база, и NFS-клиент, и Docker с десятками контейнеров — шанс сложного зависания выше.
- Привычка смотреть журналы:
journalctl -b -1после нештатной перезагрузки часто находит причину до того, как она станет постоянной.
Если вы планируете перенос сервисов на отдельную виртуализацию, удобный практический вариант — вынести «шумные» роли (Docker, сборки, мониторинг) на VDS, а сайты с типовой нагрузкой держать на виртуальном хостинге, чтобы уменьшить число сложных зависимостей на одном сервере.
Мини-чеклист диагностики (сохраните в заметки)
- После нештатного ребута:
journalctl -b -1 -eи поискstop job/umount/nfs/docker. - Если зависание сейчас:
systemctl list-jobs, затемsystemctl status --no-pager. - Если umount busy:
lsof +f -- /mountилиfuser -vm /mount. - Если процессы не убиваются: ищите D-state через
ps ... wchanи смотрите/proc/PID/stack,dmesg. - Если NFS:
findmnt -t nfs,nfs4, проверяйте порядок остановки сети и поведение при недоступности сервера. - Если Docker: остановите проблемные контейнеры, проверьте overlay-mount и D-state на хосте.
Если захотите, можно расширить этот материал готовыми systemd drop-in примерами: как ограничить время остановки сервиса (через TimeoutStopSec), и как аккуратно выстроить Before/After для mount-юнитов и сетевых целей под Debian/Ubuntu и Alma/Rocky.


