Shell脚本-设置代理

最近业务中常常需要编写一些脚本,故有此文,懒人必备~

#!/bin/bash
# 脚本名称: 设置代理
# 描述: 设置APT、docker以及Service服务代理
# 版本: 1.0
# 作者: Cikaros
# 邮箱: Cikaros<at>qq.com
# 日期: 2024-11-18
# 版权: (C) 2024 Your Company. All rights reserved.

# 定义函数来获取需要网络访问的活动服务
get_network_dependent_services() {
    # 初始化服务数组
    local services=()

    # 遍历所有活动的服务
    while IFS= read -r service; do
        # 获取服务文件的路径
        local service_file=$(systemctl show -p FragmentPath "$service" 2>/dev/null | cut -d'=' -f2)
        
        # 检查服务文件是否存在
        if [[ -f "$service_file" ]]; then
            # 检查服务文件是否包含网络依赖
            if grep -q -E 'Wants=network-online.target|After=network.target' "$service_file"; then
                services+=("$service")
            fi
        fi
    done < <(systemctl list-units --type=service --state=active | awk 'NR>1 {print $1}')

    # 返回结果
    echo "${services[@]}"
}

# 检查jq命令是否可用
check_jq_installed() {
    if ! command -v jq &> /dev/null; then
        echo "jq 命令未安装,请先安装 jq。"
        echo "在 Debian/Ubuntu 上可以使用以下命令安装:sudo apt-get install jq"
        echo "在 CentOS/RHEL 上可以使用以下命令安装:sudo yum install jq"
        exit 1
    fi
}

# 定义设置Docker代理的函数
set_docker_proxy() {
    local docker_no_proxy=${1:-$no_proxy_list}
    local docker_config_file="/etc/docker/daemon.json"
    
    read -p "Docker的排除代理列表(默认使用全局设置): " user_docker_no_proxy
    docker_no_proxy=${user_docker_no_proxy:-$docker_no_proxy}
    
    # 检查文件是否存在
    if [ -f "$docker_config_file" ]; then
        # 读取现有配置
        existing_config=$(cat $docker_config_file)
        
        # 检查是否已经存在代理配置
        if ! echo "$existing_config" | grep -q '"proxies"'; then
            # 追加代理配置
            new_config=$(jq --arg proxy "$proxy_address" --arg no_proxy "$docker_no_proxy" '. + {"proxies": {"default": {"httpProxy": $proxy, "httpsProxy": $proxy, "noProxy": $no_proxy}}}' <<< "$existing_config")
            sudo tee $docker_config_file > /dev/null <<< "$new_config"
        else
            echo "Docker代理配置已存在,不会重复添加。"
        fi
    else
        # 文件不存在,创建新文件
        sudo tee $docker_config_file > /dev/null <<EOF
{
  "proxies": {
    "default": {
      "httpProxy": "$proxy_address",
      "httpsProxy": "$proxy_address",
      "noProxy": "$docker_no_proxy"
    }
  }
}
EOF
    fi
    
    sudo systemctl restart docker
    echo "Docker代理已设置完成。"
}

# 定义设置Apt代理的函数
set_apt_proxy() {
    local apt_no_proxy=${1:-$no_proxy_list}
    local apt_config_file="/etc/apt/apt.conf.d/proxy.conf"
    
    read -p "Apt的排除代理列表(默认使用全局设置): " user_apt_no_proxy
    apt_no_proxy=${user_apt_no_proxy:-$apt_no_proxy}
    
    sudo tee $apt_config_file > /dev/null <<EOF
Acquire::http::Proxy "$proxy_address";
Acquire::https::Proxy "$proxy_address";
Acquire::http::No-Cache true;
Acquire::http::Pipeline-Depth 0;
Acquire::http::Dl-Limit 0;
Acquire::ftp::Proxy "DIRECT";
Acquire::http::Proxy::${apt_no_proxy//,/ } DIRECT;
Acquire::https::Proxy::${apt_no_proxy//,/ } DIRECT;
EOF
    echo "Apt代理已设置完成。"
}


# 定义设置Service代理的函数
set_service_proxy() {
    local service_no_proxy=${1:-$no_proxy_list}
    
    # 获取所有活动的服务
    network_services=$(get_network_dependent_services)
    
    # 列出所有活动的服务并标上序号
    echo "请选择需要设置代理的服务(输入序号,多个序号用空格分隔,输入 q 退出):"
    select service in $network_services "退出"; do
        if [ "$service" = "退出" ]; then
            break
        elif [ -n "$service" ]; then
            read -p "该服务的排除代理列表(默认使用全局设置): " user_service_no_proxy
            service_no_proxy=${user_service_no_proxy:-$service_no_proxy}
            
            # 创建或编辑服务的环境文件
            env_file="/etc/systemd/system/${service}.env"
            if [ -f "$env_file" ]; then
                # 读取现有配置
                existing_env=$(cat $env_file)
                
                # 检查是否已经存在代理配置
                if ! echo "$existing_env" | grep -q 'HTTP_PROXY='; then
                    # 追加代理配置
                    echo "HTTP_PROXY=$proxy_address" >> $env_file
                    echo "HTTPS_PROXY=$proxy_address" >> $env_file
                    echo "NO_PROXY=$service_no_proxy" >> $env_file
                else
                    echo "服务 $service 的代理配置已存在,不会重复添加。"
                fi
            else
                # 文件不存在,创建新文件
                sudo tee $env_file > /dev/null <<EOF
HTTP_PROXY=$proxy_address
HTTPS_PROXY=$proxy_address
NO_PROXY=$service_no_proxy
EOF
            fi
            
            sudo systemctl daemon-reload
            sudo systemctl restart $service
            echo "服务 $service 的代理已设置完成。"
        else
            echo "无效的选择,请重新输入。"
        fi
    done
}

# 主程序
main() {
    check_jq_installed
    
    read -p "是否为Docker设置代理?[y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        set_docker_proxy
    fi

    read -p "是否为Apt设置代理?[y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        set_apt_proxy
    fi

    read -p "是否为通过systemctl启动的服务设置代理?[y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        set_service_proxy
    fi

    echo "所有配置已完成。"
}

# 获取用户输入的代理地址
read -p "请输入代理地址(例如 http://127.0.0.1:7890/): " proxy_address

# 检查代理地址是否为空
if [ -z "$proxy_address" ]; then
    echo "代理地址不能为空,请重新运行脚本并提供有效的代理地址。"
    exit 1
fi

# 设置默认排除列表
default_no_proxy="localhost,127.0.0.1,::1"

# 全局询问排除代理的列表
read -p "请输入需要排除代理的列表(默认为 $default_no_proxy,多个地址用逗号分隔): " no_proxy_list
no_proxy_list=${no_proxy_list:-$default_no_proxy}

# 执行主程序
main

Shell脚本-设置代理
https://blog.cikaros.top/doc/3a833b84.html
作者
Cikaros
发布于
2024年11月18日
许可协议