From 17ba41923a531830c80a77e29661fa1e71a31606 Mon Sep 17 00:00:00 2001 From: dekun Date: Wed, 29 Jul 2026 21:20:40 +0800 Subject: [PATCH] Wait for apt lock during deploy on fresh Ubuntu hosts. Avoid failing Node install when unattended-upgrades holds dpkg; poll up to 10 minutes then retry. Co-authored-by: Cursor --- deploy/lib/common.sh | 73 +++++++++++++++++++++++++++++++++++++++----- deploy/manage.sh | 17 +++++++++++ docs/更新说明.md | 8 +++++ 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/deploy/lib/common.sh b/deploy/lib/common.sh index b8b94aa..81b5399 100755 --- a/deploy/lib/common.sh +++ b/deploy/lib/common.sh @@ -34,6 +34,64 @@ require_root() { fi } +# 等待 apt/dpkg 锁(常见:unattended-upgrades 正在跑) +wait_for_apt_lock() { + local max_wait="${1:-600}" + local waited=0 + local lock_frontend="/var/lib/dpkg/lock-frontend" + local lock_dpkg="/var/lib/dpkg/lock" + local lock_lists="/var/lib/apt/lists/lock" + + if ! command -v apt-get >/dev/null 2>&1; then + return 0 + fi + + while true; do + local busy=0 + if pgrep -x unattended-upgr >/dev/null 2>&1 \ + || pgrep -x apt-get >/dev/null 2>&1 \ + || pgrep -x apt >/dev/null 2>&1 \ + || pgrep -x dpkg >/dev/null 2>&1; then + busy=1 + fi + # fuser 在有进程占用锁文件时返回 0 + if command -v fuser >/dev/null 2>&1; then + if fuser "${lock_frontend}" >/dev/null 2>&1 \ + || fuser "${lock_dpkg}" >/dev/null 2>&1 \ + || fuser "${lock_lists}" >/dev/null 2>&1; then + busy=1 + fi + fi + if [[ "${busy}" -eq 0 ]]; then + if [[ "${waited}" -gt 0 ]]; then + log "apt 锁已释放,继续安装" + fi + return 0 + fi + if [[ "${waited}" -eq 0 ]]; then + log "检测到 apt/dpkg 正被占用(多为 unattended-upgrades),等待释放…" + log "可另开终端查看: ps aux | grep -E 'unattended|apt|dpkg'" + elif [[ $((waited % 60)) -eq 0 ]]; then + log "仍在等待 apt 锁…已等 ${waited}s / ${max_wait}s" + fi + if [[ "${waited}" -ge "${max_wait}" ]]; then + die "等待 apt 锁超时(${max_wait}s)。请稍后再跑一键部署,或手动: kill 结束后再执行 manage.sh" + fi + sleep 5 + waited=$((waited + 5)) + done +} + +apt_update() { + wait_for_apt_lock + apt-get update -qq +} + +apt_install() { + wait_for_apt_lock + apt-get install -y "$@" +} + detect_server_ip() { local ip="" if command -v hostname >/dev/null 2>&1; then @@ -128,8 +186,8 @@ install_python_runtime() { if ! command -v apt-get >/dev/null 2>&1; then die "非 apt 系统,请手动安装 python3 python3-venv python3-pip" fi - apt-get update -qq - apt-get install -y python3 python3-venv python3-pip + apt_update + apt_install python3 python3-venv python3-pip if ! python_runtime_ok; then die "Python 环境安装后仍不可用,请检查 apt 源" fi @@ -142,10 +200,11 @@ install_node_runtime() { if ! command -v apt-get >/dev/null 2>&1; then die "非 apt 系统,请手动安装 Node.js ${NODE_MAJOR}+" fi - apt-get update -qq - apt-get install -y ca-certificates curl + apt_update + apt_install ca-certificates curl + wait_for_apt_lock curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - - apt-get install -y nodejs + apt_install nodejs if ! node_runtime_ok; then die "Node.js 安装后仍不可用" fi @@ -177,8 +236,8 @@ ensure_base_packages() { fi step "安装基础包: ${need[*]}" export DEBIAN_FRONTEND=noninteractive - apt-get update -qq - apt-get install -y ca-certificates "${need[@]}" + apt_update + apt_install ca-certificates "${need[@]}" } ensure_system_deps() { diff --git a/deploy/manage.sh b/deploy/manage.sh index 0c89f1b..dfff46a 100755 --- a/deploy/manage.sh +++ b/deploy/manage.sh @@ -42,6 +42,23 @@ ensure_git_cli() { fi if command -v apt-get >/dev/null 2>&1; then export DEBIAN_FRONTEND=noninteractive + # 新机常撞 unattended-upgrades 占锁;最多等 10 分钟 + local waited=0 + while pgrep -x unattended-upgr >/dev/null 2>&1 \ + || pgrep -x apt-get >/dev/null 2>&1 \ + || pgrep -x apt >/dev/null 2>&1 \ + || pgrep -x dpkg >/dev/null 2>&1 \ + || { command -v fuser >/dev/null 2>&1 && fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; }; do + if [[ "${waited}" -eq 0 ]]; then + echo "等待 apt 锁释放(unattended-upgrades)…" + fi + if [[ "${waited}" -ge 600 ]]; then + echo "错误: 等待 apt 锁超时,请稍后再试" >&2 + exit 1 + fi + sleep 5 + waited=$((waited + 5)) + done apt-get update -qq apt-get install -y git ca-certificates curl else diff --git a/docs/更新说明.md b/docs/更新说明.md index 528fbe9..236fa62 100644 --- a/docs/更新说明.md +++ b/docs/更新说明.md @@ -5,6 +5,14 @@ --- +## 2026-07-29 — 部署:等待 apt 锁(unattended-upgrades) + +### 变更 + +1. 一键部署装 Node/系统包前等待 `dpkg`/`apt` 锁释放,避免新机撞上自动升级报错退出。 + +--- + ## 2026-07-29 — 文档:云服务器配置选择说明 ### 变更