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:
+44
-3
@@ -34,6 +34,37 @@ require_root() {
|
|||||||
fi
|
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 正在跑)
|
# 等待 apt/dpkg 锁(常见:unattended-upgrades 正在跑)
|
||||||
wait_for_apt_lock() {
|
wait_for_apt_lock() {
|
||||||
local max_wait="${1:-600}"
|
local max_wait="${1:-600}"
|
||||||
@@ -41,6 +72,7 @@ wait_for_apt_lock() {
|
|||||||
local lock_frontend="/var/lib/dpkg/lock-frontend"
|
local lock_frontend="/var/lib/dpkg/lock-frontend"
|
||||||
local lock_dpkg="/var/lib/dpkg/lock"
|
local lock_dpkg="/var/lib/dpkg/lock"
|
||||||
local lock_lists="/var/lib/apt/lists/lock"
|
local lock_lists="/var/lib/apt/lists/lock"
|
||||||
|
local tried_stop=0
|
||||||
|
|
||||||
if ! command -v apt-get >/dev/null 2>&1; then
|
if ! command -v apt-get >/dev/null 2>&1; then
|
||||||
return 0
|
return 0
|
||||||
@@ -69,13 +101,22 @@ wait_for_apt_lock() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [[ "${waited}" -eq 0 ]]; then
|
if [[ "${waited}" -eq 0 ]]; then
|
||||||
log "检测到 apt/dpkg 正被占用(多为 unattended-upgrades),等待释放…"
|
log "检测到 apt/dpkg 正被占用(多为重启后的 unattended-upgrades),等待释放…"
|
||||||
log "可另开终端查看: ps aux | grep -E 'unattended|apt|dpkg'"
|
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
|
elif [[ $((waited % 60)) -eq 0 ]]; then
|
||||||
log "仍在等待 apt 锁…已等 ${waited}s / ${max_wait}s"
|
log "仍在等待 apt 锁…已等 ${waited}s / ${max_wait}s"
|
||||||
|
_apt_lock_holders | while IFS= read -r line; do log " ${line}"; done
|
||||||
fi
|
fi
|
||||||
if [[ "${waited}" -ge "${max_wait}" ]]; then
|
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
|
fi
|
||||||
sleep 5
|
sleep 5
|
||||||
waited=$((waited + 5))
|
waited=$((waited + 5))
|
||||||
|
|||||||
Reference in New Issue
Block a user