From bcb2fddb2e4f73f9d9ebf63c9a7acae75fa6b13f Mon Sep 17 00:00:00 2001 From: loca1h0st Date: Thu, 8 Jan 2026 12:24:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0Linux=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E8=84=9A=E6=9C=AC=E5=B9=82=E7=AD=89=E6=80=A7=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + scripts/deploy.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 370acad13..48e3630f9 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,7 @@ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force - ⚠️ 请妥善保存脚本输出的**管理员令牌**(Admin Token),这是登录后台的唯一凭证! - ⚠️ Windows 用户:如果未安装 Docker Desktop,脚本会自动打开下载页面 +- ⚠️ 软件更新:请参考 `Docker Compose 启动章节`,deploy脚本仅用于首次部署,并不用于更新软件 (环境限制,目前仅暂在 Linux 安装脚本确保了部署幂等性,未覆盖 Powershell 脚本) ### 三步启动(Docker Compose) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index ea39c350f..a801e69d3 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -47,6 +47,7 @@ DIR_ARG="" DOMAIN_ARG="" ENABLE_CADDY=false NON_INTERACTIVE=false +FORCE_REINSTALL=false show_help() { cat << EOF @@ -62,6 +63,7 @@ Options: --domain Domain for Caddy HTTPS (enables Caddy automatically) --enable-caddy Enable Caddy reverse proxy without HTTPS (HTTP only) -y, --yes Non-interactive mode (skip prompts, use defaults) + -f, --force Force reinstall (remove existing installation) -h, --help Show this help message Examples: @@ -128,6 +130,10 @@ parse_args() { NON_INTERACTIVE=true shift ;; + -f|--force) + FORCE_REINSTALL=true + shift + ;; -h|--help) show_help exit 0 @@ -218,6 +224,90 @@ detect_os() { log_info "Detected OS: $OS_TYPE" } +check_existing_installation() { + log_info "Checking for existing installation..." + + local installation_found=false + local existing_containers=() + + # Check if deployment directory exists with key files + if [[ -d "$DEPLOY_DIR" ]]; then + if [[ -f "$DEPLOY_DIR/docker-compose.yaml" ]] || [[ -f "$DEPLOY_DIR/.env" ]]; then + installation_found=true + log_warning "Found existing installation at: $DEPLOY_DIR" + fi + fi + + # Check for running containers with our naming pattern + if command -v docker &> /dev/null; then + while IFS= read -r container; do + existing_containers+=("$container") + done < <(docker ps -a --filter "name=claude-code-hub-" --format "{{.Names}}" 2>/dev/null) + + if [[ ${#existing_containers[@]} -gt 0 ]]; then + installation_found=true + log_warning "Found existing Docker containers:" + for container in "${existing_containers[@]}"; do + echo " - $container" + done + fi + fi + + # If installation found and not forcing reinstall, abort + if [[ "$installation_found" == true ]] && [[ "$FORCE_REINSTALL" != true ]]; then + echo "" + log_error "Claude Code Hub is already installed on this system!" + echo "" + echo -e "${YELLOW}To manage your existing installation:${NC}" + echo -e " View logs: ${BLUE}cd $DEPLOY_DIR && docker compose logs -f${NC}" + echo -e " Stop: ${BLUE}cd $DEPLOY_DIR && docker compose down${NC}" + echo -e " Restart: ${BLUE}cd $DEPLOY_DIR && docker compose restart${NC}" + echo "" + echo -e "${YELLOW}To completely remove and reinstall:${NC}" + echo -e " 1. Stop services: ${BLUE}cd $DEPLOY_DIR && docker compose down -v${NC}" + echo -e " 2. Remove directory: ${BLUE}rm -rf $DEPLOY_DIR${NC}" + echo -e " 3. Re-run this script" + echo "" + echo -e "${YELLOW}Or use the --force flag to automatically remove and reinstall:${NC}" + echo -e " ${BLUE}$0 --force${NC}" + echo "" + exit 1 + fi + + # If forcing reinstall, clean up existing installation + if [[ "$installation_found" == true ]] && [[ "$FORCE_REINSTALL" == true ]]; then + log_warning "Force reinstall enabled. Removing existing installation..." + + # Stop and remove containers + if [[ ${#existing_containers[@]} -gt 0 ]]; then + log_info "Stopping and removing existing containers..." + if [[ -d "$DEPLOY_DIR" ]] && [[ -f "$DEPLOY_DIR/docker-compose.yaml" ]]; then + cd "$DEPLOY_DIR" + if docker compose version &> /dev/null; then + docker compose down -v 2>/dev/null || true + else + docker-compose down -v 2>/dev/null || true + fi + fi + + # Force remove any remaining containers + for container in "${existing_containers[@]}"; do + docker rm -f "$container" 2>/dev/null || true + done + fi + + # Remove deployment directory + if [[ -d "$DEPLOY_DIR" ]]; then + log_info "Removing deployment directory: $DEPLOY_DIR" + rm -rf "$DEPLOY_DIR" + fi + + log_success "Existing installation removed successfully" + else + log_success "No existing installation found. Proceeding with fresh installation..." + fi +} + select_branch() { # Skip if branch already set via CLI or non-interactive mode if [[ -n "$BRANCH_ARG" ]]; then @@ -748,10 +838,13 @@ main() { print_header detect_os - + # Apply CLI overrides after OS detection (for deploy dir) validate_inputs - + + # Check for existing installation before proceeding + check_existing_installation + if ! check_docker; then log_warning "Docker is not installed. Attempting to install..." install_docker