mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-03-21 22:06:45 +08:00
Update uninstall.sh
This commit is contained in:
175
uninstall.sh
175
uninstall.sh
@ -1,152 +1,105 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# More accurate uninstall for clash-for-linux
|
|
||||||
SERVICE_NAME="clash-for-linux"
|
SERVICE_NAME="clash-for-linux"
|
||||||
UNIT_PATH="/etc/systemd/system/${SERVICE_NAME}.service"
|
UNIT_PATH="/etc/systemd/system/${SERVICE_NAME}.service"
|
||||||
|
INSTALL_DIR="${CLASH_INSTALL_DIR:-/opt/clash-for-linux}"
|
||||||
|
|
||||||
RED='\033[31m'
|
CLASHCTL_LINK="/usr/local/bin/clashctl"
|
||||||
GREEN='\033[32m'
|
PROFILED_FILE="/etc/profile.d/clash-for-linux.sh"
|
||||||
YELLOW='\033[33m'
|
|
||||||
NC='\033[0m'
|
PURGE=false
|
||||||
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|
||||||
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
for arg in "$@"; do
|
||||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
case "$arg" in
|
||||||
err() { echo -e "${RED}[ERROR]${NC} $*"; }
|
--purge)
|
||||||
|
PURGE=true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[ERROR] Unknown arg: $arg" >&2
|
||||||
|
echo "Usage: uninstall.sh [--purge]" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
log() { printf "%b\n" "$*"; }
|
||||||
|
ok() { log "\033[32m[OK]\033[0m $*"; }
|
||||||
|
warn() { log "\033[33m[WARN]\033[0m $*"; }
|
||||||
|
err() { log "\033[31m[ERROR]\033[0m $*"; }
|
||||||
|
|
||||||
if [ "$(id -u)" -ne 0 ]; then
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
err "需要 root 权限执行卸载脚本(请使用 sudo bash uninstall.sh)"
|
err "需要 root 权限执行卸载"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Candidate install dirs:
|
echo "[INFO] uninstalling clash-for-linux..."
|
||||||
# 1) explicit CLASH_INSTALL_DIR
|
|
||||||
# 2) working directory if it looks like clash-for-linux
|
|
||||||
# 3) service WorkingDirectory / ExecStart path inferred from unit
|
|
||||||
# 4) common defaults
|
|
||||||
candidates=()
|
|
||||||
[ -n "${CLASH_INSTALL_DIR:-}" ] && candidates+=("${CLASH_INSTALL_DIR}")
|
|
||||||
PWD_BASENAME="$(basename "${PWD}")"
|
|
||||||
if [ "$PWD_BASENAME" = "clash-for-linux" ] && [ -f "${PWD}/start.sh" ]; then
|
|
||||||
candidates+=("${PWD}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$UNIT_PATH" ]; then
|
|
||||||
wd="$(sed -nE 's#^WorkingDirectory=(.*)#\1#p' "$UNIT_PATH" | head -n1 || true)"
|
|
||||||
[ -n "$wd" ] && candidates+=("$wd")
|
|
||||||
|
|
||||||
exec_path="$(sed -nE 's#^ExecStart=/bin/bash[[:space:]]+([^[:space:]]+/start\.sh).*#\1#p' "$UNIT_PATH" | head -n1 || true)"
|
|
||||||
if [ -n "$exec_path" ]; then
|
|
||||||
candidates+=("$(dirname "$exec_path")")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
candidates+=("/root/clash-for-linux" "/opt/clash-for-linux")
|
|
||||||
|
|
||||||
# normalize + uniq + choose first existing dir containing start.sh or shutdown.sh
|
|
||||||
INSTALL_DIR=""
|
|
||||||
declare -A seen
|
|
||||||
for d in "${candidates[@]}"; do
|
|
||||||
[ -n "$d" ] || continue
|
|
||||||
d="${d%/}"
|
|
||||||
[ -n "$d" ] || continue
|
|
||||||
if [ -z "${seen[$d]:-}" ]; then
|
|
||||||
seen[$d]=1
|
|
||||||
if [ -d "$d" ] && { [ -f "$d/start.sh" ] || [ -f "$d/shutdown.sh" ] || [ -d "$d/conf" ]; }; then
|
|
||||||
INSTALL_DIR="$d"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$INSTALL_DIR" ]; then
|
|
||||||
warn "未能自动识别安装目录,将按候选路径继续清理 systemd / 环境文件。"
|
|
||||||
else
|
|
||||||
info "识别到安装目录: $INSTALL_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
info "开始卸载 ${SERVICE_NAME} ..."
|
|
||||||
|
|
||||||
# 1) graceful stop
|
|
||||||
if [ -n "$INSTALL_DIR" ] && [ -f "${INSTALL_DIR}/shutdown.sh" ]; then
|
|
||||||
info "执行 shutdown.sh(优雅停止)..."
|
|
||||||
bash "${INSTALL_DIR}/shutdown.sh" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# 停止服务
|
||||||
|
# =========================
|
||||||
if command -v systemctl >/dev/null 2>&1; then
|
if command -v systemctl >/dev/null 2>&1; then
|
||||||
info "停止并禁用 systemd 服务..."
|
|
||||||
systemctl stop "${SERVICE_NAME}.service" >/dev/null 2>&1 || true
|
systemctl stop "${SERVICE_NAME}.service" >/dev/null 2>&1 || true
|
||||||
systemctl disable "${SERVICE_NAME}.service" >/dev/null 2>&1 || true
|
systemctl disable "${SERVICE_NAME}.service" >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 2) stop process by pid file from all likely dirs
|
# =========================
|
||||||
for d in "/root/clash-for-linux" "/opt/clash-for-linux" "${INSTALL_DIR:-}"; do
|
# 停止进程(仅当前项目)
|
||||||
[ -n "$d" ] || continue
|
# =========================
|
||||||
PID_FILE="$d/runtime/clash.pid"
|
PID_FILE="${INSTALL_DIR}/runtime/clash.pid"
|
||||||
|
|
||||||
if [ -f "$PID_FILE" ]; then
|
if [ -f "$PID_FILE" ]; then
|
||||||
PID="$(cat "$PID_FILE" 2>/dev/null || true)"
|
PID="$(cat "$PID_FILE" 2>/dev/null || true)"
|
||||||
|
|
||||||
if [ -n "${PID:-}" ] && kill -0 "$PID" 2>/dev/null; then
|
if [ -n "${PID:-}" ] && kill -0 "$PID" 2>/dev/null; then
|
||||||
info "检测到 PID=${PID}(来自 $PID_FILE),尝试停止..."
|
echo "[INFO] stopping pid=$PID"
|
||||||
kill "$PID" 2>/dev/null || true
|
kill "$PID" 2>/dev/null || true
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
if kill -0 "$PID" 2>/dev/null; then
|
if kill -0 "$PID" 2>/dev/null; then
|
||||||
warn "进程仍在运行,强制 kill -9 ${PID}"
|
echo "[WARN] force kill -9 $PID"
|
||||||
kill -9 "$PID" 2>/dev/null || true
|
kill -9 "$PID" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
rm -f "$PID_FILE" || true
|
|
||||||
|
rm -f "$PID_FILE"
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
# 兜底:按完整路径匹配,避免误杀其他 clash
|
# =========================
|
||||||
pkill -f '/clash-for-linux/.*/clash' >/dev/null 2>&1 || true
|
# 删除 systemd
|
||||||
pkill -f '/clash-for-linux/.*/mihomo' >/dev/null 2>&1 || true
|
# =========================
|
||||||
sleep 1
|
|
||||||
pkill -9 -f '/clash-for-linux/.*/clash' >/dev/null 2>&1 || true
|
|
||||||
pkill -9 -f '/clash-for-linux/.*/mihomo' >/dev/null 2>&1 || true
|
|
||||||
|
|
||||||
# 3) remove unit and related files
|
|
||||||
if [ -f "$UNIT_PATH" ]; then
|
if [ -f "$UNIT_PATH" ]; then
|
||||||
rm -f "$UNIT_PATH"
|
rm -f "$UNIT_PATH"
|
||||||
ok "已移除 systemd 单元: ${UNIT_PATH}"
|
ok "removed systemd unit"
|
||||||
fi
|
|
||||||
if [ -d "/etc/systemd/system/${SERVICE_NAME}.service.d" ]; then
|
|
||||||
rm -rf "/etc/systemd/system/${SERVICE_NAME}.service.d"
|
|
||||||
ok "已移除 drop-in: /etc/systemd/system/${SERVICE_NAME}.service.d"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command -v systemctl >/dev/null 2>&1; then
|
if command -v systemctl >/dev/null 2>&1; then
|
||||||
systemctl daemon-reload >/dev/null 2>&1 || true
|
systemctl daemon-reload >/dev/null 2>&1 || true
|
||||||
systemctl reset-failed >/dev/null 2>&1 || true
|
systemctl reset-failed >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4) cleanup env / command entry
|
# =========================
|
||||||
rm -f "/etc/default/${SERVICE_NAME}" >/dev/null 2>&1 || true
|
# 删除命令入口
|
||||||
rm -f "/etc/profile.d/clash-for-linux.sh" >/dev/null 2>&1 || true
|
# =========================
|
||||||
rm -f "/usr/local/bin/clashctl" >/dev/null 2>&1 || true
|
rm -f "$CLASHCTL_LINK" >/dev/null 2>&1 || true
|
||||||
for d in "/root/clash-for-linux" "/opt/clash-for-linux" "${INSTALL_DIR:-}"; do
|
rm -f "$PROFILED_FILE" >/dev/null 2>&1 || true
|
||||||
[ -n "$d" ] || continue
|
|
||||||
rm -f "$d/temp/clash-for-linux.sh" >/dev/null 2>&1 || true
|
|
||||||
done
|
|
||||||
|
|
||||||
# 5) remove install dirs
|
ok "removed command + env"
|
||||||
removed_any=false
|
|
||||||
for d in "${INSTALL_DIR:-}" "/root/clash-for-linux" "/opt/clash-for-linux"; do
|
# =========================
|
||||||
[ -n "$d" ] || continue
|
# 删除安装目录
|
||||||
if [ -d "$d" ] && { [ -f "$d/start.sh" ] || [ -d "$d/conf" ] || [ "$d" = "$INSTALL_DIR" ]; }; then
|
# =========================
|
||||||
rm -rf "$d"
|
if [ "$PURGE" = true ]; then
|
||||||
ok "已移除安装目录: $d"
|
if [ -d "$INSTALL_DIR" ]; then
|
||||||
removed_any=true
|
rm -rf "$INSTALL_DIR"
|
||||||
|
ok "removed install dir: $INSTALL_DIR"
|
||||||
|
else
|
||||||
|
warn "install dir not found: $INSTALL_DIR"
|
||||||
fi
|
fi
|
||||||
done
|
else
|
||||||
|
warn "install dir preserved: $INSTALL_DIR"
|
||||||
if [ "$removed_any" = false ]; then
|
echo "run with --purge to remove it"
|
||||||
warn "未发现可删除的安装目录"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
warn "如果你曾执行 proxy_on,当前终端可能仍保留代理环境变量。可执行:"
|
ok "uninstall complete"
|
||||||
echo " unset http_proxy https_proxy no_proxy HTTP_PROXY HTTPS_PROXY NO_PROXY"
|
|
||||||
echo " # 或关闭终端重新打开"
|
|
||||||
|
|
||||||
echo
|
|
||||||
ok "卸载完成 ✅"
|
|
||||||
Reference in New Issue
Block a user