自动切换网络代理的脚本

wen 实用脚本 2

本文目录导读:

自动切换网络代理的脚本

  1. 基于网络的自动代理切换脚本(macOS/Linux)
  2. 基于 ping 的去抖动版本(更稳定)
  3. Python 版本(跨平台)
  4. 使用方式

我来提供一个自动切换网络代理的脚本方案,以下是几种常见的实现方式:

基于网络的自动代理切换脚本(macOS/Linux)

#!/bin/bash
# 自动代理切换脚本 v1.0
# 适用于 macOS 和 Linux
# 配置区域
declare -A PROXIES=(
    ["work"]="http://192.168.1.100:8080"
    ["home"]="http://192.168.1.101:8080"
    ["public"]="http://proxy.company.com:3128"
)
# 网络检测函数
detect_network() {
    # 检测当前网络类型
    # 这里可以根据需要修改检测逻辑
    # 检测是否在公司网络
    if ping -c 1 -W 1 192.168.1.1 &>/dev/null; then
        echo "work"
    # 检测是否在家
    elif ping -c 1 -W 1 10.0.0.1 &>/dev/null; then
        echo "home"
    # 其他网络
    else
        echo "public"
    fi
}
# 设置系统代理
set_proxy() {
    local proxy_type=$1
    local proxy_url=${PROXIES[$proxy_type]}
    # macOS 使用 networksetup
    if [[ "$(uname)" == "Darwin" ]]; then
        networksetup -setwebproxy "Wi-Fi" "$(echo $proxy_url | cut -d'/' -f3 | cut -d':' -f1)" "$(echo $proxy_url | cut -d':' -f3)"
        networksetup -setsecurewebproxy "Wi-Fi" "$(echo $proxy_url | cut -d'/' -f3 | cut -d':' -f1)" "$(echo $proxy_url | cut -d':' -f3)"
    # Linux 使用 gsettings 或 proxychains
    else
        gsettings set org.gnome.system.proxy mode 'manual'
        gsettings set org.gnome.system.proxy.http host "$(echo $proxy_url | cut -d'/' -f3 | cut -d':' -f1)"
        gsettings set org.gnome.system.proxy.http port "$(echo $proxy_url | cut -d':' -f3)"
        gsettings set org.gnome.system.proxy.https host "$(echo $proxy_url | cut -d'/' -f3 | cut -d':' -f1)"
        gsettings set org.gnome.system.proxy.https port "$(echo $proxy_url | cut -d':' -f3)"
    fi
    echo "[$(date)] 切换到: $proxy_type 网络,使用代理: $proxy_url"
}
# 主函数
main() {
    local current_network=$(detect_network)
    echo "[$(date)] 检测到网络: $current_network"
    # 检查是否切换了网络
    if [[ "$current_network" != "$LAST_NETWORK" ]]; then
        set_proxy $current_network
        LAST_NETWORK=$current_network
    else
        echo "[$(date)] 网络未变化,保持当前代理设置"
    fi
    # 添加延迟避免频繁检测
    sleep 10
}
# 初始化
LAST_NETWORK=""
echo "[$(date)] 启动网络代理自动切换守护进程"
tskill -9 $$ 2>/dev/null
trap 'echo "脚本已停止"; exit' INT TERM
# 主循环
while true; do
    main
done

基于 ping 的去抖动版本(更稳定)

