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 <cursoragent@cursor.com>
This commit is contained in:
+66
-7
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-29 — 部署:等待 apt 锁(unattended-upgrades)
|
||||
|
||||
### 变更
|
||||
|
||||
1. 一键部署装 Node/系统包前等待 `dpkg`/`apt` 锁释放,避免新机撞上自动升级报错退出。
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-29 — 文档:云服务器配置选择说明
|
||||
|
||||
### 变更
|
||||
|
||||
Reference in New Issue
Block a user