Когда на сервере внезапно «ломается» установка пакетов, это почти всегда происходит в самый неподходящий момент: перед деплоем, во время инцидента или при срочном обновлении безопасности. Ниже — практичный runbook для Debian/Ubuntu (и производных), который помогает последовательно восстановить работу apt и dpkg без лишней магии.
Цель runbook: вернуть менеджер пакетов в консистентное состояние. Сначала разбираемся с блокировками и незавершёнными операциями, затем выравниваем зависимости, и только после этого повторяем установку/обновление.
Симптомы: как понять, что проблема в APT/dpkg
Типичные сообщения, которые указывают на «разъезд» состояния пакетов:
apt brokenи предложение запуститьapt --fix-broken installunmet dependenciesпри установке/обновлении- «dpkg was interrupted, you must manually run 'dpkg --configure -a'»
- ошибка блокировки: «Could not get lock /var/lib/dpkg/lock», «/var/lib/apt/lists/lock», «/var/cache/apt/archives/lock»
held packagesи отказ продолжать обновление
Правило №0: не усугубить
Перед тем как «чинить», важно не сделать хуже:
- Не запускайте параллельно несколько процессов
apt/dpkg(особенно в разных SSH-сессиях). - Не удаляйте lock-файлы «на автомате», пока не убедились, что нет активной установки.
- Фиксируйте действия: команды и ключевой вывод (хотя бы в буфере терминала), чтобы понимать, где именно сломалось.
Если сервер на VDS, отдельный плюс — вы можете безопасно выделить «ремонтное окно» и выполнить шаги последовательно, не боясь, что фоновые процессы «перетрут» друг друга параллельными вызовами пакетного менеджера.

Шаг 1. Проверяем, кто держит блокировки (lock)
Ошибка с /var/lib/dpkg/lock обычно означает одно из двух: либо реально идёт установка (и надо подождать), либо процесс упал/завис и оставил систему в полу-состоянии.
1.1. Смотрим активные процессы apt/dpkg
ps aux | egrep 'apt|apt-get|dpkg|unattended' | grep -v egrep
Если видите unattended-upgrades или активный apt-get — чаще всего правильное решение: дождаться завершения (или аккуратно перенести работы на другое окно).
1.2. Проверяем, кто держит lock-файлы
sudo lsof /var/lib/dpkg/lock
sudo lsof /var/lib/dpkg/lock-frontend
sudo lsof /var/lib/apt/lists/lock
sudo lsof /var/cache/apt/archives/lock
Если lsof показывает PID процесса, это лучший сигнал, что блокировка не «мёртвая», а занята.
1.3. Если apt завис: аккуратная остановка
Когда процесс реально завис (нет прогресса, I/O нулевой, висит долго и вы уверены, что ждать бессмысленно), действуйте по возрастанию «жёсткости»:
- Корректно завершить:
sudo kill PID. - Если не помогло:
sudo kill -TERM PID. - Только если процесс не умирает совсем:
sudo kill -KILL PID.
sudo kill 12345
Удалять
/var/lib/dpkg/lockимеет смысл только после остановки всех процессов apt/dpkg и проверкиlsof. Сам lock-файл — не «проблема», а индикатор.
1.4. Удаляем lock-файлы (только если они точно «сироты»)
sudo rm -f /var/lib/dpkg/lock
sudo rm -f /var/lib/dpkg/lock-frontend
sudo rm -f /var/lib/apt/lists/lock
sudo rm -f /var/cache/apt/archives/lock
Шаг 2. Завершаем незаконченные операции dpkg
Если установка была прервана, самая частая «точка восстановления» — команда dpkg --configure -a. Она пытается донастроить пакеты, которые уже распакованы, но ещё не сконфигурированы.
sudo dpkg --configure -a
2.1. Если dpkg ругается на зависимости
На этом этапе часто всплывают unmet dependencies: пакет распакован, но для конфигурации не хватает библиотек/утилит. Тогда переходите к шагу с «фиксом» APT.
Шаг 3. Чиним зависимости: apt --fix-broken install
Классическая связка для случаев apt broken и unmet dependencies выглядит так:
3.1. Обновляем индексы пакетов
sudo apt update
3.2. Исправляем «сломанные» зависимости
sudo apt --fix-broken install
APT попытается подтянуть недостающие зависимости, удалить конфликтующие пакеты и привести систему к согласованному виду.
3.3. Повторяем dpkg configure при необходимости
sudo dpkg --configure -a
Иногда порядок «dpkg configure → apt fix-broken → dpkg configure» приходится повторить 1–2 раза, если проблема каскадная.
Шаг 4. Диагностируем: что именно сломано в базе пакетов
Если стандартные команды не помогли, нужно понять, в каком состоянии пакеты и на каком шаге всё падает.
4.1. Смотрим пакеты в проблемных состояниях
sudo dpkg -l | egrep '^(..r|..iF|..iU|..iH|..rc|i.)'
Короткая расшифровка самых полезных статусов:
iU— распакован, но не настроен (unpacked)iF— конфигурация упала (half-configured)rc— удалён, но конфиги остались (обычно не критично)
4.2. Проверяем «половинчатые» установки
sudo dpkg --audit
4.3. Смотрим последние логи APT/dpkg
sudo tail -n 200 /var/log/dpkg.log
sudo tail -n 200 /var/log/apt/term.log
Логи часто прямо говорят, на каком пакете всё ломается: postinst-скрипт, конфликт файлов, несовместимость версий.
Шаг 5. Held packages: удержанные пакеты (apt-mark hold)
held packages — частая причина unmet dependencies и невозможности обновить систему. Пакет может быть удержан администратором через apt-mark (а ещё бывает pinning/приоритеты репозиториев, но это отдельная тема).
5.1. Проверяем, есть ли hold
apt-mark showhold
5.2. Удерживаем пакет осознанно (пример)
sudo apt-mark hold nginx
Используйте apt-mark hold только когда понимаете последствия: вы берёте на себя ручной контроль зависимостей и рискуете застрять на цепочке конфликтов при следующих обновлениях.
5.3. Снимаем hold, чтобы починить зависимости
sudo apt-mark unhold nginx
После снятия hold обычно повторяют:
sudo apt update
sudo apt --fix-broken install
Шаг 6. Точечное лечение конфликтов и «нестыковок» версий
Иногда apt --fix-broken install упирается в конкретный конфликт: пакет A требует одну версию библиотеки, а пакет B уже зафиксировал другую (или система смешала источники пакетов).
6.1. Пытаемся установить недостающую зависимость явно
sudo apt install libexample1
Если APT предлагает варианты (удалить, заменить, понизить версию) — на проде сначала оцените последствия. Если это веб-сервер, кэш или прокси, изменения набора пакетов легко «роняют» конфигурацию и модули.
6.2. Проверяем кандидатов и версии пакета
apt-cache policy nginx
Команда показывает «Candidate» и список источников, помогая понять, почему APT выбирает именно эту версию.
6.3. Принудительная переустановка проблемного пакета
sudo apt install --reinstall nginx
Полезно, когда postinst-скрипт падал из-за временных условий (например, сервис не стартовал из-за занятого порта), а сейчас окружение уже исправлено.
Шаг 7. Сценарий «всё сломано»: безопасная последовательность команд
Ниже — «универсальный» чеклист, который покрывает ключевые ситуации: /var/lib/dpkg/lock, незавершённый dpkg --configure -a, apt broken и unmet dependencies.
ps aux | egrep 'apt|apt-get|dpkg|unattended' | grep -v egrep
sudo lsof /var/lib/dpkg/lock
sudo lsof /var/lib/dpkg/lock-frontend
sudo lsof /var/lib/apt/lists/lock
sudo lsof /var/cache/apt/archives/lock
sudo dpkg --configure -a
sudo apt update
sudo apt --fix-broken install
sudo dpkg --configure -a
sudo apt -f install
Обратите внимание: apt -f install и apt --fix-broken install по сути про одно и то же. В runbook часто оставляют оба варианта, потому что в разных инструкциях и скриптах встречаются разные привычки записи.
Шаг 8. Если проблема повторяется после каждой установки
Если вы чините APT/dpkg «по кругу», обычно причина не в самом менеджере пакетов, а в окружении:
- Ошибки диска или файловой системы:
dpkgне может записать состояние. - Заканчивается место в
/varили на корневом разделе: распаковка обрывается, остаются «unpacked» пакеты. - Сломанные сторонние репозитории или смешение релизов: версии пакетов перестают стыковаться.
- Автообновления запускаются в неудобное время и конфликтуют с ручными установками.

