#!/bin/sh RED='\033[31m' GREEN='\033[32m' YELLOW='\033[33m' BLUE='\033[34m' PURPLE='\033[35m' CYAN='\033[36m' BOLD='\033[1m' RESET='\033[0m' WORKER_URL="https://op.sawayn.nom.za" AUTH_KEY="urTMjh522lnFkJwOt7anJMvhwdp0KQhk" PASSED_KEY="null" # 通用兼容下载工具 http_download() { OUT_FILE="$1" DL_URL="$2" if command -v curl >/dev/null 2>&1; then curl -sSL -k -o "$OUT_FILE" "$DL_URL" elif command -v uclient-fetch >/dev/null 2>&1; then uclient-fetch --no-check-certificate -q -O "$OUT_FILE" "$DL_URL" else wget --no-check-certificate -q -O "$OUT_FILE" "$DL_URL" fi } printf "%b==================================================%b\n" "$CYAN$BOLD" "$RESET" printf "%b 🚀 OpenWrt 常用工具 (代理插件/Docker模块化管理) %b\n" "$CYAN$BOLD" "$RESET" printf "%b==================================================%b\n" "$CYAN$BOLD" "$RESET" # 1. 严格环境检测:仅允许 OpenWrt if [ ! -f /etc/openwrt_release ]; then printf "%b[✘] 错误:检测到当前系统非 OpenWrt,本脚本仅适用于 OpenWrt 环境!%b\n" "$RED$BOLD" "$RESET" exit 1 fi . /etc/openwrt_release ARCH="${DISTRIB_ARCH:-x86_64}" DISTRIB_RELEASE="${DISTRIB_RELEASE:-25.12}" RELEASE="$(echo "$DISTRIB_RELEASE" | cut -d. -f1,2)" if command -v apk >/dev/null 2>&1; then PKG_MGR="apk" else PKG_MGR="opkg" fi # 2. 密钥验证 if [ "$PASSED_KEY" != "$AUTH_KEY" ]; then printf "%b请输入访问密钥 Key (粘贴/输入均不显示): %b" "$BOLD" "$RESET" read -s -r INPUT_KEY printf "\n" if [ "$INPUT_KEY" != "$AUTH_KEY" ]; then printf "%b[✘] 密钥校验错误,拒绝访问!%b\n" "$RED" "$RESET" exit 1 fi PASSED_KEY="$INPUT_KEY" fi printf "%b[✓] 密钥验证成功!%b\n\n" "$GREEN$BOLD" "$RESET" check_installed() { PLUGIN_NAME="$1" SHORT_NAME=$(echo "$PLUGIN_NAME" | sed 's/luci-app-//') IS_INSTALLED=0 if [ "$PKG_MGR" = "apk" ]; then FOUND=$(apk info 2>/dev/null | grep -E "^(luci-app-${SHORT_NAME}|${SHORT_NAME})($|[-_])") [ -n "$FOUND" ] && IS_INSTALLED=1 else FOUND=$(opkg list-installed 2>/dev/null | cut -d' ' -f1 | grep -E "^(luci-app-${SHORT_NAME}|${SHORT_NAME})($|[-_])") [ -n "$FOUND" ] && IS_INSTALLED=1 fi if [ "$IS_INSTALLED" -eq 1 ]; then printf "%b[已安装]%b" "$GREEN$BOLD" "$RESET" else printf "%b[未安装]%b" "$RED$BOLD" "$RESET" fi } # 3. 环境及状态展示 printf "%b[i] OpenWrt 环境及核心服务状态检测:%b\n" "$BLUE$BOLD" "$RESET" printf " - %-18s %s\n" "系统版本:" "$DISTRIB_RELEASE" printf " - %-18s %s\n" "设备架构:" "$ARCH" printf " - %-18s %b%s%b\n" "包管理器:" "$GREEN" "$PKG_MGR" "$RESET" printf " --------------------------------------------------\n" printf " - %-22s " "PassWall 状态:" && check_installed "luci-app-passwall" && printf "\n" printf " - %-22s " "PassWall2 状态:" && check_installed "luci-app-passwall2" && printf "\n" printf " - %-22s " "OpenClash 状态:" && check_installed "luci-app-openclash" && printf "\n" printf " - %-22s " "Docker (引擎) 状态:" && check_installed "dockerd" && printf "\n" printf " - %-22s " "Dockerman (界面) 状态:" && check_installed "luci-app-dockerman" && printf "\n" printf "%b--------------------------------------------------%b\n\n" "$CYAN" "$RESET" # 4. 功能函数区 add_passwall_repo() { printf "%b[+] 正在配置 PassWall 软件源...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then mkdir -p /etc/apk/keys /etc/apk/repositories.d http_download "/etc/apk/keys/openwrt-passwall-build.pem" "https://master.dl.sourceforge.net/project/openwrt-passwall-build/apk.pub" touch /etc/apk/repositories.d/customfeeds.list for feed in passwall_luci passwall_packages passwall2; do FEED_URL="https://master.dl.sourceforge.net/project/openwrt-passwall-build/releases/packages-$RELEASE/$ARCH/$feed/packages.adb" grep -qF "$FEED_URL" /etc/apk/repositories.d/customfeeds.list || echo "$FEED_URL" >> /etc/apk/repositories.d/customfeeds.list done printf "%b[✓] 软件源添加完成,正在更新包索引...%b\n" "$GREEN" "$RESET" apk update || true else http_download "/tmp/ipk.pub" "https://master.dl.sourceforge.net/project/openwrt-passwall-build/ipk.pub" opkg-key add /tmp/ipk.pub >/dev/null 2>&1 || true rm -f /tmp/ipk.pub touch /etc/opkg/customfeeds.conf for feed in passwall_luci passwall_packages passwall2; do FEED_LINE="src/gz $feed https://master.dl.sourceforge.net/project/openwrt-passwall-build/releases/packages-$RELEASE/$ARCH/$feed" grep -qF "$feed" /etc/opkg/customfeeds.conf || echo "$FEED_LINE" >> /etc/opkg/customfeeds.conf done printf "%b[✓] 软件源添加完成,正在更新包索引...%b\n" "$GREEN" "$RESET" opkg update || true fi printf "%b[✓] PassWall 软件源配置完成!%b\n" "$GREEN$BOLD" "$RESET" } install_openclash() { printf "%b[+] 正在安装 OpenClash 基础依赖...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk update || true apk add curl ca-certificates luci-compat bash iptables ip-full || true else opkg update || true opkg install curl ca-certificates luci-compat bash iptables ip-full || true fi EXT="ipk" [ "$PKG_MGR" = "apk" ] && EXT="apk" FILE_NAME="luci-app-openclash-master.$EXT" DOWNLOAD_URL="$WORKER_URL/?key=$PASSED_KEY&download=openclash_$EXT" printf "%b[+] 正在通过云端 Worker 中转拉取包: %b%s%b\n" "$CYAN" "$BOLD" "$FILE_NAME" "$RESET" http_download "/tmp/$FILE_NAME" "$DOWNLOAD_URL" if [ ! -s "/tmp/$FILE_NAME" ]; then printf "%b[✘] 错误:云端中转下载失败,目标文件为空!%b\n" "$RED" "$RESET" rm -f "/tmp/$FILE_NAME" return 1 fi printf "%b[+] 开始安装 %s...%b\n" "$YELLOW" "$FILE_NAME" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk add --allow-untrusted "/tmp/$FILE_NAME" || true else opkg install "/tmp/$FILE_NAME" || true fi rm -f "/tmp/$FILE_NAME" printf "%b[✓] OpenClash 安装流程完成!%b\n" "$GREEN$BOLD" "$RESET" } install_docker_engine() { printf "%b[+] 正在安装 Docker 引擎 (dockerd) 及 Docker Compose...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk update || true apk add dockerd docker-compose || true else opkg update || true opkg install dockerd docker-compose || true fi if [ -f "/etc/init.d/dockerd" ]; then /etc/init.d/dockerd enable || true /etc/init.d/dockerd start || true fi printf "%b[✓] Docker 引擎与 Compose 安装完成,服务已开启!%b\n" "$GREEN$BOLD" "$RESET" } install_dockerman_ui() { printf "%b[+] 正在安装 Dockerman 图形管理界面...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk update || true apk add luci-app-dockerman luci-i18n-dockerman-zh-cn || true else opkg update || true opkg install luci-app-dockerman || true fi printf "%b[✓] Dockerman 管理界面安装完成!%b\n" "$GREEN$BOLD" "$RESET" } remove_docker_engine() { printf "%b[+] 正在卸载 Docker 引擎...%b\n" "$YELLOW" "$RESET" if [ -f "/etc/init.d/dockerd" ]; then /etc/init.d/dockerd stop >/dev/null 2>&1 || true /etc/init.d/dockerd disable >/dev/null 2>&1 || true fi if [ "$PKG_MGR" = "apk" ]; then FOR_DEL=$(apk info 2>/dev/null | grep -E "^(dockerd|docker|docker-compose)($|[-_])") [ -n "$FOR_DEL" ] && apk del $FOR_DEL --purge || true else FOR_DEL=$(opkg list-installed 2>/dev/null | cut -d' ' -f1 | grep -E "^(dockerd|docker|docker-compose)($|[-_])") [ -n "$FOR_DEL" ] && opkg remove $FOR_DEL --force-remove-source-change --force-depends || true fi printf "%b[✓] Docker 引擎及 CLI 工具卸载完成!%b\n" "$GREEN$BOLD" "$RESET" } remove_dockerman_ui() { printf "%b[+] 正在卸载 Dockerman 图形管理界面...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then FOR_DEL=$(apk info 2>/dev/null | grep -E "^(luci-app-dockerman|luci-i18n-dockerman-zh-cn)($|[-_])") [ -n "$FOR_DEL" ] && apk del $FOR_DEL --purge || true else FOR_DEL=$(opkg list-installed 2>/dev/null | cut -d' ' -f1 | grep -E "^(luci-app-dockerman|luci-i18n-dockerman-zh-cn)($|[-_])") [ -n "$FOR_DEL" ] && opkg remove $FOR_DEL --force-remove-source-change --force-depends || true fi rm -rf "/etc/config/dockerman" \ "/usr/lib/lua/luci/controller/dockerman.lua" \ "/usr/share/luci/menu.d/luci-app-dockerman.json" printf "%b[✓] Dockerman Web 界面卸载完成!%b\n" "$GREEN$BOLD" "$RESET" } remove_plugin() { PLUGIN_NAME="$1" SHORT_NAME=$(echo "$PLUGIN_NAME" | sed 's/luci-app-//') printf "%b[+] 正在彻底卸载 %s...%b\n" "$YELLOW" "$PLUGIN_NAME" "$RESET" if [ "$PKG_MGR" = "apk" ]; then FOR_DEL=$(apk info 2>/dev/null | grep -E "^(luci-app-${SHORT_NAME}|${SHORT_NAME}|luci-i18n-${SHORT_NAME}-zh-cn)($|[-_])") [ -n "$FOR_DEL" ] && apk del $FOR_DEL --purge || true else FOR_DEL=$(opkg list-installed 2>/dev/null | cut -d' ' -f1 | grep -E "^(luci-app-${SHORT_NAME}|${SHORT_NAME}|luci-i18n-${SHORT_NAME}-zh-cn)($|[-_])") [ -n "$FOR_DEL" ] && opkg remove $FOR_DEL --force-remove-source-change --force-depends || true fi rm -rf "/etc/config/$SHORT_NAME" \ "/etc/$SHORT_NAME" \ "/etc/init.d/$SHORT_NAME" \ "/usr/lib/lua/luci/controller/$SHORT_NAME.lua" \ "/usr/share/luci/menu.d/luci-app-$SHORT_NAME.json" printf "%b[✓] %s 彻底卸载完成!%b\n" "$GREEN$BOLD" "$PLUGIN_NAME" "$RESET" } install_zh_cn() { printf "%b[+] 正在补全全系统简体中文语言包...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk update || true apk add --allow-untrusted luci-i18n-base-zh-cn || true for pkg in $(apk info | grep '^luci-app-'); do apk add "${pkg}-zh-cn" >/dev/null 2>&1 || true done else opkg update || true opkg install luci-i18n-base-zh-cn || true for pkg in $(opkg list-installed | cut -d' ' -f1 | grep '^luci-app-'); do opkg install "${pkg}-zh-cn" >/dev/null 2>&1 || true done fi printf "%b[✓] 所有 LuCI 插件中文语言包匹配完成!%b\n" "$GREEN$BOLD" "$RESET" } # 5. 模块化清晰菜单展示 printf "%b【 1. 代理 / 科学上网插件 】%b\n" "$GREEN$BOLD" "$RESET" printf " %b[1]%b 安装 PassWall (luci-app-passwall)\n" "$GREEN$BOLD" "$RESET" printf " %b[2]%b 安装 PassWall 2 (luci-app-passwall2)\n" "$GREEN$BOLD" "$RESET" printf " %b[3]%b 安装 OpenClash (luci-app-openclash)\n" "$GREEN$BOLD" "$RESET" printf " %b[4]%b 一键安装所有代理插件 (PassWall + PassWall2 + OpenClash)\n" "$GREEN$BOLD" "$RESET" printf "\n%b【 2. Docker 容器环境 】%b\n" "$BLUE$BOLD" "$RESET" printf " %b[5]%b 安装 Docker 引擎 + Compose (dockerd + compose)\n" "$BLUE$BOLD" "$RESET" printf " %b[6]%b 安装 Dockerman Web 控制台界面\n" "$BLUE$BOLD" "$RESET" printf " %b[7]%b 一键安装 Docker 全家桶 (引擎 + Compose + Dockerman界面)\n" "$BLUE$BOLD" "$RESET" printf "\n%b【 3. 软件源与系统工具 】%b\n" "$PURPLE$BOLD" "$RESET" printf " %b[8]%b 仅配置 PassWall 软件源\n" "$PURPLE$BOLD" "$RESET" printf " %b[9]%b 补全全系统插件中文语言包\n" "$PURPLE$BOLD" "$RESET" printf "\n%b【 4. 卸载管理 】%b\n" "$RED$BOLD" "$RESET" printf " %b[10]%b 彻底卸载 PassWall\n" "$RED$BOLD" "$RESET" printf " %b[11]%b 彻底卸载 PassWall 2\n" "$RED$BOLD" "$RESET" printf " %b[12]%b 彻底卸载 OpenClash\n" "$RED$BOLD" "$RESET" printf " %b[13]%b 一键彻底卸载所有代理插件\n" "$RED$BOLD" "$RESET" printf " %b[14]%b 仅卸载 Dockerman Web 界面\n" "$RED$BOLD" "$RESET" printf " %b[15]%b 仅卸载 Docker 引擎 (保留容器数据 /var/lib/docker)\n" "$RED$BOLD" "$RESET" printf " %b[16]%b 一键彻底卸载 Docker 全家桶 (引擎 + 界面)\n" "$RED$BOLD" "$RESET" printf "\n %b[0]%b 退出脚本\n" "$YELLOW$BOLD" "$RESET" printf "==================================================\n\n" printf "%b请输入选项 (支持多选,用空格分隔,如 %b1 5 6%b): %b" "$BOLD" "$GREEN$BOLD" "$RESET$BOLD" "$RESET" read -r CHOICES for CHOICE in $CHOICES; do case "$CHOICE" in 1) add_passwall_repo printf "%b[+] 开始安装 PassWall...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk add luci-app-passwall luci-i18n-passwall-zh-cn || true else opkg install luci-app-passwall || true fi ;; 2) add_passwall_repo printf "%b[+] 开始安装 PassWall 2...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk add luci-app-passwall2 luci-i18n-passwall2-zh-cn || true else opkg install luci-app-passwall2 || true fi ;; 3) install_openclash ;; 4) add_passwall_repo printf "%b[+] 开始一键安装所有代理插件...%b\n" "$YELLOW" "$RESET" if [ "$PKG_MGR" = "apk" ]; then apk add luci-app-passwall luci-app-passwall2 || true else opkg install luci-app-passwall luci-app-passwall2 || true fi install_openclash install_zh_cn ;; 5) install_docker_engine ;; 6) install_dockerman_ui ;; 7) install_docker_engine install_dockerman_ui ;; 8) add_passwall_repo ;; 9) install_zh_cn ;; 10) remove_plugin "luci-app-passwall" ;; 11) remove_plugin "luci-app-passwall2" ;; 12) remove_plugin "luci-app-openclash" ;; 13) remove_plugin "luci-app-passwall" remove_plugin "luci-app-passwall2" remove_plugin "luci-app-openclash" ;; 14) remove_dockerman_ui ;; 15) remove_docker_engine ;; 16) remove_dockerman_ui remove_docker_engine ;; 0) printf "%b已选择退出。%b\n" "$GREEN" "$RESET" exit 0 ;; *) printf "%b[!] 忽略无效选项: %s%b\n" "$RED" "$CHOICE" "$RESET" ;; esac done # 刷新 LuCI Web 界面缓存 rm -rf /tmp/luci-indexcache /tmp/luci-modulecache/ printf "\n%b==================================================\n" "$CYAN$BOLD" printf " 🎉 所选任务均已执行完成!已自动刷新 LuCI 缓存。\n" printf "==================================================%b\n" "$RESET"