Commit 3e41c4a1 authored by BO ZHANG's avatar BO ZHANG 🏀
Browse files

feat(bootstrap): 添加强制终止包管理器选项并优化安装逻辑

parent 3b44f1f5
Loading
Loading
Loading
Loading
+129 −36
Original line number Diff line number Diff line
@@ -13,10 +13,33 @@ set -euo pipefail
#   - docker
#   - docker compose plugin
#
# Options:
#   -f, --force            Kill running apt/dpkg related processes before continuing
#
# Example:
#   bash tools/bootstrap.sh
#   bash tools/bootstrap.sh -f
#   sudo USER="$USER" bash tools/bootstrap.sh

FORCE_KILL_PACKAGE_MANAGER=0
while [[ $# -gt 0 ]]; do
  case "$1" in
    -f|--force)
      FORCE_KILL_PACKAGE_MANAGER=1
      shift
      ;;
    -h|--help)
      sed -n '1,22p' "$0" | sed 's/^# \{0,1\}//'
      exit 0
      ;;
    *)
      echo "Unknown option: $1" >&2
      echo "Use -h for help." >&2
      exit 1
      ;;
  esac
done

if [[ "${EUID}" -ne 0 ]]; then
  echo "Please run as root (for example: sudo bash tools/bootstrap.sh)" >&2
  exit 1
@@ -45,26 +68,94 @@ if [[ -z "${TARGET_USER}" || "${TARGET_USER}" == "root" ]]; then
  TARGET_USER=""
fi

list_package_manager_processes() {
  ps -eo pid=,args= | awk -v self="$$" '
    $1 != self &&
    $0 !~ /awk/ &&
    $0 !~ /ps -eo/ &&
    ($0 ~ /(^|[[:space:]])apt([[:space:]]|$)/ ||
     $0 ~ /apt-get/ ||
     $0 ~ /(^|[[:space:]])dpkg([[:space:]]|$)/ ||
     $0 ~ /unattended-upgrade/) {
      print
    }
  '
}

ensure_package_manager_available() {
  local blocking pids
  blocking="$(list_package_manager_processes)"
  if [[ -z "${blocking}" ]]; then
    return 0
  fi

  if [[ "${FORCE_KILL_PACKAGE_MANAGER}" -ne 1 ]]; then
    echo "Another apt/dpkg process is running. Please wait for it to finish and retry, or rerun with -f." >&2
    echo "${blocking}" >&2
    exit 1
  fi

  echo "Force-killing running apt/dpkg processes before continuing:" >&2
  echo "${blocking}" >&2
  pids="$(printf '%s\n' "${blocking}" | awk '{print $1}')"
  if [[ -n "${pids}" ]]; then
    kill ${pids} 2>/dev/null || true
    sleep 2
    blocking="$(list_package_manager_processes)"
    if [[ -n "${blocking}" ]]; then
      pids="$(printf '%s\n' "${blocking}" | awk '{print $1}')"
      kill -9 ${pids} 2>/dev/null || true
      sleep 1
    fi
  fi

  blocking="$(list_package_manager_processes)"
  if [[ -n "${blocking}" ]]; then
    echo "Failed to clear apt/dpkg processes:" >&2
    echo "${blocking}" >&2
    exit 1
  fi
}

has_command() {
  command -v "$1" >/dev/null 2>&1
}

echo "Bootstrapping Ubuntu ${VERSION_ID} control host..."

export DEBIAN_FRONTEND=noninteractive

base_packages=()
has_command curl || base_packages+=(curl)
has_command git || base_packages+=(git)
has_command make || base_packages+=(make)
has_command python3 || base_packages+=(python3)
dpkg -s python3-pip >/dev/null 2>&1 || base_packages+=(python3-pip)
has_command rsync || base_packages+=(rsync)
dpkg -s ca-certificates >/dev/null 2>&1 || base_packages+=(ca-certificates)
dpkg -s gnupg >/dev/null 2>&1 || base_packages+=(gnupg)
dpkg -s lsb-release >/dev/null 2>&1 || base_packages+=(lsb-release)
dpkg -s software-properties-common >/dev/null 2>&1 || base_packages+=(software-properties-common)

if [[ ${#base_packages[@]} -gt 0 ]]; then
  ensure_package_manager_available
  apt-get update
  apt-get install -y --no-install-recommends "${base_packages[@]}"
else
  echo "Base packages already available."
fi

if ! has_command ansible-playbook; then
  ensure_package_manager_available
  apt-get update
apt-get install -y --no-install-recommends \
  ca-certificates \
  curl \
  git \
  gnupg \
  lsb-release \
  make \
  python3 \
  python3-pip \
  rsync \
  software-properties-common

# Install ansible-playbook from Ubuntu packages.
  apt-get install -y --no-install-recommends ansible-core
else
  echo "ansible-playbook already available."
fi

if has_command docker && docker compose version >/dev/null 2>&1; then
  echo "docker and docker compose already available."
else
  # Install Docker Engine + Compose plugin from Docker's official apt repo.
  install -m 0755 -d /etc/apt/keyrings
  if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then
@@ -78,6 +169,7 @@ echo \
    "deb [arch=${ARCH} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${CODENAME} stable" \
    > /etc/apt/sources.list.d/docker.list

  ensure_package_manager_available
  apt-get update
  apt-get install -y --no-install-recommends \
    containerd.io \
@@ -85,8 +177,9 @@ apt-get install -y --no-install-recommends \
    docker-ce \
    docker-ce-cli \
    docker-compose-plugin
fi

systemctl enable --now docker
has_command docker && systemctl enable --now docker

if [[ -n "${TARGET_USER}" ]]; then
  usermod -aG docker "${TARGET_USER}" || true