Короткий ответ

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.

Возможные причины

  1. Параллельный apt администратора.
  2. unattended-upgrades.service / apt-daily-upgrade.
  3. needrestart ждёт интерактива (реже в lock, чаще tty).
  4. Процесс убит, lock остался.
  5. Зависший dpkg на postinst (сеть, disk).
  6. 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 busy

busy при пустом 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.