♻️ refactor(core): 优化 Homebrew 智能升级管理脚本

* 优化 Shell 环境设置,采用 set -euo pipefail 提升脚本鲁棒性
* 改进路径处理逻辑,动态按需向 PATH 注入 Homebrew 常用路径
* 增强失败隔离机制,实现 Cask 批量失败后仅对过期项精准重试
* 优化临时文件管理,改用临时目录并在退出时自动清理相关资源
* 完善网络容错能力,在 bootstrap 阶段增加 curl 重试与超时限制
* 更新文档说明,同步最新的升级策略、并发控制及错误处理逻辑
* 引入终端动态宽度支持,优化非交互式环境下的输出展示效果
This commit is contained in:
2026-07-17 00:30:07 +08:00
parent 3e7063b30a
commit ff54bffc53
3 changed files with 461 additions and 154 deletions
+60 -34
View File
@@ -3,61 +3,56 @@
set -euo pipefail
REMOTE="https://git.orionc.me/orion/script/raw/branch/main/homebrew/brew-upgrade-manager.sh"
TEMP="$(mktemp "${TMPDIR:-/tmp}/brew-upgrade-manager.XXXXXX.sh")"
TEMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/brew-upgrade-manager.XXXXXX")"
TEMP="$TEMP_DIR/brew-upgrade-manager.sh"
ASKPASS_TEMP="$TEMP_DIR/brewup-askpass.sh"
KEYCHAIN_SERVICE="${BREWUP_KEYCHAIN_SERVICE:-brewup-sudo-password}"
ASKPASS_TEMP="$(mktemp "${TMPDIR:-/tmp}/brewup-askpass.XXXXXX.sh")"
CURRENT_USER="${USER:-$(id -un)}"
cleanup() {
rm -f "$TEMP" "$ASKPASS_TEMP"
rmdir "$TEMP_DIR" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
on_interrupt() {
exit 130
}
on_terminate() {
exit 143
}
trap cleanup EXIT
trap on_interrupt INT
trap on_terminate TERM
PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin"
export PATH
setup_sudo_askpass() {
cat > "$ASKPASS_TEMP" <<'EOF'
#!/usr/bin/env bash
exec /usr/bin/security find-generic-password -a "${USER:-$(id -un)}" -s "${BREWUP_KEYCHAIN_SERVICE:-brewup-sudo-password}" -w
EOF
chmod 700 "$ASKPASS_TEMP"
export SUDO_ASKPASS="$ASKPASS_TEMP"
export BREWUP_KEYCHAIN_SERVICE="$KEYCHAIN_SERVICE"
if ! /usr/bin/security find-generic-password -a "$USER" -s "$KEYCHAIN_SERVICE" -w >/dev/null 2>&1; then
printf "首次使用:请输入一次 sudo 密码,将保存到 macOS Keychain"
IFS= read -r -s BREWUP_SUDO_PASSWORD
printf "\n"
/usr/bin/security add-generic-password -U -a "$USER" -s "$KEYCHAIN_SERVICE" -w "$BREWUP_SUDO_PASSWORD" >/dev/null
unset BREWUP_SUDO_PASSWORD
fi
echo "正在通过 Keychain 准备 sudo 凭据..."
if ! sudo -A -v; then
echo "Keychain 中的 sudo 密码不可用,请删除后重新保存:" >&2
echo " security delete-generic-password -a \"$USER\" -s \"$KEYCHAIN_SERVICE\"" >&2
exit 1
fi
}
setup_sudo_askpass
echo "正在下载远程脚本..."
download_retries="${BREWUP_DOWNLOAD_RETRIES:-3}"
download_retry_delay="${BREWUP_DOWNLOAD_RETRY_DELAY_SECONDS:-2}"
connect_timeout="${BREWUP_CONNECT_TIMEOUT_SECONDS:-15}"
speed_time="${BREWUP_LOW_SPEED_TIME_SECONDS:-30}"
[[ "$download_retries" =~ ^[1-9][0-9]*$ ]] || download_retries=3
[[ "$download_retry_delay" =~ ^[0-9]+$ ]] || download_retry_delay=2
[[ "$connect_timeout" =~ ^[1-9][0-9]*$ ]] || connect_timeout=15
[[ "$speed_time" =~ ^[1-9][0-9]*$ ]] || speed_time=30
curl_retry_all_errors=()
if curl --help all 2>/dev/null | grep -q -- '--retry-all-errors'; then
curl_retry_all_errors+=(--retry-all-errors)
fi
echo "正在下载远程脚本..."
curl -f -sSL \
--connect-timeout "$connect_timeout" \
--speed-limit 1024 \
--speed-time "$speed_time" \
--retry "$download_retries" \
--retry-delay "$download_retry_delay" \
"${curl_retry_all_errors[@]}" \
"$REMOTE" -o "$TEMP"
chmod 600 "$TEMP"
[[ -s "$TEMP" ]] || { echo "远程脚本为空,已停止执行。" >&2; exit 1; }
if [[ -n "${BREWUP_SHA256:-}" ]]; then
echo "正在校验脚本 SHA256..."
@@ -71,11 +66,42 @@ if [[ -n "${BREWUP_SHA256:-}" ]]; then
fi
fi
bash -n "$TEMP"
if [[ "${BREWUP_DEBUG:-}" == "1" ]]; then
if [[ "${BREWUP_DEBUG:-0}" == "1" ]]; then
echo "Downloaded script first line:"
head -n 1 "$TEMP"
fi
export COLUMNS="130"
setup_sudo_askpass() {
cat > "$ASKPASS_TEMP" <<'EOF'
#!/usr/bin/env bash
exec /usr/bin/security find-generic-password \
-a "${BREWUP_KEYCHAIN_ACCOUNT:-${USER:-$(id -un)}}" \
-s "${BREWUP_KEYCHAIN_SERVICE:-brewup-sudo-password}" -w
EOF
chmod 700 "$ASKPASS_TEMP"
export SUDO_ASKPASS="$ASKPASS_TEMP"
export BREWUP_KEYCHAIN_SERVICE="$KEYCHAIN_SERVICE"
export BREWUP_KEYCHAIN_ACCOUNT="$CURRENT_USER"
if ! /usr/bin/security find-generic-password -a "$CURRENT_USER" -s "$KEYCHAIN_SERVICE" -w >/dev/null 2>&1; then
printf "首次使用:请输入一次 sudo 密码,将保存到 macOS Keychain"
IFS= read -r -s BREWUP_SUDO_PASSWORD
printf '\n'
/usr/bin/security add-generic-password -U -a "$CURRENT_USER" -s "$KEYCHAIN_SERVICE" -w "$BREWUP_SUDO_PASSWORD" >/dev/null
unset BREWUP_SUDO_PASSWORD
fi
echo "正在通过 Keychain 准备 sudo 凭据..."
if ! sudo -A -v; then
echo "Keychain 中的 sudo 密码不可用,请删除后重新保存:" >&2
echo " security delete-generic-password -a \"$CURRENT_USER\" -s \"$KEYCHAIN_SERVICE\"" >&2
exit 1
fi
}
setup_sudo_askpass
export COLUMNS="${COLUMNS:-130}"
bash "$TEMP" "$@"