diff --git a/deploy.sh b/deploy.sh index eecf55f..afbdacd 100644 --- a/deploy.sh +++ b/deploy.sh @@ -1,9 +1,9 @@ #!/bin/bash # ============================================================ -# frpc-console 一键部署脚本 +# frpc-console 一键部署脚本(Docker 优先) # 支持:Linux x86_64 / ARM64 / ARMv7 -# 自动安装:git / curl / wget / Go / Docker +# 自动安装:git / curl / wget / Docker # # 用法: # ./deploy.sh # 完整交互流程 @@ -40,22 +40,18 @@ WORK_DIR="/tmp/frpc-console-build" DEFAULT_PORT=9300 DEFAULT_DEPLOY_DIR="/opt/frpc-console" IMAGE_NAME="frpc-console" -GO_VERSION="1.25.0" # ---------- 状态变量 ---------- OS="" OS_VERSION="" ARCH="" -GO_ARCH="" HAS_GIT=false HAS_CURL=false HAS_WGET=false -HAS_GO=false HAS_DOCKER=false NEED_INSTALL_GIT=false NEED_INSTALL_CURL=false NEED_INSTALL_WGET=false -NEED_INSTALL_GO=false PORT=${DEFAULT_PORT} DEPLOY_DIR=${DEFAULT_DEPLOY_DIR} DATA_DIR="${DEPLOY_DIR}/data" @@ -136,14 +132,8 @@ detect_os() { detect_arch() { ARCH=$(uname -m) case $ARCH in - x86_64|amd64) - GO_ARCH="amd64" - ;; - aarch64|arm64) - GO_ARCH="arm64" - ;; - armv7l|armhf) - GO_ARCH="armv6l" + x86_64|amd64|aarch64|arm64|armv7l|armhf) + print_success "CPU 架构: $ARCH" ;; *) print_error "不支持的 CPU 架构: $ARCH" @@ -154,33 +144,10 @@ detect_arch() { # ---------- 检测工具 ---------- check_tools() { - if command -v git &> /dev/null; then - HAS_GIT=true - else - NEED_INSTALL_GIT=true - fi - - if command -v curl &> /dev/null; then - HAS_CURL=true - else - NEED_INSTALL_CURL=true - fi - - if command -v wget &> /dev/null; then - HAS_WGET=true - else - NEED_INSTALL_WGET=true - fi - - if command -v go &> /dev/null; then - HAS_GO=true - else - NEED_INSTALL_GO=true - fi - - if command -v docker &> /dev/null; then - HAS_DOCKER=true - fi + command -v git &> /dev/null && HAS_GIT=true || NEED_INSTALL_GIT=true + command -v curl &> /dev/null && HAS_CURL=true || NEED_INSTALL_CURL=true + command -v wget &> /dev/null && HAS_WGET=true || NEED_INSTALL_WGET=true + command -v docker &> /dev/null && HAS_DOCKER=true } # ---------- 检查容器状态 ---------- @@ -200,7 +167,7 @@ print_environment_summary() { echo "" echo -e " ${CYAN}操作系统:${NC} $OS $OS_VERSION" - echo -e " ${CYAN}CPU 架构:${NC} $ARCH → Go 架构: $GO_ARCH" + echo -e " ${CYAN}CPU 架构:${NC} $ARCH" echo "" echo " ${CYAN}必要工具:${NC}" @@ -220,14 +187,6 @@ print_environment_summary() { echo " wget ❌ 未安装 (将自动安装)" fi - echo "" - echo " ${CYAN}Go 环境:${NC}" - if [ "$HAS_GO" = true ]; then - echo -e " go ✅ 已安装 ($(go version | awk '{print $3}'))" - else - echo " go ❌ 未安装 (将自动安装 Go ${GO_VERSION})" - fi - echo "" echo " ${CYAN}Docker 环境:${NC}" if [ "$HAS_DOCKER" = true ]; then @@ -267,12 +226,8 @@ generate_plan() { [ "$NEED_INSTALL_WGET" = true ] && pkgs="${pkgs} wget" PLAN="${PLAN} • 安装必要工具:${pkgs}\n" fi - if [ "$NEED_INSTALL_GO" = true ]; then - PLAN="${PLAN} • 安装 Go ${GO_VERSION}\n" - fi PLAN="${PLAN} • 拉取 frpc-console 源码 (${BRANCH} 分支)\n" - PLAN="${PLAN} • 编译 frpc-console 二进制\n" - PLAN="${PLAN} • 构建 Docker 镜像\n" + PLAN="${PLAN} • 构建 Docker 镜像(源码内编译)\n" if [ "$CONTAINER_EXISTS" = true ]; then PLAN="${PLAN} • 停止并删除旧容器\n" fi @@ -321,12 +276,8 @@ confirm_deploy() { read -r CONFIRM /dev/null; then if ! sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='users';" 2>/dev/null | grep -q "^1$"; then print_warn "数据库文件无效,将删除,由容器全新初始化" @@ -386,6 +336,16 @@ do_deploy() { print_info "数据库文件不存在,跳过备份" fi + # ----- 停止旧容器(提前释放资源)----- + if [ "$CONTAINER_EXISTS" = true ]; then + print_step "停止旧容器..." + if [ "$CONTAINER_RUNNING" = true ]; then + docker stop frpc-console 2>/dev/null || true + fi + docker rm frpc-console 2>/dev/null || true + print_success "旧容器已清理" + fi + # ----- 安装必要工具 ----- if [ "$NEED_INSTALL_GIT" = true ] || [ "$NEED_INSTALL_CURL" = true ] || [ "$NEED_INSTALL_WGET" = true ]; then print_step "安装必要工具..." @@ -424,57 +384,6 @@ do_deploy() { print_success "必要工具安装完成" fi - # ----- 安装 Go ----- - if [ "$NEED_INSTALL_GO" = true ]; then - print_step "安装 Go ${GO_VERSION} (${GO_ARCH})..." - - GO_TMP="/tmp/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" - - if [ -f "$GO_TMP" ]; then - print_info "使用缓存: $GO_TMP" - else - print_info "正在下载..." - MIRRORS=( - "https://mirrors.aliyun.com/golang/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" - "https://mirrors.tuna.tsinghua.edu.cn/golang/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" - "https://golang.google.cn/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" - "https://dl.google.com/go/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" - ) - - DOWNLOADED=false - for MIRROR in "${MIRRORS[@]}"; do - print_info "尝试: $MIRROR" - if curl -# -f -L -o "$GO_TMP" "$MIRROR"; then - print_success "下载成功" - DOWNLOADED=true - break - else - print_warn "失败,尝试下一个镜像..." - rm -f "$GO_TMP" - fi - done - - if [ "$DOWNLOADED" = false ]; then - print_error "所有镜像源均下载失败" - exit 1 - fi - fi - - rm -rf /usr/local/go - tar -C /usr/local -xzf "$GO_TMP" - export PATH=$PATH:/usr/local/go/bin - if [ ! -f /etc/profile.d/go.sh ]; then - echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/go.sh - fi - - /usr/local/go/bin/go env -w GOPROXY=https://goproxy.cn,direct - /usr/local/go/bin/go env -w GOPRIVATE=git.whitetop.xyz - - print_success "Go ${GO_VERSION} (${GO_ARCH}) 安装完成" - fi - - export PATH=$PATH:/usr/local/go/bin - # ----- 拉取代码 ----- print_step "拉取代码..." rm -rf "$WORK_DIR" @@ -483,33 +392,14 @@ do_deploy() { mkdir -p bin static print_success "代码拉取完成" - # ----- 修复 go.mod ----- + # ----- 修复 go.mod(Docker 构建时使用)----- print_step "检查 go.mod..." if grep -q "go 1.2[6-9]" go.mod 2>/dev/null; then print_warn "检测到 go.mod 版本过高,自动降级到 go 1.21" sed -i 's/go 1.2[6-9].*/go 1.21/' go.mod fi - # ----- 下载依赖 ----- - print_step "下载 Go 依赖..." - go mod download - print_success "依赖下载完成" - - # ----- 编译 ----- - print_step "编译 frpc-console..." - CGO_ENABLED=0 GOOS=linux go build \ - -ldflags="-s -w" \ - -o frpc-console . - - if [ -f "frpc-console" ]; then - SIZE=$(du -h frpc-console | cut -f1) - print_success "编译完成 ($SIZE)" - else - print_error "编译失败" - exit 1 - fi - - # ----- 准备部署目录 ----- + # ----- 准备数据目录 ----- print_step "准备部署目录..." mkdir -p "$DEPLOY_DIR" mkdir -p "$DATA_DIR" @@ -520,24 +410,11 @@ do_deploy() { print_info "数据库文件不存在,容器启动时将自动创建" fi - cp frpc-console "$DEPLOY_DIR/" - print_success "二进制已复制到 $DEPLOY_DIR" - - # ----- 构建 Docker 镜像 ----- + # ----- 构建 Docker 镜像(内部自动编译)----- print_step "构建 Docker 镜像..." docker build -t "${IMAGE_NAME}:latest" . print_success "Docker 镜像构建完成: ${IMAGE_NAME}:latest" - # ----- 停止旧容器 ----- - if [ "$CONTAINER_EXISTS" = true ]; then - print_step "处理旧容器..." - if [ "$CONTAINER_RUNNING" = true ]; then - docker stop frpc-console 2>/dev/null || true - fi - docker rm frpc-console 2>/dev/null || true - print_success "旧容器已清理" - fi - # ----- 启动新容器 ----- print_step "启动 frpc-console 容器..." docker run -d \ @@ -556,14 +433,12 @@ do_deploy() { exit 1 fi - # ----- 检查 frpc 子进程(增强版) ----- + # ----- 检查 frpc 子进程 ----- print_step "检查 frpc 状态..." sleep 3 - # 先确认容器在运行 if docker ps --format '{{.Names}}' | grep -q "^frpc-console$"; then - # 再检查 frpc 进程 - if docker exec frpc-console ps aux 2>/dev/null | grep -q "frpc -c"; then + if docker exec frpc-console ps aux 2>/dev/null | grep -q "[f]rpc -c"; then print_success "frpc 进程运行正常" else print_warn "frpc 进程未运行(可能配置为空,请在 WebUI 中导入 TOML)" @@ -573,7 +448,7 @@ do_deploy() { exit 1 fi - # ----- 事务后钩子:检测数据库是否可用 ----- + # ----- 事务后钩子:检测数据库 ----- print_step "验证数据库状态..." if docker exec frpc-console sqlite3 /app/frpc-console.db "SELECT COUNT(*) FROM users;" 2>/dev/null | grep -q "^[0-9]"; then print_success "数据库可用" @@ -593,8 +468,8 @@ do_deploy() { echo "" echo -e " ${CYAN}📍 访问地址:${NC} http://$(hostname -I | awk '{print $1}'):${PORT}" - echo -e " ${CYAN}📂 数据目录:${NC} ${DATA_DIR}" - echo -e " ${CYAN}📦 备份目录:${NC} ${BACKUP_DIR}" + echo -e " ${CYAN}📂 数据目录:${NC} ${DEPLOY_DIR}" + echo -e " ${CYAN}📦 备份目录:${NC} /tmp/frpc-console/db-backups" echo -e " ${CYAN}🐳 容器名称:${NC} frpc-console" echo "" echo -e " ${CYAN}常用命令:${NC}" @@ -638,7 +513,6 @@ main() { fi generate_plan - print_deployment_plan if ! confirm_deploy; then