#!/usr/bin/env bash set -euo pipefail # FRP 一键卸载脚本 # 用法:curl -fsSL "https://pan.shumengya.top/d/scripts/frp/uninstall_frp.sh" | sudo bash INSTALL_DIR="/shumengya/bin/frp" SERVICE_PREFIX="smy-frp" log() { printf '[frp-卸载] %s\n' "$*" >&2; } fail() { log "错误: $*" >&2; exit 1; } show_progress() { local pid=$1 local text=$2 local delay=0.1 local spin='-\|/' printf "[frp-卸载] %s... " "$text" >&2 while ps -p "$pid" > /dev/null 2>&1; do local temp=${spin#?} printf "\b%c" "$spin" >&2 local spin=$temp${spin%"$temp"} sleep $delay done printf "\b完成\n" >&2 } require_root() { if [ "${EUID:-$(id -u)}" -ne 0 ]; then fail "请使用 root 权限运行 (sudo bash uninstall_frp.sh)" fi } select_mode() { echo "请选择卸载模式:" >&2 echo "1) 卸载客户端 (frpc)" >&2 echo "2) 卸载服务端 (frps)" >&2 echo "3) 全部卸载" >&2 read -p "请输入选项 [1-3]: " choice < /dev/tty case "$choice" in 1) echo "client" ;; 2) echo "server" ;; 3) echo "both" ;; *) fail "无效选项" ;; esac } stop_and_disable_service() { local name=$1 local service_name="${SERVICE_PREFIX}${name:3}" if systemctl is-active --quiet "${service_name}.service"; then systemctl stop "${service_name}.service" fi if systemctl is-enabled --quiet "${service_name}.service" 2>/dev/null; then systemctl disable "${service_name}.service" fi } remove_service_file() { local name=$1 local service_name="${SERVICE_PREFIX}${name:3}" local service_file="/etc/systemd/system/${service_name}.service" if [ -f "$service_file" ]; then rm -f "$service_file" systemctl daemon-reload fi } cleanup_process() { local name=$1 # 查找并杀掉所有匹配的进程 local pids pids=$(pgrep -f "$INSTALL_DIR/$name" || true) if [ -n "$pids" ]; then kill -9 $pids 2>/dev/null || true fi } uninstall_component() { local name=$1 log "正在卸载 $name ..." (stop_and_disable_service "$name") & show_progress $! "停止服务" cleanup_process "$name" (remove_service_file "$name") & show_progress $! "删除服务文件" if [ -f "$INSTALL_DIR/$name" ]; then rm -f "$INSTALL_DIR/$name" fi # 注意:不自动删除配置文件,以免误删用户配置 # if [ -f "$INSTALL_DIR/${name}.toml" ]; then # rm -f "$INSTALL_DIR/${name}.toml" # fi } main() { require_root local mode if [ $# -gt 0 ]; then case "$1" in client|frpc) mode="client" ;; server|frps) mode="server" ;; both) mode="both" ;; *) fail "无效参数: $1 (可用: client, server, both)" ;; esac else mode=$(select_mode) fi if [ "$mode" = "client" ] || [ "$mode" = "both" ]; then uninstall_component "frpc" fi if [ "$mode" = "server" ] || [ "$mode" = "both" ]; then uninstall_component "frps" fi # 如果目录为空,则删除目录 if [ -d "$INSTALL_DIR" ]; then if [ -z "$(ls -A "$INSTALL_DIR")" ]; then rm -rf "$INSTALL_DIR" log "已删除空安装目录" else log "保留安装目录 (包含配置文件): $INSTALL_DIR" fi fi log "==========================================" log "卸载任务完成" log "==========================================" } main "$@"