#!/bin/bash
# 稳定的代理切换脚本
# 使用多 ping 来确定网络状态
declare -A NETWORK_TARGETS=(
    ["work"]="192.168.1.1"
    ["home"]="10.0.0.1"
    ["public"]="8.8.8.8"
)
declare -A PROXIES=(
    ["work"]="http://proxy.work.com:8080"
    ["home"]="http://proxy.home.com:8080"
    ["public"]=""
)
# 使用多个 ping 检查网络稳定性
check_network_stable() {
    local target=$1
    local success=0
    local ping_count=5
    for ((i=1; i<=$ping_count; i++)); do
        if ping -c 1 -W 1 $target &>/dev/null; then
            success=$((success + 1))
        fi
        sleep 0.2
    done
    # 要求至少 80% 的成功率
    if (( success >= 4 )); then
        return 0
    else
        return 1
    fi
}
find_network() {
    for net in "${!NETWORK_TARGETS[@]}"; do
        if check_network_stable "${NETWORK_TARGETS[$net]}"; then
            echo $net
            return
        fi
    done
    echo "unknown"
}
# 应用代理设置(跨平台)
apply_proxy() {
    local proxy_address=$1
    if [[ -z "$proxy_address" ]]; then
        echo "关闭代理"
        # 关闭代理的代码...
        return
    fi
    # 提取 IP 和端口
    local ip=$(echo $proxy_address | sed 's|http://||' | cut -d: -f1)
    local port=$(echo $proxy_address | sed 's|http://||' | cut -d: -f2)
    if [[ "$(uname)" == "Darwin" ]]; then
        # macOS
        networksetup -setwebproxy "Wi-Fi" $ip $port
        networksetup -setsecurewebproxy "Wi-Fi" $ip $port
    else
        # Linux
        export http_proxy="$proxy_address"
        export https_proxy="$proxy_address"
        export HTTP_PROXY="$proxy_address"
        export HTTPS_PROXY="$proxy_address"
        if command -v gsettings &>/dev/null; then
            gsettings set org.gnome.system.proxy mode 'manual'
            gsettings set org.gnome.system.proxy.http host $ip
            gsettings set org.gnome.system.proxy.http port $port
            gsettings set org.gnome.system.proxy.https host $ip
            gsettings set org.gnome.system.proxy.https port $port
        fi
    fi
}
main() {
    local current_net=$(find_network)
    local proxy_url="${PROXIES[$current_net]}"
    if [[ "$current_net" != "$last_net" || "$proxy_url" != "$last_proxy" ]]; then
        echo "[$(date)] 网络变化: $last_net -> $current_net (代理: $proxy_url)"
        apply_proxy "$proxy_url"
        last_net=$current_net
        last_proxy=$proxy_url
    fi
    sleep 5
}
# 运行
last_net=""
last_proxy=""
echo "代理切换脚本启动 (PID: $$)"
while true; do
    main
done

