Files
frpc-console/deploy.sh
T

330 lines
9.7 KiB
Bash
Raw 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
# ============================================================
# frpc-console 一键部署脚本
# 支持:Linux x86_64 / ARM64 / ARMv7
# 自动安装:git / curl / wget / Go / Docker
# ============================================================
set -e
# ---------- 颜色输出 ----------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# ---------- 配置 ----------
REPO_URL="https://git.whitetop.xyz/lxh2875931338/frpc-console.git"
BRANCH="main"
WORK_DIR="/tmp/frpc-console-build"
DEPLOY_DIR="/opt/frpc-console"
DATA_DIR="${DEPLOY_DIR}/data"
DEFAULT_PORT=9300
IMAGE_NAME="frpc-console"
GO_VERSION="1.25.0"
# ---------- 打印函数 ----------
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[✓]${NC} $1"; }
print_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
print_error() { echo -e "${RED}[✗]${NC} $1"; }
print_step() { echo -e "\n${CYAN}${NC} $1"; }
# ---------- 检查 root ----------
if [ "$EUID" -ne 0 ]; then
print_error "请使用 root 权限运行此脚本"
echo " sudo bash deploy.sh"
exit 1
fi
# ---------- 1. 检测操作系统 ----------
print_step "检测操作系统..."
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
OS_VERSION=$VERSION_ID
else
print_error "无法识别操作系统"
exit 1
fi
print_info "系统: $OS $OS_VERSION"
# ---------- 2. 检测 CPU 架构 ----------
print_step "检测 CPU 架构..."
ARCH=$(uname -m)
case $ARCH in
x86_64|amd64)
GO_ARCH="amd64"
;;
aarch64|arm64)
GO_ARCH="arm64"
;;
armv7l|armhf)
GO_ARCH="armv6l"
;;
*)
print_error "不支持的 CPU 架构: $ARCH"
exit 1
;;
esac
print_success "CPU 架构: $ARCH → Go 架构: $GO_ARCH"
# ---------- 3. 安装必要工具 ----------
print_step "检查必要工具..."
# git
if ! command -v git &> /dev/null; then
print_warn "git 未安装,正在安装..."
case $OS in
opensuse*|suse*|opensuse-tumbleweed|opensuse-slowroll)
zypper install -y git
;;
ubuntu|debian|linuxmint)
apt update -qq && apt install -y git
;;
centos|rhel|fedora|rocky|almalinux)
yum install -y git
;;
alpine)
apk add git
;;
*)
print_error "无法识别包管理器,请手动安装 git"
exit 1
;;
esac
print_success "git 安装完成"
else
print_success "git 已安装: $(git --version | awk '{print $3}')"
fi
# curl
if ! command -v curl &> /dev/null; then
print_warn "curl 未安装,正在安装..."
case $OS in
opensuse*|suse*|opensuse-tumbleweed|opensuse-slowroll) zypper install -y curl ;;
ubuntu|debian|linuxmint) apt install -y curl ;;
centos|rhel|fedora|rocky|almalinux) yum install -y curl ;;
alpine) apk add curl ;;
*) print_error "无法安装 curl"; exit 1 ;;
esac
print_success "curl 安装完成"
else
print_success "curl 已安装"
fi
# wget(备用)
if ! command -v wget &> /dev/null; then
print_warn "wget 未安装,正在安装..."
case $OS in
opensuse*|suse*|opensuse-tumbleweed|opensuse-slowroll) zypper install -y wget ;;
ubuntu|debian|linuxmint) apt install -y wget ;;
centos|rhel|fedora|rocky|almalinux) yum install -y wget ;;
alpine) apk add wget ;;
*) print_warn "wget 未安装,但不影响主要功能" ;;
esac
else
print_success "wget 已安装"
fi
# ---------- 4. 安装 Go ----------
print_step "检查 Go 环境..."
if ! command -v go &> /dev/null; then
print_warn "Go 未安装,正在下载 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
# 安装 Go
rm -rf /usr/local/go
tar -C /usr/local -xzf "$GO_TMP"
export PATH=$PATH:/usr/local/go/bin
echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/go.sh
# 配置 Go 代理
/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}) 安装完成"
else
print_success "Go 已安装: $(go version | awk '{print $3}') (架构: $(go env GOARCH))"
go env -w GOPROXY=https://goproxy.cn,direct 2>/dev/null || true
go env -w GOPRIVATE=git.whitetop.xyz 2>/dev/null || true
fi
# ---------- 5. 检查 Docker ----------
print_step "检查 Docker 环境..."
if ! command -v docker &> /dev/null; then
print_error "Docker 未安装,请先安装 Docker"
echo ""
echo " 快速安装:"
echo " curl -fsSL https://get.docker.com | bash"
echo " systemctl enable --now docker"
echo ""
exit 1
else
print_success "Docker 已安装: $(docker --version | awk '{print $3}' | tr -d ',')"
fi
# ---------- 6. 交互式配置 ----------
print_step "部署配置"
read -p "监听端口 [${DEFAULT_PORT}]: " PORT
PORT=${PORT:-$DEFAULT_PORT}
read -p "部署目录 [${DEPLOY_DIR}]: " DEPLOY_DIR_INPUT
DEPLOY_DIR=${DEPLOY_DIR_INPUT:-$DEPLOY_DIR}
DATA_DIR="${DEPLOY_DIR}/data"
print_info "端口: $PORT"
print_info "部署目录: $DEPLOY_DIR"
print_info "数据目录: $DATA_DIR"
# ---------- 7. 拉取代码 ----------
print_step "拉取代码..."
rm -rf "$WORK_DIR"
git clone --depth 1 --branch "$BRANCH" "$REPO_URL" "$WORK_DIR"
cd "$WORK_DIR"
# 确保目录存在
mkdir -p bin static
print_success "代码拉取完成"
# ---------- 8. 修复 go.mod 版本(防止 toolchain 下载) ----------
print_step "检查 go.mod..."
if grep -q "go 1.26" go.mod 2>/dev/null; then
print_warn "检测到 go.mod 版本过高,自动降级到 go 1.21"
sed -i 's/go 1.26.*/go 1.21/' go.mod
fi
# ---------- 9. 下载依赖 ----------
print_step "下载 Go 依赖..."
go mod download
print_success "依赖下载完成"
# ---------- 10. 编译 ----------
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
# ---------- 11. 准备部署目录 ----------
print_step "准备部署目录..."
mkdir -p "$DEPLOY_DIR"
mkdir -p "$DATA_DIR"
# 如果已有数据,保留;否则创建空占位
if [ ! -f "$DATA_DIR/frpc-console.db" ]; then
touch "$DATA_DIR/frpc-console.db"
print_info "新数据目录已创建"
else
print_info "已有数据目录,保留现有数据"
fi
cp frpc-console "$DEPLOY_DIR/"
print_success "二进制已复制到 $DEPLOY_DIR"
# ---------- 12. 构建 Docker 镜像 ----------
print_step "构建 Docker 镜像..."
docker build -t "${IMAGE_NAME}:latest" .
print_success "Docker 镜像构建完成: ${IMAGE_NAME}:latest"
# ---------- 13. 停止旧容器 ----------
print_step "检查旧容器..."
if docker ps -a --format '{{.Names}}' | grep -q "^frpc-console$"; then
print_warn "发现旧容器,正在停止并删除..."
docker stop frpc-console 2>/dev/null || true
docker rm frpc-console 2>/dev/null || true
print_success "旧容器已清理"
fi
# ---------- 14. 启动新容器 ----------
print_step "启动 frpc-console 容器..."
docker run -d \
--name frpc-console \
--restart=always \
--network host \
-v ${DATA_DIR}:/app/data \
-e PORT=9300 \
-e TZ=Asia/Shanghai \
${IMAGE_NAME}:latest
if docker ps | grep -q frpc-console; then
print_success "容器启动成功!"
else
print_error "容器启动失败,请检查日志: docker logs frpc-console"
exit 1
fi
# ---------- 15. 检查 frpc 子进程 ----------
print_step "检查 frpc 状态..."
sleep 3
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"
fi
# ---------- 16. 清理临时文件 ----------
print_step "清理临时文件..."
rm -rf "$WORK_DIR"
print_success "临时文件已清理"
# ---------- 17. 输出信息 ----------
echo ""
echo "=========================================="
echo -e "${GREEN}✅ frpc-console 部署完成!${NC}"
echo "=========================================="
echo ""
echo "📍 访问地址: http://$(hostname -I | awk '{print $1}'):${PORT}"
echo "📂 数据目录: ${DATA_DIR}"
echo "🐳 容器名称: frpc-console"
echo ""
echo "常用命令:"
echo " docker logs frpc-console # 查看日志"
echo " docker restart frpc-console # 重启服务"
echo " docker stop frpc-console # 停止服务"
echo " docker start frpc-console # 启动服务"
echo ""
echo "首次访问需要注册管理员账户"
echo "=========================================="