Короткий ответ
Lock — штатный механизм: два apt не должны писать базу сразу. Снимите PID через lsof/fuser. Если процесс жив и работает — ждите или штатно остановите его (systemctl stop unattended-upgrades), не kill -9 на середине unpack. Если процесса нет, lock остался после kill/OOM/ENOSPC — тогда dpkg --configure -a и только потом удаление stale lock. rm lock первым шагом даёт расхождение status и файлов в /usr.
Хост host.example, пользователь admin.
Симптомы и как отличить
Сообщение:
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (apt-get)Если PID указан — даже не думайте про rm. Если «lock» без процесса — stale или вы не root.
Отличия: 404 репозитория — репо; нет места — диск / inode; unit needrestart — не lock.
Возможные причины
- Параллельный
aptадминистратора. unattended-upgrades.service/apt-daily-upgrade.needrestartждёт интерактива (реже в lock, чаще tty).- Процесс убит, lock остался.
- Зависший
dpkgна postinst (сеть, disk). - NFS
/usr— отдельный кошмар, не этот runbook.
Диагностика
sudo lsof /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock /var/lib/apt/lists/lock /var/cache/apt/archives/lock
sudo fuser -v /var/lib/dpkg/lock-frontend
ps -fp $(sudo fuser /var/lib/dpkg/lock-frontend 2>/dev/null)
systemctl status unattended-upgrades.service apt-daily-upgrade.service --no-pager
df -h /var /usr
df -i /varЖурнал текущего apt:
sudo journalctl -u unattended-upgrades -u apt-daily-upgrade --since 'today' --no-pager | tail -n 80
ls -l /var/log/apt/term.log
sudo tail -n 50 /var/log/apt/term.logСостояние базы:
dpkg --audit
sudo dpkg -CРешение
Сценарий A. Живой нормальный apt
Дождитесь. Смотрите term.log — идёт unpack. Можно:
sudo systemctl stop unattended-upgrades.serviceесли это он и политика позволяет отложить. Не stop посреди linux-image без необходимости.
Сценарий B. Завис на сети/зеркале часами
Зафиксируйте strace не обязательно. TERM один раз:
sudo kill -TERM 1234
sleep 5
ps -p 1234Если жив и не D-state — разбор hang. Если D на диске — зависание.
После смерти процесса:
sudo dpkg --configure -a
sudo apt-get -f installСценарий C. Процесса нет, lock есть
Повторный lsof пустой. Тогда:
sudo dpkg --configure -aЕсли dpkg всё ещё говорит locked — ищите другой lock-файл. Удаление:
sudo rm -f /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock
sudo dpkg --configure -a
sudo apt-get -f installТолько после пустого lsof.
Сценарий D. Interrupted unpack, диск полный
Освободите место, затем --configure -a. Иначе цикл.
Сценарий E. Сломанный postinst
dpkg --configure -a покажет пакет. Читайте /var/lib/dpkg/info/пакет.postinst. Не --force-all первым движением.
Как отличить живой unpack от зомби lock
Живой apt: в ps есть apt-get/apt/dpkg, lsof показывает PID, term.log растёт (watch -n2 'tail -n 3 /var/log/apt/term.log'). Зомби: PID нет, lock-файл есть, term.log не менялся часами, dpkg --audit непустой.
unattended-upgrades держит lock легитимно 5–40 минут на security. Timeout мониторинга 60 с на apt-get update не должен слать SIGKILL.
Если fuser показывает PID в состоянии D на /var — это диск, не «надо rm lock». См. hang и read-only.
Восстановление status из /var/backups/dpkg.status.0 — крайняя мера после копирования текущего status в /root/dpkg.status.broken. Нескольких .0 .1 бывает ротация. Сверяйте дату файла с инцидентом.
На 24.04 apt-daily-upgrade.timer + ручной upgrade админа = ожидание lock. Это нормально: второй процесс пишет Could not get lock и выходит. В скриптах используйте flock или apt-get -o DPkg::Lock::Timeout=60.
lsof может не быть установлен на minimal-сервере. Запасной путь:
sudo fuser -v /var/lib/dpkg/lock-frontend
ls -l /proc/*/fd 2>/dev/null | grep -F dpkg/lockЕсли unattended-upgrades в состоянии activating часами на Could not get lock — он сам жертва другого apt, не наоборот. Найдите того, кто держит frontend.
Не запускайте параллельно apt-get install из двух Ansible play. В роли используйте lock_timeout или serial. Сообщение lock в CI — часто гонка, не «сломан dpkg».
После --configure -a смотрите debconf вопросы: noninteractive с DEBIAN_FRONTEND=noninteractive может оставить пакет в unpacked. Повторите configure с DEBIAN_FRONTEND=readline на консоли, если это консольный сервер и вопрос легитимный (лицензия, restart).
Состояние пакета iF / iU в dpkg -l (вторая буква не i) = полунастроен. --configure -a как раз про них. Если configure падает на postinst из-за сети (скачивание из postinst — плохой пакет), это уже не lock: либо почините сеть/DNS, либо apt-get install --reinstall после зеркала.
Не используйте rm /var/lib/dpkg/updates/* из старых HOWTO: там очередь configure. Пустой каталог updates при живой очереди теряет список операций.
Проверка, что frontend lock свободен циклом:
sudo flock -n /var/lib/dpkg/lock-frontend -c true && echo free || echo busybusy при пустом lsof бывает на NFS-lock — корень не должен быть NFS для /var/lib/dpkg.
Как проверить, что проблема устранена
sudo lsof /var/lib/dpkg/lock-frontend || true
sudo apt-get update
sudo apt-get -f install
dpkg --auditПустой audit, update проходит (модуль репо может быть ещё красный — это не lock).
Если не помогло
dpkg: error: parsing file '/var/lib/dpkg/status'— восстанавливайте из/var/backups/dpkg.status.*, не изобретайте status.- Полунастроенный
linux-image— не reboot до configure; иначе не загружается. - Третий стороной скрипт держит flock в цикле —
ps+systemctl cat.
Профилактика
- Один канал обновлений: либо окно админа, либо unattended, не оба в тот же час без очереди (apt подождёт — это ок).
- Мониторинг
dpkg --audit≠ 0. - Не убивать apt из Zabbix «по таймауту 30 с»: дождитесь
term.logили поднимите порог до десятков минут на security upgrade. - В Ansible/CI один serial на хост и
DPkg::Lock::Timeout, чтобы два play не снимали lock друг другу.
FAQ
Чем lock-frontend отличается от lock?
Frontend (apt) vs низкий dpkg. Apt берёт оба.
kill -9 безопасен?
Нет. Оставляет полураспакованные пакеты. TERM → configure.
Можно ли dpkg --force-overwrite?
Только на конкретный конфликт файлов, не как снятие lock.
unattended-upgrades каждый раз виноват?
Часто да в рабочее утро. Настройте Automatic-Reboot и окна в /etc/apt/apt.conf.d/50unattended-upgrades.
Recovery из status-old
/var/lib/dpkg/status-old — предыдущая копия. Копируйте только понимая diff, после backup текущего status.