8.1. Быстрые проверки диска и места
df -h
df -i
Если место закончилось, APT может сваливаться в apt broken, а dpkg — оставлять пакеты в состоянии «unpacked». Сначала освобождаем место, затем повторяем шаги восстановления.
8.2. Если виноваты автообновления
На серверах часто работает unattended-upgrades. Он полезен, но может держать lock в момент, когда вы запускаете деплой. Минимум — научитесь распознавать его по процессам и логам. Решение «убивать всегда» — плохая практика; лучше дождаться завершения или настроить расписание/окна обновлений.
Шаг 9. Минимальная профилактика: чтобы APT не ломался на ровном месте
- Не делайте «частичные апгрейды» на проде без понимания:
apt update, затем план, затем применение. - Держите систему в рамках одного релиза; избегайте смешения репозиториев и «случайных» PPA.
- Перед большим обновлением проверяйте hold-пакеты:
apt-mark showhold. - После аварийного восстановления делайте контроль:
dpkg --audit.
Полезная перелинковка для веб-серверов и прокси
Если «сломанные обновления» случились на узле с reverse proxy/кэшем, держите под рукой дизайн кэш-ключей и правила управления кэшем — это помогает быстрее оценивать последствия апгрейда Nginx/модулей и зависимостей:
Краткий FAQ по частым ошибкам
Почему /var/lib/dpkg/lock появляется снова?
Потому что lock — нормальный механизм защиты от параллельных операций. Он должен появляться при любой установке. Проблема не в факте существования lock, а в ситуации, когда он занят «не тем» процессом или остался после аварии.
Когда достаточно только dpkg --configure -a?
Когда пакеты распакованы, но не сконфигурированы, и зависимости в системе уже присутствуют. Если зависимостей не хватает — подключается apt --fix-broken install.
Можно ли игнорировать held packages?
На короткой дистанции — иногда да. Но при обновлениях безопасности удержанные пакеты часто приводят к цепочкам unmet dependencies. Лучше документировать причину удержания и периодически пересматривать список.
Итог
Runbook для APT/dpkg — это про дисциплину: сначала убедиться, что нет активных процессов и блокировок, затем завершить настройку пакетов через dpkg --configure -a, потом выровнять зависимости с apt --fix-broken install, и только после этого возвращаться к обычным установкам. Такой порядок закрывает большинство кейсов с apt broken, unmet dependencies, held packages и ошибками /var/lib/dpkg/lock.
Если вы поддерживаете несколько проектов и хотите меньше «сюрпризов» при обновлениях, удобно разносить окружения по разным тарифам виртуального хостинга или по отдельным VDS — так аварийное лечение пакетов на одном узле не затрагивает остальные.


