Files
ECShopX/install.sh
2026-03-30 13:34:31 +08:00

429 lines
14 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 远程一键安装脚本模板
# 用法: curl -fsSL https://shopex.cn/install.sh | bash
set -e
REPO_URL="${REPO_URL:-https://gitee.com/ShopeX/ECShopX.git}"
# 终端颜色(无 GUM 时使用,避免未定义变量)
ERROR='\033[0;31m'
SUCCESS='\033[0;32m'
NC='\033[0m'
# ---------------------------------------------------------------------------
# UI 与通用辅助函数
# ---------------------------------------------------------------------------
ui_error() {
local msg="$*"
if [[ -n "$GUM" ]]; then
"$GUM" log --level error "$msg"
else
echo -e "${ERROR}${NC} ${msg}"
fi
}
ui_success() {
local msg="$*"
if [[ -n "$GUM" ]]; then
local mark
mark="$("$GUM" style --foreground "#00e5cc" --bold "✓")"
echo "${mark} ${msg}"
else
echo -e "${SUCCESS}${NC} ${msg}"
fi
}
ui_info() {
local msg="$*"
if [[ -n "${GUM:-}" ]]; then
"$GUM" log --level info "$msg"
else
echo "[install] ${msg}"
fi
}
is_root() {
[[ "$(id -u)" -eq 0 ]]
}
require_sudo() {
if [[ "$OS" != "linux" ]]; then
return 0
fi
if is_root; then
return 0
fi
if command -v sudo &> /dev/null; then
if ! sudo -n true >/dev/null 2>&1; then
ui_info "需要管理员权限,请输入密码"
sudo -v
fi
return 0
fi
ui_error "Linux 下安装需要 sudo当前系统未找到 sudo"
echo " 请先安装 sudo 或使用 root 用户重新运行。"
exit 1
}
run_quiet_step() {
local desc="$1"
shift
ui_info "$desc..."
if "$@" >/dev/null 2>&1; then
return 0
fi
echo "[install] 步骤失败,输出如下:" >&2
if ! "$@"; then
ui_error "步骤失败: $desc"
exit 1
fi
}
# ---------------------------------------------------------------------------
# 系统检测(结果写入全局 OS
# ---------------------------------------------------------------------------
OS="unknown"
detect_os_or_die() {
if [[ "$OSTYPE" == "darwin"* ]]; then
OS="macos"
elif [[ "$OSTYPE" == "linux-gnu"* ]] || [[ -n "${WSL_DISTRO_NAME:-}" ]]; then
OS="linux"
fi
if [[ "$OS" == "unknown" ]]; then
ui_error "不支持的操作系统"
echo "本安装脚本仅支持 macOS 与 Linux含 WSL。"
echo "Windows 请使用: iwr -useb https://openclaw.ai/install.ps1 | iex"
exit 1
fi
ui_success "已检测系统: $OS"
}
# ---------------------------------------------------------------------------
# Homebrew仅 macOS供 Git/Docker 使用,避免依赖 Xcode 命令行工具)
# ---------------------------------------------------------------------------
ensure_homebrew() {
[[ "$OS" != "macos" ]] && return 0
if command -v brew &>/dev/null; then
eval "$(brew shellenv)" 2>/dev/null || true
return 0
fi
echo "[install] 未检测到 Homebrew正在自动安装后续 Git/Docker 将由此安装,无需 Xcode..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
if ! command -v brew &>/dev/null; then
ui_error "Homebrew 安装后未找到 brew 命令,请重新打开终端或执行: eval \"\$(/opt/homebrew/bin/brew shellenv)\" 后重试"
exit 1
fi
ui_success "Homebrew 已安装"
}
# ---------------------------------------------------------------------------
# Git 安装(兼容 macos / linux 多包管理器macOS 使用 Homebrew 安装以避开 Xcode
# ---------------------------------------------------------------------------
install_git() {
if [[ "$OS" == "macos" ]]; then
ensure_homebrew
run_quiet_step "正在安装 Git通过 Homebrew无需 Xcode" brew install git
eval "$(brew shellenv)" 2>/dev/null || true
elif [[ "$OS" == "linux" ]]; then
require_sudo
if command -v apt-get &>/dev/null; then
if is_root; then
run_quiet_step "正在更新软件包索引" apt-get update -qq
run_quiet_step "正在安装 Git" apt-get install -y -qq git
else
run_quiet_step "正在更新软件包索引" sudo apt-get update -qq
run_quiet_step "正在安装 Git" sudo apt-get install -y -qq git
fi
elif command -v dnf &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Git" dnf install -y -q git
else
run_quiet_step "正在安装 Git" sudo dnf install -y -q git
fi
elif command -v yum &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Git" yum install -y -q git
else
run_quiet_step "正在安装 Git" sudo yum install -y -q git
fi
elif command -v zypper &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Git" zypper install -y git
else
run_quiet_step "正在安装 Git" sudo zypper install -y git
fi
else
ui_error "未检测到可用包管理器,请手动安装 Git: https://git-scm.com/downloads"
exit 1
fi
else
ui_error "无法识别操作系统,请手动安装 Git: https://git-scm.com/downloads"
exit 1
fi
ui_success "Git 已安装"
}
# ---------------------------------------------------------------------------
# Docker 安装(兼容 macos / linux 多包管理器)
# ---------------------------------------------------------------------------
install_docker() {
if [[ "$OS" == "macos" ]]; then
ensure_homebrew
run_quiet_step "正在安装 Docker Desktop" brew install --cask docker
ui_success "Docker Desktop 已安装,请从应用程序中启动并完成初始化"
return 0
fi
if [[ "$OS" != "linux" ]]; then
ui_error "无法在此系统自动安装 Docker请参考: https://docs.docker.com/engine/install/"
exit 1
fi
require_sudo
# 确保有 curlget.docker.com 或后续步骤可能需要)
if ! command -v curl &>/dev/null; then
if command -v apt-get &>/dev/null; then
if is_root; then
run_quiet_step "正在更新软件包索引" apt-get update -qq
run_quiet_step "正在安装 curl" apt-get install -y -qq curl
else
run_quiet_step "正在更新软件包索引" sudo apt-get update -qq
run_quiet_step "正在安装 curl" sudo apt-get install -y -qq curl
fi
elif command -v dnf &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 curl" dnf install -y -q curl
else
run_quiet_step "正在安装 curl" sudo dnf install -y -q curl
fi
elif command -v yum &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 curl" yum install -y -q curl
else
run_quiet_step "正在安装 curl" sudo yum install -y -q curl
fi
else
ui_error "需要 curl 来安装 Docker请先安装 curl"
exit 1
fi
fi
# Linux: 优先使用包管理器,否则使用官方安装脚本
if command -v apt-get &>/dev/null; then
if is_root; then
run_quiet_step "正在更新软件包索引" apt-get update -qq
run_quiet_step "正在安装 Docker" apt-get install -y -qq docker.io
else
run_quiet_step "正在更新软件包索引" sudo apt-get update -qq
run_quiet_step "正在安装 Docker" sudo apt-get install -y -qq docker.io
fi
elif command -v dnf &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Docker" dnf install -y -q docker
else
run_quiet_step "正在安装 Docker" sudo dnf install -y -q docker
fi
elif command -v yum &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Docker" yum install -y -q docker
else
run_quiet_step "正在安装 Docker" sudo yum install -y -q docker
fi
elif command -v zypper &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Docker" zypper install -y docker
else
run_quiet_step "正在安装 Docker" sudo zypper install -y docker
fi
else
run_quiet_step "正在通过 get.docker.com 安装 Docker" sh -c "curl -fsSL https://get.docker.com | sh"
fi
# 将当前用户加入 docker 组(非 root 时)
if ! is_root; then
local who="${SUDO_USER:-$(whoami)}"
if getent group docker &>/dev/null; then
run_quiet_step "正在将用户加入 docker 组" sudo usermod -aG docker "$who" || true
fi
fi
# 启动 Docker 服务Linux
if command -v systemctl &>/dev/null; then
if is_root; then
systemctl start docker 2>/dev/null || true
systemctl enable docker 2>/dev/null || true
else
sudo systemctl start docker 2>/dev/null || true
sudo systemctl enable docker 2>/dev/null || true
fi
elif command -v service &>/dev/null; then
if is_root; then
service docker start 2>/dev/null || true
else
sudo service docker start 2>/dev/null || true
fi
fi
ui_success "Docker 已安装。若当前用户需免 sudo 运行 docker请重新登录或执行: newgrp docker"
}
# ---------------------------------------------------------------------------
# Docker Compose 检测与安装dev-setup.sh 依赖)
# ---------------------------------------------------------------------------
has_docker_compose() {
command -v docker-compose &>/dev/null || docker compose version &>/dev/null 2>&1
}
install_docker_compose() {
if [[ "$OS" == "macos" ]]; then
ensure_homebrew
run_quiet_step "正在安装 Docker Compose" brew install docker-compose
ui_success "Docker Compose 已安装"
return 0
fi
if [[ "$OS" != "linux" ]]; then
return 0
fi
require_sudo
if command -v apt-get &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Docker Compose 插件" apt-get install -y -qq docker-compose-plugin
else
run_quiet_step "正在安装 Docker Compose 插件" sudo apt-get install -y -qq docker-compose-plugin
fi
elif command -v dnf &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Docker Compose" dnf install -y -q docker-compose-plugin
else
run_quiet_step "正在安装 Docker Compose" sudo dnf install -y -q docker-compose-plugin
fi
elif command -v yum &>/dev/null; then
if is_root; then
run_quiet_step "正在安装 Docker Compose" yum install -y -q docker-compose-plugin
else
run_quiet_step "正在安装 Docker Compose" sudo yum install -y -q docker-compose-plugin
fi
else
if is_root; then
run_quiet_step "正在安装 Docker Compose 独立版" sh -c 'curl -fsSL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose'
else
run_quiet_step "正在安装 Docker Compose 独立版" sudo sh -c 'curl -fsSL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose'
fi
fi
ui_success "Docker Compose 已安装"
}
ensure_docker_compose() {
if has_docker_compose; then
ui_success "已检测到 Docker Compose"
return 0
fi
install_docker_compose
}
# macOS/usr/bin/git 有时是 Xcode 占位,会弹窗或要求装 CLT真正可用的 git 可直接跳过 brew install
macos_git_usable() {
command -v git &>/dev/null || return 1
local ver
ver="$(git --version 2>&1)" || return 1
case "$ver" in
*xcode-select*|*xcrun:*error*|*"command line tools"*|*"开发者工具"*) return 1 ;;
esac
[[ "$ver" == git\ version* ]] || return 1
return 0
}
ensure_git() {
if [[ "$OS" == "macos" ]]; then
if macos_git_usable; then
ui_success "已检测到 Git: $(git --version 2>&1 | head -n1)"
return 0
fi
if command -v brew &>/dev/null; then
eval "$(brew shellenv)" 2>/dev/null || true
if brew list git &>/dev/null 2>&1; then
ui_success "已检测到 GitHomebrew"
return 0
fi
fi
# 无可用 git 或 brew 下未安装 git通过 Homebrew 安装(避免依赖 Xcode
install_git
return 0
fi
if command -v git &>/dev/null; then
ui_success "已检测到 Git"
return 0
fi
install_git
}
ensure_docker() {
if command -v docker &>/dev/null; then
ui_success "已检测到 Docker: $(docker --version)"
return 0
fi
install_docker
}
# ---------------------------------------------------------------------------
# 主流程
# ---------------------------------------------------------------------------
detect_os_or_die
echo "[install] 检查依赖: Git、Docker、Docker Compose (OS=$OS)..."
[[ "$OS" == "macos" ]] && ensure_homebrew
ensure_git
ensure_docker
ensure_docker_compose
echo ""
echo "[install] 当前目录: $(pwd)"
confirm="n"
if [ -e /dev/tty ]; then
read -r -p "是否在当前目录安装?(y/n): " confirm </dev/tty
fi
case "$confirm" in
[yY]|[yY][eE][sS]) ;;
*)
echo "[install] 请先切换到目标目录后再重新运行本脚本。"
echo " 例如: cd /path/to/your/project && curl -fsSL https://shopex.cn/install.sh | bash"
exit 1
;;
esac
INSTALL_DIR="$(pwd)"
# 仓库目录名(从 REPO_URL 解析,如 ECShopX
REPO_DIR="${REPO_DIR:-$(basename "$REPO_URL" .git)}"
echo "[install] 安装目录: $INSTALL_DIR"
echo ""
if [ ! -d "$REPO_DIR/.git" ]; then
echo "[install] 克隆仓库..."
git clone --depth 1 "$REPO_URL"
cd "$REPO_DIR"
else
echo "[install] 已存在仓库,拉取最新..."
cd "$REPO_DIR"
git pull --rebase || true
fi
if [ -f "dev-setup.sh" ]; then
echo "[install] 运行 dev-setup.sh..."
bash dev-setup.sh
else
echo "[install] 完成。未找到 dev-setup.sh请手动进入 $REPO_DIR 执行后续步骤。"
fi