#!/bin/bash # FRP Client 自动安装/卸载脚本 # 支持自动检测架构(amd64/arm64)并下载对应安装包 # # 使用方法: # chmod +x frpc.sh && ./frpc.sh # 交互式主菜单 # ./frpc.sh manage # 进入服务管理界面 # # 快速安装: # curl -sS -O https://gitea.tohub.top/Share/script/raw/branch/main/frpc.sh && chmod +x frpc.sh && ./frpc.sh # # 功能说明: # 1. 自动检测系统架构(amd64/arm64) # 2. 自动下载对应架构的安装包 # 3. 验证安装包完整性 # 4. 安装并配置 frpc 服务 # 5. 提供完整的服务管理功能 # 彩色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # 配置变量 INSTALL_DIR="/root/data/docker_data/frpc" BASE_URL="https://gitea.tohub.top/Share/script/raw/branch/main/frpc" FRPC_VERSION="0.65.0" set -e # 日志函数 print_info() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # 兼容旧函数名 log_info() { print_info "$1" } log_warn() { print_warning "$1" } log_error() { print_error "$1" } # 检查是否为root用户 check_root() { if [[ $EUID -ne 0 ]]; then print_error "此脚本需要root权限运行" print_info "请使用: sudo $0" exit 1 fi } # 检测系统架构 detect_arch() { local arch=$(uname -m) case "$arch" in x86_64) echo "amd64" ;; aarch64) echo "arm64" ;; *) print_error "不支持的系统架构: $arch" print_info "仅支持 x86_64(amd64) 和 aarch64(arm64)" exit 1 ;; esac } # 创建安装目录 create_install_dir() { if [[ ! -d "$INSTALL_DIR" ]]; then print_info "创建安装目录: $INSTALL_DIR" mkdir -p "$INSTALL_DIR" if [[ $? -ne 0 ]]; then print_error "创建目录失败" exit 1 fi fi } # 下载文件 download_file() { local url=$1 local output=$2 print_info "正在下载: $url" # 如果存在旧的不完整文件,先删除 if [[ -f "$output" ]]; then rm -f "$output" fi if command -v wget &> /dev/null; then wget -q --show-progress "$url" -O "$output" elif command -v curl &> /dev/null; then curl -# -L "$url" -o "$output" else print_error "未找到 wget 或 curl,请先安装" exit 1 fi # 检查下载是否成功 if [[ $? -eq 0 ]] && [[ -f "$output" ]] && [[ -s "$output" ]]; then print_success "下载完成: $output" return 0 else print_error "下载失败: $url" rm -f "$output" return 1 fi } # 验证tar.gz文件是否有效 verify_tar_file() { local file=$1 if [[ ! -f "$file" ]]; then return 1 fi if [[ ! -s "$file" ]]; then print_warning "文件为空: $file" return 1 fi # 尝试列出tar文件内容来验证完整性 if ! tar -tzf "$file" >/dev/null 2>&1; then print_warning "文件不是有效的 tar.gz 包: $file" return 1 fi return 0 } # 下载安装包 download_packages() { local arch=$(detect_arch) print_info "检测到系统架构: $arch" create_install_dir local frp_file="frp_${FRPC_VERSION}_linux_${arch}.tar.gz" local download_failed=0 # 下载 FRP if [[ ! -f "$INSTALL_DIR/$frp_file" ]]; then if ! download_file "$BASE_URL/$frp_file" "$INSTALL_DIR/$frp_file"; then download_failed=1 fi else print_warning "文件已存在,跳过下载: $frp_file" fi # 下载配置文件(如果不存在) if [[ ! -f "$INSTALL_DIR/frpc.toml" ]]; then print_info "下载配置文件模板..." if ! download_file "$BASE_URL/frpc.toml" "$INSTALL_DIR/frpc.toml"; then print_warning "配置文件下载失败,需要手动创建" fi fi return $download_failed } # 创建frp用户 create_frp_user() { if ! id "frp" &>/dev/null; then log_info "创建 frp 用户..." useradd -r -s /bin/false frp else log_info "frp 用户已存在" fi } # 解压安装包 extract_archive() { local arch=$(detect_arch) local frp_file="$INSTALL_DIR/frp_${FRPC_VERSION}_linux_${arch}.tar.gz" # 检查文件是否存在 if [[ ! -f "$frp_file" ]]; then print_warning "安装包不存在,开始下载..." if ! download_packages; then print_error "下载失败,无法继续安装" return 1 fi fi # 验证文件完整性 print_info "验证安装包完整性..." if ! verify_tar_file "$frp_file"; then print_error "安装包验证失败,请重新下载" rm -f "$frp_file" return 1 fi print_success "安装包验证通过" print_info "解压 frp_${FRPC_VERSION}_linux_${arch}.tar.gz..." # 创建临时目录 TEMP_DIR=$(mktemp -d) # 解压到临时目录 tar -xzf "$frp_file" -C "$TEMP_DIR" # 复制文件到安装目录 cp "$TEMP_DIR"/frp_${FRPC_VERSION}_linux_${arch}/frpc "$INSTALL_DIR/" # 清理临时目录 rm -rf "$TEMP_DIR" # 设置权限 - 确保 frp 用户可以访问和执行 # 设置目录权限,允许 frp 用户访问 chmod 755 /root chmod 755 /root/data chmod 755 /root/data/docker_data chmod 755 "$INSTALL_DIR" # 设置文件所有者和权限 chown root:frp "$INSTALL_DIR/frpc" chmod 755 "$INSTALL_DIR/frpc" # 删除压缩包 print_info "清理下载的压缩包..." rm -f "$frp_file" print_success "已删除压缩包" print_success "frpc 已安装到 $INSTALL_DIR/" } # 配置frpc configure_frpc() { print_info "配置 frpc..." # 检查配置文件是否已存在 if [[ -f "$INSTALL_DIR/frpc.toml" ]]; then print_success "配置文件已存在: $INSTALL_DIR/frpc.toml" elif [[ -f "frpc.toml" ]]; then # 如果当前目录有配置文件,复制它 cp frpc.toml "$INSTALL_DIR/" print_success "配置文件已复制到 $INSTALL_DIR/frpc.toml" else print_error "找不到配置文件 frpc.toml" print_info "请手动创建配置文件: $INSTALL_DIR/frpc.toml" return 1 fi chown root:frp "$INSTALL_DIR/frpc.toml" chmod 640 "$INSTALL_DIR/frpc.toml" } # 创建systemd服务 create_service() { print_info "创建 systemd 服务..." cat > /etc/systemd/system/frpc.service << EOF [Unit] Description=Frp Client Service After=network.target [Service] Type=simple User=frp Restart=on-failure RestartSec=5s ExecStart=${INSTALL_DIR}/frpc -c ${INSTALL_DIR}/frpc.toml ExecReload=/bin/kill -s HUP \$MAINPID KillMode=mixed TimeoutStopSec=5s [Install] WantedBy=multi-user.target EOF # 重新加载systemd systemctl daemon-reload print_success "systemd 服务已创建" } # 启动服务 start_service() { print_info "启动 frpc 服务..." # 启用开机自启 systemctl enable frpc # 启动服务 systemctl start frpc # 检查服务状态 if systemctl is-active --quiet frpc; then print_success "frpc 服务启动成功" else print_error "frpc 服务启动失败" print_error "请检查日志: journalctl -u frpc -f" return 1 fi } # 显示状态信息 show_status() { echo "" print_success "============================================" print_success "FRP Client 安装完成!" print_success "============================================" echo "" echo "服务状态:" systemctl status frpc --no-pager echo "" print_info "常用命令:" echo " 启动服务: systemctl start frpc" echo " 停止服务: systemctl stop frpc" echo " 重启服务: systemctl restart frpc" echo " 查看状态: systemctl status frpc" echo " 查看日志: journalctl -u frpc -f" echo "" print_info "配置文件位置: $INSTALL_DIR/frpc.toml" print_info "程序位置: $INSTALL_DIR/frpc" print_success "============================================" echo "" } # 安装frpc主函数 install_frpc() { print_info "开始安装 FRP Client..." create_frp_user extract_archive || return 1 configure_frpc || return 1 create_service start_service || return 1 show_status print_success "FRP Client 安装完成!" } # 卸载frpc uninstall_frpc() { print_warning "即将卸载 FRP Client" read -p "是否继续?[y/N] " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then print_info "已取消卸载" return fi # 停止服务 print_info "停止 frpc 服务..." systemctl stop frpc 2>/dev/null || true # 禁用开机自启 print_info "禁用开机自启..." systemctl disable frpc 2>/dev/null || true # 删除服务文件 print_info "删除服务文件..." rm -f /etc/systemd/system/frpc.service systemctl daemon-reload # 删除程序文件 print_info "删除程序文件..." rm -rf "$INSTALL_DIR" # 删除frp用户 print_info "删除 frp 用户..." userdel frp 2>/dev/null || true echo "" print_success "FRP Client 已完全卸载" } # 检查安装状态 check_status() { local arch=$(detect_arch) local frp_file="$INSTALL_DIR/frp_${FRPC_VERSION}_linux_${arch}.tar.gz" echo "" print_info "============================================" print_info "检查 FRP Client 状态" print_info "============================================" # 检查程序是否安装 if [[ -f "$INSTALL_DIR/frpc" ]]; then print_success "FRP Client 已安装" print_info " 程序位置: $INSTALL_DIR/frpc" # 获取程序版本 if [[ -x "$INSTALL_DIR/frpc" ]]; then local version=$("$INSTALL_DIR/frpc" --version 2>/dev/null | head -n 1 || echo "未知") print_info " 版本信息: $version" fi # 检查服务状态 if systemctl is-active --quiet frpc; then print_success "frpc 服务运行中" else print_warning "frpc 服务未运行" fi if systemctl is-enabled --quiet frpc; then print_success "开机自启已启用" else print_warning "开机自启未启用" fi # 检查配置文件 if [[ -f "$INSTALL_DIR/frpc.toml" ]]; then print_success "配置文件存在" else print_warning "配置文件不存在" fi else print_warning "FRP Client 未安装" fi # 检查frp用户 if id "frp" &>/dev/null; then print_success "frp 用户存在" else print_warning "frp 用户不存在" fi # 检查安装包状态 echo "" print_info "安装包状态:" if [[ -f "$frp_file" ]]; then local size=$(du -h "$frp_file" 2>/dev/null | cut -f1) print_info " FRP 压缩包: ${CYAN}已下载${NC} (${size})" else print_warning " FRP 压缩包: 未下载" fi if [[ -f "$INSTALL_DIR/frpc.toml" ]]; then print_info " 配置文件: ${CYAN}存在${NC}" else print_warning " 配置文件: 不存在" fi print_info "============================================" echo "" } # 交互式服务管理菜单 interactive_menu() { while true; do echo "" echo "===============================================" echo " FRP Client 服务管理" echo "===============================================" echo "1. 启动服务 (start)" echo "2. 停止服务 (stop)" echo "3. 重启服务 (restart)" echo "4. 查看状态 (status)" echo "5. 查看日志 (logs)" echo "6. 查看配置文件 (config)" echo "7. 编辑配置文件 (edit)" echo "8. 卸载服务 (uninstall)" echo "0. 退出 (exit)" echo "===============================================" read -p "请选择操作 [0-8]: " choice case $choice in 1|start) log_info "启动 frpc 服务..." systemctl start frpc if systemctl is-active --quiet frpc; then log_info "服务启动成功" else log_error "服务启动失败" fi systemctl status frpc --no-pager ;; 2|stop) log_info "停止 frpc 服务..." systemctl stop frpc log_info "服务已停止" ;; 3|restart) log_info "重启 frpc 服务..." systemctl restart frpc if systemctl is-active --quiet frpc; then log_info "服务重启成功" else log_error "服务重启失败" fi systemctl status frpc --no-pager ;; 4|status) echo "服务状态:" systemctl status frpc --no-pager ;; 5|logs) log_info "查看服务日志 (按 Ctrl+C 退出):" sleep 1 journalctl -u frpc -f ;; 6|config) echo "配置文件内容:" echo "----------------------------------------" cat "$INSTALL_DIR/frpc.toml" echo "----------------------------------------" ;; 7|edit) print_info "编辑配置文件..." if command -v nano >/dev/null 2>&1; then nano "$INSTALL_DIR/frpc.toml" elif command -v vi >/dev/null 2>&1; then vi "$INSTALL_DIR/frpc.toml" else print_error "未找到文本编辑器,请手动编辑: $INSTALL_DIR/frpc.toml" fi read -p "是否重启服务使配置生效? [y/N]: " restart_choice if [[ $restart_choice =~ ^[Yy]$ ]]; then systemctl restart frpc print_info "服务已重启" fi ;; 8|uninstall) uninstall_frpc if [[ $? -eq 0 ]]; then exit 0 fi ;; 0|exit|quit|q) log_info "退出管理界面" exit 0 ;; *) log_error "无效选择,请输入 0-8 或对应命令" ;; esac read -p "按回车键继续..." done } # 主菜单 show_main_menu() { clear echo -e "${CYAN}" echo "============================================" echo " FRP Client 自动安装/卸载脚本" echo "============================================" echo -e "${NC}" echo -e "${GREEN}1.${NC} 安装 FRP Client" echo -e "${GREEN}2.${NC} 卸载 FRP Client" echo -e "${GREEN}3.${NC} 检查状态" echo -e "${GREEN}4.${NC} 下载安装包" echo -e "${GREEN}5.${NC} 服务管理" echo -e "${GREEN}0.${NC} 退出" echo "" echo -e "${CYAN}============================================${NC}" } # 主函数 main() { check_root # 检查是否为管理模式 if [[ "$1" == "manage" || "$1" == "menu" || "$1" == "-m" ]]; then interactive_menu return fi # 如果没有参数,显示交互式主菜单 if [[ $# -eq 0 ]]; then while true; do show_main_menu read -p "请选择操作 [0-5]: " choice case $choice in 1) install_frpc read -p "按任意键继续..." -n 1 ;; 2) uninstall_frpc read -p "按任意键继续..." -n 1 ;; 3) check_status read -p "按任意键继续..." -n 1 ;; 4) print_info "开始下载安装包..." if download_packages; then print_success "下载完成!" else print_error "下载失败" fi read -p "按任意键继续..." -n 1 ;; 5) interactive_menu ;; 0) print_info "退出脚本" exit 0 ;; *) print_error "无效的选择,请重新输入" sleep 2 ;; esac done else # 兼容旧的直接安装模式(如果有参数的话) print_info "开始安装 FRP Client..." install_frpc echo "" # 询问是否进入交互管理界面 read -p "是否进入服务管理界面? [y/N]: " enter_menu if [[ $enter_menu =~ ^[Yy]$ ]]; then interactive_menu else echo "" print_info "可使用以下命令:" echo " $0 # 进入主菜单" echo " $0 manage # 进入服务管理界面" echo " systemctl [start|stop|restart|status] frpc" fi fi } # 运行主函数 main "$@"