#!/usr/bin/env bash # XW远程(湘网远程)客户端一键配置 —— macOS / Linux 通用 # # 用法: # ./install-xw-remote.sh # 配置当前用户 # sudo ./install-xw-remote.sh # 同时配置 root 服务级(无人值守) # # 说明: # 写配置前会先停掉 RustDesk,否则其退出时会把内存中的旧配置回写磁盘。 set -euo pipefail # ============ 服务器参数 ============ ID_SERVER="rd.xwlemd.com" RELAY_SERVER="rd.xwlemd.com" API_SERVER="https://rd.xwlemd.com" PUBLIC_KEY="okv1OjwoFuEeM4zD09UV2FJK85itofUwvNSEVYQujS0=" C_OK="\033[32m"; C_WARN="\033[33m"; C_ERR="\033[31m"; C_STEP="\033[36m"; C_DIM="\033[90m"; C_OFF="\033[0m" step() { printf "${C_STEP}[*]${C_OFF} %s\n" "$1"; } ok() { printf "${C_OK}[+]${C_OFF} %s\n" "$1"; } warn() { printf "${C_WARN}[!]${C_OFF} %s\n" "$1"; } err() { printf "${C_ERR}[x]${C_OFF} %s\n" "$1"; } printf "\n XW远程 · 客户端配置\n ${C_DIM}服务器 %s${C_OFF}\n\n" "$ID_SERVER" # ---------- 平台判定 ---------- OS="$(uname -s)" case "$OS" in Darwin) PLATFORM="macos" ;; Linux) PLATFORM="linux" ;; *) err "不支持的系统: $OS"; exit 1 ;; esac ok "平台: $PLATFORM" # ---------- 停服务 ---------- stop_rustdesk() { if [ "$PLATFORM" = "linux" ]; then if command -v systemctl >/dev/null 2>&1; then if systemctl is-active --quiet rustdesk 2>/dev/null; then step "停止 rustdesk.service" systemctl stop rustdesk 2>/dev/null || true fi fi pkill -x rustdesk 2>/dev/null || true else pkill -x RustDesk 2>/dev/null || true pkill -f "RustDesk.app" 2>/dev/null || true fi sleep 1 } start_rustdesk() { if [ "$PLATFORM" = "linux" ]; then if command -v systemctl >/dev/null 2>&1 && systemctl list-unit-files 2>/dev/null | grep -q '^rustdesk'; then systemctl start rustdesk 2>/dev/null && ok "rustdesk.service 已启动" || warn "服务启动失败,请手动检查" return fi if command -v rustdesk >/dev/null 2>&1; then nohup rustdesk --hidden >/dev/null 2>&1 & ok "客户端已启动" fi else if [ -d "/Applications/RustDesk.app" ]; then open -a RustDesk 2>/dev/null && ok "客户端已启动" || warn "请手动打开 RustDesk" fi fi } # ---------- TOML 写入 ---------- set_root_option() { local file="$1" key="$2" val="$3" mkdir -p "$(dirname "$file")"; touch "$file" if grep -qE "^[[:space:]]*${key}[[:space:]]*=" "$file"; then KEY="$key" VAL="$val" perl -i -pe 'BEGIN{$k=$ENV{KEY};$v=$ENV{VAL}} if(/^[[:space:]]*\Q$k\E[[:space:]]*=/){$_="$k = \x27$v\x27\n"}' "$file" else KEY="$key" VAL="$val" perl -i -pe 'BEGIN{$k=$ENV{KEY};$v=$ENV{VAL};$d=0} if(!$d && /^[[:space:]]*\[/){$_="$k = \x27$v\x27\n".$_;$d=1} END{if(!$d){print "$k = \x27$v\x27\n"}}' "$file" fi } set_options_option() { local file="$1" key="$2" val="$3" mkdir -p "$(dirname "$file")"; touch "$file" if grep -qE "^[[:space:]]*${key}[[:space:]]*=" "$file"; then KEY="$key" VAL="$val" perl -i -pe 'BEGIN{$k=$ENV{KEY};$v=$ENV{VAL}} if(/^[[:space:]]*\Q$k\E[[:space:]]*=/){$_="$k = \x27$v\x27\n"}' "$file" elif grep -qE "^[[:space:]]*\[options\][[:space:]]*$" "$file"; then KEY="$key" VAL="$val" perl -i -pe 'BEGIN{$k=$ENV{KEY};$v=$ENV{VAL};$d=0} if(!$d && /^[[:space:]]*\[options\][[:space:]]*$/){$_ .= "$k = \x27$v\x27\n";$d=1}' "$file" else printf "\n[options]\n%s = '%s'\n" "$key" "$val" >> "$file" fi } configure() { local file="$1" label="$2" step "写入$label: $file" if [ -f "$file" ]; then local bak="${file}.bak-$(date +%Y%m%d-%H%M%S)" cp -p "$file" "$bak" ok "已备份 -> $(basename "$bak")" fi set_root_option "$file" "rendezvous_server" "${ID_SERVER}:21116" set_options_option "$file" "custom-rendezvous-server" "$ID_SERVER" set_options_option "$file" "relay-server" "$RELAY_SERVER" set_options_option "$file" "api-server" "$API_SERVER" set_options_option "$file" "key" "$PUBLIC_KEY" ok "配置已写入" } # ---------- 执行 ---------- stop_rustdesk if [ "$PLATFORM" = "linux" ]; then configure "$HOME/.config/rustdesk/RustDesk2.toml" "用户级" if [ "$(id -u)" -eq 0 ] && [ -n "${SUDO_USER:-}" ]; then configure "/root/.config/rustdesk/RustDesk2.toml" "root 服务级" fi else configure "$HOME/Library/Application Support/RustDesk/config/RustDesk2.toml" "用户级" if [ "$(id -u)" -eq 0 ]; then configure "/var/root/Library/Application Support/RustDesk/config/RustDesk2.toml" "root 服务级" fi fi start_rustdesk sleep 2 printf "\n${C_DIM}──────────────────────────────────────────${C_OFF}\n" printf " 服务器: %s\n" "$ID_SERVER" printf " 请在客户端主界面查看本机 ID\n" printf "${C_DIM}──────────────────────────────────────────${C_OFF}\n\n" ok "配置完成。若仍显示旧服务器,请完全退出 RustDesk 后重新打开。" warn "远程控制本机前,请先在「设置 → 安全」中设置永久密码。"