Improve apt-lock wait: stop unattended-upgrades during deploy.

Shows lock holders and optionally stops auto-upgrade so Node install is not stuck after reboot.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-29 21:29:38 +08:00
parent 17ba41923a
commit 9ec0cacf45
+44 -3
View File
@@ -34,6 +34,37 @@ require_root() {
fi
}
# 打印当前占用 apt 的进程,便于排查
_apt_lock_holders() {
ps -eo pid,cmd 2>/dev/null | grep -E '[u]nattended-upgr|[a]pt-get|[a]pt |[d]pkg ' | head -n 8 || true
if command -v fuser >/dev/null 2>&1; then
fuser -v /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock /var/lib/apt/lists/lock 2>&1 | head -n 12 || true
fi
}
# 部署期间临时停自动升级(重启后常立刻再跑,占锁很久)
_stop_auto_apt_for_deploy() {
if [[ "${APT_STOP_AUTO:-1}" != "1" ]]; then
return 0
fi
if command -v systemctl >/dev/null 2>&1; then
log "临时停止 unattended-upgrades / apt-daily,避免占锁…"
systemctl stop unattended-upgrades.service 2>/dev/null || true
systemctl stop apt-daily.service apt-daily-upgrade.service 2>/dev/null || true
systemctl kill --kill-who=all unattended-upgrades.service 2>/dev/null || true
fi
# 若仍卡死且 APT_FORCE_UNLOCK=1,才强杀(默认不杀,避免打断半截升级)
if [[ "${APT_FORCE_UNLOCK:-0}" == "1" ]]; then
log "APT_FORCE_UNLOCK=1:结束残留 apt/dpkg 进程…"
pkill -9 -x unattended-upgr 2>/dev/null || true
pkill -9 -x apt-get 2>/dev/null || true
pkill -9 -x apt 2>/dev/null || true
pkill -9 -x dpkg 2>/dev/null || true
sleep 2
dpkg --configure -a 2>/dev/null || true
fi
}
# 等待 apt/dpkg 锁(常见:unattended-upgrades 正在跑)
wait_for_apt_lock() {
local max_wait="${1:-600}"
@@ -41,6 +72,7 @@ wait_for_apt_lock() {
local lock_frontend="/var/lib/dpkg/lock-frontend"
local lock_dpkg="/var/lib/dpkg/lock"
local lock_lists="/var/lib/apt/lists/lock"
local tried_stop=0
if ! command -v apt-get >/dev/null 2>&1; then
return 0
@@ -69,13 +101,22 @@ wait_for_apt_lock() {
return 0
fi
if [[ "${waited}" -eq 0 ]]; then
log "检测到 apt/dpkg 正被占用(多为 unattended-upgrades),等待释放…"
log "可另开终端查看: ps aux | grep -E 'unattended|apt|dpkg'"
log "检测到 apt/dpkg 正被占用(多为重启后的 unattended-upgrades),等待释放…"
log "占用进程:"
_apt_lock_holders | while IFS= read -r line; do log " ${line}"; done
log "可另开终端: ps aux | grep -E 'unattended|apt|dpkg'"
elif [[ "${tried_stop}" -eq 0 && "${waited}" -ge 15 ]]; then
# 等约 15s 仍占用:停自动升级服务(不杀半截 dpkg,除非 APT_FORCE_UNLOCK=1
tried_stop=1
_stop_auto_apt_for_deploy
elif [[ $((waited % 60)) -eq 0 ]]; then
log "仍在等待 apt 锁…已等 ${waited}s / ${max_wait}s"
_apt_lock_holders | while IFS= read -r line; do log " ${line}"; done
fi
if [[ "${waited}" -ge "${max_wait}" ]]; then
die "等待 apt 锁超时(${max_wait}s)。请稍后再跑一键部署,或手动: kill 结束后再执行 manage.sh"
log "超时前占用进程:"
_apt_lock_holders | while IFS= read -r line; do log " ${line}"; done
die "等待 apt 锁超时(${max_wait}s)。可手动: systemctl stop unattended-upgrades; 或 APT_FORCE_UNLOCK=1 bash manage.sh"
fi
sleep 5
waited=$((waited + 5))