chore: allowlist trusted plugins
This commit is contained in:
Executable
+206
@@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# mihomo-guard.sh
|
||||
# 自动保活 + 自动刷新订阅 + 自动切换可用线路
|
||||
#
|
||||
# 目标:
|
||||
# - 定期通过 mihomo 代理探测 Telegram 官方入口连通性
|
||||
# - 连续失败后,自动刷新订阅并切换到候选节点
|
||||
# - 若切换后仍失败,再 fallback 重启 mihomo
|
||||
#
|
||||
# 说明:
|
||||
# - 依赖 mihomo external-controller API (9090)
|
||||
# - 当前按你的环境写死了 controller / secret / provider / group 名称
|
||||
|
||||
# ===== 可调参数 =====
|
||||
|
||||
PROBE_URL="https://api.telegram.org"
|
||||
PROXY_ADDR="http://127.0.0.1:7897"
|
||||
PROBE_TIMEOUT=4
|
||||
SLEEP_INTERVAL=15
|
||||
MAX_FAIL_COUNT=5
|
||||
|
||||
MIHOMO_BIN="/usr/local/opt/mihomo/bin/mihomo"
|
||||
MIHOMO_DIR="/usr/local/etc/mihomo"
|
||||
LOG_FILE="/usr/local/var/mihomo-guard.log"
|
||||
|
||||
# Mihomo controller API
|
||||
CONTROLLER_URL="http://127.0.0.1:9090"
|
||||
CONTROLLER_SECRET="123456"
|
||||
SUB_PROVIDER="my_sub"
|
||||
|
||||
# 代理组名称(基于你当前 API 返回)
|
||||
MANUAL_GROUP="手动选择"
|
||||
AI_GROUP="🤖 AI服务"
|
||||
DEV_GROUP="💻 开发服务"
|
||||
|
||||
# 故障恢复时优先尝试的候选节点(亚洲优先)
|
||||
CANDIDATE_PROXIES=(
|
||||
"🇭🇰香港01-IPv6|AI"
|
||||
"🇭🇰香港03-IPv6|AI"
|
||||
"🇭🇰香港05-流媒体解锁|AI"
|
||||
"🇸🇬新加坡01-流媒体解锁|AI"
|
||||
"🇸🇬新加坡02-流媒体解锁|AI"
|
||||
"🇨🇳台湾03-流媒体解锁|AI"
|
||||
"🇨🇳台湾04-流媒体解锁|AI"
|
||||
"🇯🇵日本03"
|
||||
"🇯🇵日本01"
|
||||
)
|
||||
|
||||
FAIL_COUNT=0
|
||||
LAST_SWITCH_INDEX=-1
|
||||
|
||||
log() {
|
||||
local ts
|
||||
ts="$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo "[$ts] $*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
api_call() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local data="${3:-}"
|
||||
|
||||
if [ -n "$data" ]; then
|
||||
curl -sS -X "$method" \
|
||||
-H "Authorization: Bearer $CONTROLLER_SECRET" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$data" \
|
||||
"$CONTROLLER_URL$path"
|
||||
else
|
||||
curl -sS -X "$method" \
|
||||
-H "Authorization: Bearer $CONTROLLER_SECRET" \
|
||||
"$CONTROLLER_URL$path"
|
||||
fi
|
||||
}
|
||||
|
||||
probe_once() {
|
||||
curl -x "$PROXY_ADDR" -m "$PROBE_TIMEOUT" -sS "$PROBE_URL" >/dev/null
|
||||
}
|
||||
|
||||
refresh_subscription() {
|
||||
log "[ACTION] Refreshing provider: $SUB_PROVIDER"
|
||||
api_call PUT "/providers/proxies/$SUB_PROVIDER" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
switch_group_to() {
|
||||
local group_name="$1"
|
||||
local target_proxy="$2"
|
||||
|
||||
log "[ACTION] Switching group [$group_name] -> [$target_proxy]"
|
||||
api_call PUT "/proxies/$group_name" "{\"name\":\"$target_proxy\"}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
try_switch_routes() {
|
||||
log "[ACTION] Starting provider refresh + route switching workflow"
|
||||
|
||||
refresh_subscription
|
||||
sleep 3
|
||||
|
||||
local total=${#CANDIDATE_PROXIES[@]}
|
||||
local i
|
||||
for ((i=1; i<=total; i++)); do
|
||||
local idx=$(((LAST_SWITCH_INDEX + i) % total))
|
||||
local candidate="${CANDIDATE_PROXIES[$idx]}"
|
||||
|
||||
log "[INFO] Trying candidate proxy: $candidate"
|
||||
|
||||
# 1) 手动选择 -> 指定节点
|
||||
switch_group_to "$MANUAL_GROUP" "$candidate"
|
||||
sleep 1
|
||||
|
||||
# 2) 关键业务组切到手动选择,避免继续受 URLTest 组影响
|
||||
switch_group_to "$AI_GROUP" "$MANUAL_GROUP"
|
||||
sleep 1
|
||||
switch_group_to "$DEV_GROUP" "$MANUAL_GROUP"
|
||||
sleep 1
|
||||
|
||||
# 给 mihomo 一点时间收敛
|
||||
sleep 3
|
||||
|
||||
if probe_once; then
|
||||
LAST_SWITCH_INDEX=$idx
|
||||
log "[OK] Probe success after switching to [$candidate]"
|
||||
log "[RECOVERED] 当前恢复到线路: [$candidate]"
|
||||
return 0
|
||||
else
|
||||
log "[WARN] Probe still failed after switching to [$candidate]"
|
||||
fi
|
||||
done
|
||||
|
||||
log "[ERROR] All candidate proxies failed after refresh + switching"
|
||||
return 1
|
||||
}
|
||||
|
||||
restart_mihomo() {
|
||||
log "[ACTION] Restarting mihomo..."
|
||||
|
||||
if pgrep -f "$MIHOMO_BIN" >/dev/null 2>&1; then
|
||||
log "[INFO] Existing mihomo process found, sending TERM"
|
||||
pkill -f "$MIHOMO_BIN" || log "[WARN] pkill mihomo returned non-zero"
|
||||
sleep 3
|
||||
else
|
||||
log "[INFO] No existing mihomo process found"
|
||||
fi
|
||||
|
||||
if [ ! -x "$MIHOMO_BIN" ]; then
|
||||
log "[ERROR] mihomo binary not found or not executable: $MIHOMO_BIN"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$MIHOMO_DIR" ]; then
|
||||
log "[ERROR] mihomo directory not found: $MIHOMO_DIR"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "[INFO] Starting mihomo with: $MIHOMO_BIN -d $MIHOMO_DIR"
|
||||
nohup "$MIHOMO_BIN" -d "$MIHOMO_DIR" >>"$LOG_FILE" 2>&1 &
|
||||
sleep 3
|
||||
|
||||
if pgrep -f "$MIHOMO_BIN" >/dev/null 2>&1; then
|
||||
log "[INFO] mihomo started successfully (pid: $(pgrep -f "$MIHOMO_BIN" | tr '\n' ' '))"
|
||||
else
|
||||
log "[ERROR] Failed to start mihomo"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 5
|
||||
|
||||
if probe_once; then
|
||||
log "[OK] Probe success after mihomo restart"
|
||||
log "[RECOVERED] 当前恢复到线路: [mihomo重启后默认线路]"
|
||||
return 0
|
||||
else
|
||||
log "[WARN] Probe still failed after mihomo restart"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
log "=== mihomo-guard started (PROXY=$PROXY_ADDR, URL=$PROBE_URL, INTERVAL=${SLEEP_INTERVAL}s, MAX_FAIL=$MAX_FAIL_COUNT) ==="
|
||||
log "=== controller=$CONTROLLER_URL provider=$SUB_PROVIDER manual_group=$MANUAL_GROUP ==="
|
||||
|
||||
while true; do
|
||||
if probe_once; then
|
||||
if [ "$FAIL_COUNT" -gt 0 ]; then
|
||||
log "[OK] Probe success after $FAIL_COUNT failure(s)"
|
||||
fi
|
||||
FAIL_COUNT=0
|
||||
else
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
log "[WARN] Probe failed ($FAIL_COUNT/$MAX_FAIL_COUNT)"
|
||||
|
||||
if [ "$FAIL_COUNT" -ge "$MAX_FAIL_COUNT" ]; then
|
||||
log "[WARN] Consecutive probe failures reached $FAIL_COUNT, trying refresh + route switch"
|
||||
|
||||
if try_switch_routes; then
|
||||
FAIL_COUNT=0
|
||||
else
|
||||
log "[WARN] Refresh + route switch failed, falling back to mihomo restart"
|
||||
restart_mihomo || log "[ERROR] Restart fallback did not recover probe"
|
||||
FAIL_COUNT=0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep "$SLEEP_INTERVAL"
|
||||
done
|
||||
Reference in New Issue
Block a user