Python 版本(跨平台)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import platform
import time
import os
import sys
class AutoProxySwitcher:
    def __init__(self):
        self.system = platform.system()
        self.config = {
            'work': {
                'test_ip': '192.168.1.1',
                'proxy': 'http://192.168.1.100:8080'
            },
            'home': {
                'test_ip': '10.0.0.1', 
                'proxy': 'http://192.168.1.101:8080'
            },
            'public': {
                'test_ip': '8.8.8.8',
                'proxy': ''  # 无代理
            }
        }
        self.current_network = None
    def ping_host(self, host, count=3):
        """Ping 测试主机"""
        if self.system == "Windows":
            cmd = ['ping', '-n', str(count), '-w', '1000', host]
        else:
            cmd = ['ping', '-c', str(count), '-W', '1', host]
        try:
            result = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            return result.returncode == 0
        except Exception as e:
            print(f"Ping 错误: {e}")
            return False
    def detect_network(self):
        """检测当前网络"""
        for network, config in self.config.items():
            if self.ping_host(config['test_ip']):
                return network
        return 'public'
    def set_proxy_mac(self, proxy_url):
        """macOS 设置代理"""
        if not proxy_url:
            # 关闭代理
            subprocess.run(['networksetup', '-setwebproxystate', 'Wi-Fi', 'off'])
            subprocess.run(['networksetup', '-setsecurewebproxystate', 'Wi-Fi', 'off'])
            return
        # 解析代理地址
        proxy_part = proxy_url.replace('http://', '').split(':')
        ip = proxy_part[0]
        port = proxy_part[1]
        subprocess.run(['networksetup', '-setwebproxy', 'Wi-Fi', ip, port])
        subprocess.run(['networksetup', '-setsecurewebproxy', 'Wi-Fi', ip, port])
    def set_proxy_linux(self, proxy_url):
        """Linux 设置代理"""
        if not proxy_url:
            os.environ.pop('http_proxy', None)
            os.environ.pop('https_proxy', None)
            return
        os.environ['http_proxy'] = proxy_url
        os.environ['https_proxy'] = proxy_url
        # 设置系统代理(如果使用 GNOME)
        if proxy_url:
            proxy_part = proxy_url.replace('http://', '').split(':')
            ip = proxy_part[0]
            port = proxy_part[1]
            subprocess.run(['gsettings', 'set', 'org.gnome.system.proxy', 'mode', 'manual'])
            subprocess.run(['gsettings', 'set', 'org.gnome.system.proxy.http', 'host', ip])
            subprocess.run(['gsettings', 'set', 'org.gnome.system.proxy.http', 'port', port])
    def set_proxy_windows(self, proxy_url):
        """Windows 设置代理(通过注册表)"""
        import winreg
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 
                           r'Software\Microsoft\Windows\CurrentVersion\Internet Settings', 
                           0, winreg.KEY_SET_VALUE)
        if proxy_url:
            winreg.SetValueEx(key, 'ProxyEnable', 0, winreg.REG_DWORD, 1)
            winreg.SetValueEx(key, 'ProxyServer', 0, winreg.REG_SZ, proxy_url)
        else:
            winreg.SetValueEx(key, 'ProxyEnable', 0, winreg.REG_DWORD, 0)
        # 通知系统更改
        import ctypes
        INTERNET_OPTION_SETTINGS_CHANGED = 39
        INTERNET_OPTION_REFRESH = 37
        internet_settings = ctypes.windll.Wininet.InternetSetOption
        internet_settings(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
        internet_settings(0, INTERNET_OPTION_REFRESH, 0, 0)
    def apply_proxy(self, proxy_url):
        """根据系统平台应用代理设置"""
        if self.system == "Darwin":
            self.set_proxy_mac(proxy_url)
        elif self.system == "Linux":
            self.set_proxy_linux(proxy_url)
        elif self.system == "Windows":
            self.set_proxy_windows(proxy_url)
        else:
            print(f"不支持的平台: {self.system}")
    def run(self):
        """主运行循环"""
        print(f"自动代理切换脚本启动 (PID: {os.getpid()})")
        while True:
            try:
                network = self.detect_network()
                proxy = self.config[network]['proxy']
                if network != self.current_network:
                    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 网络: {network}, 代理: {proxy}")
                    self.apply_proxy(proxy)
                    self.current_network = network
                # 等待 10 秒后再次检测
                time.sleep(10)
            except KeyboardInterrupt:
                print("\n脚本已停止")
                break
            except Exception as e:
                print(f"错误: {e}")
                time.sleep(5)
if __name__ == "__main__":
    switcher = AutoProxySwitcher()
    switcher.run()

使用方式

保存和执行

# 保存脚本
chmod +x auto_proxy_switch.sh
# 后台运行
nohup ./auto_proxy_switch.sh &
# 查看日志
tail -f /tmp/proxy_switch.log

配置自定义

根据你的网络环境修改配置:

  1. 修改检测目标(IP地址)
  2. 修改代理服务器地址和端口
  3. 调整检测频率
  4. 添加更多网络场景

集成到系统

macOS (launchd):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.proxyswitch</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/auto_proxy_switch.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

Linux (systemd):

[Unit]
Description=Auto Proxy Switch
[Service]
Type=simple
ExecStart=/path/to/auto_proxy_switch.sh
[Install]
WantedBy=multi-user.target

这个脚本会根据当前网络环境自动切换代理设置,适用于办公、家庭、公共网络等多种场景,你可以根据实际需求修改配置。

抱歉,评论功能暂时关闭!