2055 字
10 分钟
Shell脚本分享 - Linux Proxy服务器优化
NOTE

可以根据自己的服务器配置调整网络性能优化参数

脚本内容#

#!/usr/bin/env bash

# 启用严格模式
set -euo pipefail

# 定义日志文件
LOG_FILE="/var/log/server-optimization.log"
BACKUP_DIR="/root/system_backup"
NIC_CHECK_FILE="/var/log/network-check.log"

# 定义颜色输出
echo=echo
for cmd in echo /bin/echo; do
    $cmd >/dev/null 2>&1 || continue
    if ! $cmd -e "" | grep -qE '^-e'; then
        echo=$cmd
        break
    fi
done
CSI=$($echo -e "\033[")
CEND="${CSI}0m"
CDGREEN="${CSI}32m"
CRED="${CSI}1;31m"
CGREEN="${CSI}1;32m"
CYELLOW="${CSI}1;33m"
CBLUE="${CSI}1;34m"
CMAGENTA="${CSI}1;35m"
CCYAN="${CSI}1;36m"

# 输出函数
OUT_ALERT() { echo -e "${CYELLOW} $1 ${CEND}" | tee -a "$LOG_FILE"; }
OUT_ERROR() { echo -e "${CRED} $1 ${CEND}" | tee -a "$LOG_FILE"; }
OUT_INFO() { echo -e "${CCYAN} $1 ${CEND}" | tee -a "$LOG_FILE"; }
OUT_SUCCESS() { echo -e "${CGREEN} $1 ${CEND}" | tee -a "$LOG_FILE"; }

# 检查root权限
check_root() {
    if [[ $EUID -ne 0 ]]; then
        OUT_ERROR "[错误] 此脚本需要root权限运行"
        exit 1
    fi
}

# 检测系统类型
check_system() {
    if [[ -f /etc/redhat-release ]]; then
        release="centos"
    elif cat /etc/issue | grep -q -E -i "debian|raspbian"; then
        release="debian"
    elif cat /etc/issue | grep -q -E -i "ubuntu"; then
        release="ubuntu"
    elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat"; then
        release="centos"
    elif cat /proc/version | grep -q -E -i "raspbian|debian"; then
        release="debian"
    elif cat /proc/version | grep -q -E -i "ubuntu"; then
        release="ubuntu"
    elif cat /proc/version | grep -q -E -i "centos|red hat|redhat"; then
        release="centos"
    else
        OUT_ERROR "[错误] 不支持的操作系统!"
        exit 1
    fi
}

# 检查虚拟化环境
check_virtualization() {
    OUT_INFO "[信息] 检查虚拟化环境..."
    
    is_vm=0
    virt_type="none"
    
    # 检查常见虚拟化标志
    if systemd-detect-virt &>/dev/null; then
        virt_type=$(systemd-detect-virt)
        is_vm=1
    elif [ -f "/sys/hypervisor/type" ]; then
        virt_type=$(cat /sys/hypervisor/type)
        is_vm=1
    elif dmesg | grep -i "vmware\|kvm\|qemu\|virtio\|xen\|hyper-v" &>/dev/null; then
        if dmesg | grep -i "vmware" &>/dev/null; then
            virt_type="vmware"
        elif dmesg | grep -i "kvm\|qemu\|virtio" &>/dev/null; then
            virt_type="kvm"
        elif dmesg | grep -i "xen" &>/dev/null; then
            virt_type="xen"
        elif dmesg | grep -i "hyper-v" &>/dev/null; then
            virt_type="hyper-v"
        fi
        is_vm=1
    fi

    if [ $is_vm -eq 1 ]; then
        OUT_INFO "[信息] 检测到虚拟化环境: $virt_type"
    else
        OUT_INFO "[信息] 检测到物理机环境"
    fi
}

# 检查网卡类型
check_nic_type() {
    local interface=$1
    local is_virtio=0
    
    # 检查是否为virtio网卡
    if ethtool -i $interface 2>/dev/null | grep -q "driver: virtio"; then
        is_virtio=1
    elif lspci | grep -i "virtio" | grep -i "network" &>/dev/null; then
        is_virtio=1
    elif dmesg | grep -i "virtio.*network" | grep $interface &>/dev/null; then
        is_virtio=1
    fi
    
    echo $is_virtio
}

# 安装必要工具
install_requirements() {
    OUT_INFO "[信息] 安装必要工具..."
    if [[ ${release} == "centos" ]]; then
        yum install -y epel-release
        yum install -y ethtool wget net-tools curl chrony
    else
        apt-get update
        apt-get install -y ethtool wget net-tools curl chrony
    fi
    OUT_SUCCESS "[成功] 工具安装完成"
}

# 配置DNS - 根据区域选择不同的DNS服务器
configure_dns() {
    OUT_INFO "配置系统DNS..."

    read -p "是否使用国内DNS?(y/n): " use_cn_dns

    # 确保备份目录存在
    BACKUP_DIR="/root/system_backup"
    if [[ ! -d "${BACKUP_DIR}" ]]; then
        mkdir -p "${BACKUP_DIR}" || {
            OUT_ERROR "无法创建备份目录:${BACKUP_DIR}"
            exit 1
        }
    fi

    # 检查并移除符号链接或不可修改属性
    if [[ -L /etc/resolv.conf ]]; then
        rm -f /etc/resolv.conf
    elif [[ -f /etc/resolv.conf ]]; then
        chattr -i /etc/resolv.conf 2>/dev/null || true
        mv /etc/resolv.conf "${BACKUP_DIR}/resolv.conf.bak" || {
            OUT_ERROR "无法备份 /etc/resolv.conf 文件"
            exit 1
        }
    fi

    # 写入新的 DNS 配置
    if [[ "${use_cn_dns}" =~ ^[Yy]$ ]]; then
        # 国内DNS配置
        cat > /etc/resolv.conf << EOF
options timeout:2 attempts:3 rotate
nameserver 223.5.5.5
nameserver 223.6.6.6
nameserver 119.29.29.29
nameserver 180.76.76.76
EOF
        OUT_INFO "已配置国内DNS"
    else
        # 国外DNS配置
        cat > /etc/resolv.conf << EOF
options timeout:2 attempts:3 rotate
nameserver 1.1.1.1
nameserver 8.8.8.8
nameserver 9.9.9.9
nameserver 208.67.222.222
EOF
        OUT_INFO "已配置国际DNS"
    fi

    # 设置文件为不可修改
    chattr +i /etc/resolv.conf || {
        OUT_ERROR "无法设置 /etc/resolv.conf 为只读"
        exit 1
    }

    OUT_SUCCESS "DNS配置完成"
}

# 配置NTP - 根据区域选择不同的NTP服务器
configure_ntp() {
    OUT_INFO "配置NTP时间同步..."

    read -p "是否使用国内NTP服务器?(y/n): " use_cn_ntp

    # 使用真实服务名称 chrony.service
    NTP_SERVICE="chrony.service"

    if [[ "${use_cn_ntp}" =~ ^[Yy]$ ]]; then
        # 国内NTP配置
        cat > /etc/chrony.conf << EOF
server ntp.aliyun.com iburst
server cn.ntp.org.cn iburst
server ntp.tencent.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOF
        OUT_INFO "已配置国内NTP服务器"
    else
        # 国外NTP配置
        cat > /etc/chrony.conf << EOF
pool pool.ntp.org iburst
pool time.google.com iburst
pool time.cloudflare.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOF
        OUT_INFO "已配置国际NTP服务器"
    fi

    # 启用并重启服务
    systemctl enable "${NTP_SERVICE}" || {
        OUT_ERROR "无法启用 NTP 服务:${NTP_SERVICE}"
        exit 1
    }
    systemctl restart "${NTP_SERVICE}" || {
        OUT_ERROR "无法重启 NTP 服务:${NTP_SERVICE}"
        exit 1
    }

    OUT_SUCCESS "NTP配置完成"
}

# 检查网卡特性和兼容性
declare -A NIC_FEATURES
check_nic_compatibility() {
    local interface=$1
    OUT_INFO "[信息] 检查网卡 $interface 的特性支持情况..."
    
    # 获取网卡基本信息
    local driver=$(ethtool -i $interface 2>/dev/null | grep "^driver:" | cut -d: -f2 | tr -d ' ')
    local version=$(ethtool -i $interface 2>/dev/null | grep "^version:" | cut -d: -f2 | tr -d ' ')
    local firmware=$(ethtool -i $interface 2>/dev/null | grep "^firmware-version:" | cut -d: -f2 | tr -d ' ')
    
    OUT_INFO "网卡信息: 驱动=$driver, 版本=$version, 固件=$firmware"
    
    # 检查各项特性支持
    local features=""
    
    # 检查TSO支持
    if ethtool -k $interface 2>/dev/null | grep -q "tcp-segmentation-offload: on"; then
        features+="tso "
        NIC_FEATURES[$interface]+="tso "
    fi
    
    # 检查GSO支持
    if ethtool -k $interface 2>/dev/null | grep -q "generic-segmentation-offload: on"; then
        features+="gso "
        NIC_FEATURES[$interface]+="gso "
    fi
    
    # 检查GRO支持
    if ethtool -k $interface 2>/dev/null | grep -q "generic-receive-offload: on"; then
        features+="gro "
        NIC_FEATURES[$interface]+="gro "
    fi
    
    # 检查队列大小调整支持
    if ethtool -g $interface &>/dev/null; then
        features+="queue "
        NIC_FEATURES[$interface]+="queue "
    fi
    
    # 检查中断合并支持
    if ethtool -c $interface &>/dev/null; then
        features+="coalesce "
        NIC_FEATURES[$interface]+="coalesce "
    fi
    
    # 输出支持的特性
    OUT_INFO "支持的特性: $features"
    
    # 检查是否是较新的网卡
    local is_modern=0
    if [[ $features == *"tso"* && $features == *"gso"* && $features == *"gro"* ]]; then
        is_modern=1
        OUT_INFO "检测结果: 现代网卡,支持完整优化"
    else
        OUT_INFO "检测结果: 较老的网卡,将使用基础优化"
    fi
    
    # 返回是否是现代网卡
    echo $is_modern
}
# 创建一个开机自动执行的网卡优化脚本
optimize_network() {
    OUT_INFO "[信息] 配置网卡优化..."
    
    # 创建网卡优化脚本
    cat > /etc/network/if-up.d/network-optimize << 'EOF'
#!/bin/bash

# 只在网卡启动时执行优化
[ "$IFACE" = lo ] && exit 0
[ "$MODE" != start ] && exit 0

# 获取网卡类型
is_virtio=0
if ethtool -i $IFACE 2>/dev/null | grep -q "driver: virtio"; then
    is_virtio=1
fi

# 基础优化
ethtool -K $IFACE rx-checksumming on 2>/dev/null || true
ethtool -K $IFACE tx-checksumming on 2>/dev/null || true
ethtool -K $IFACE scatter-gather on 2>/dev/null || true

if [ $is_virtio -eq 1 ]; then
    # virtio网卡优化
    ethtool -K $IFACE gso off 2>/dev/null || true
    ethtool -K $IFACE tso off 2>/dev/null || true
    ethtool -K $IFACE gro off 2>/dev/null || true
    ethtool -C $IFACE rx-usecs 50 tx-usecs 50 2>/dev/null || true
else
    # 物理网卡优化
    if ethtool -k $IFACE | grep -q "tcp-segmentation-offload: on"; then
        ethtool -K $IFACE tso on 2>/dev/null || true
        ethtool -K $IFACE gso on 2>/dev/null || true
    fi
    ethtool -K $IFACE gro off 2>/dev/null || true
    ethtool -G $IFACE rx 4096 tx 4096 2>/dev/null || true
    ethtool -C $IFACE adaptive-rx off adaptive-tx off \
            rx-usecs 100 tx-usecs 100 \
            rx-frames 64 tx-frames 64 2>/dev/null || true
fi

# CPU亲和性优化
if [ -d "/sys/class/net/$IFACE/queues" ]; then
    num_cores=$(nproc)
    core_mask=0
    for ((i=0; i<num_cores; i++)); do
        core_mask=$((core_mask | (1<<i)))
    done
    core_mask=$(printf "%x" $core_mask)
    
    # 设置RPS/XPS
    for rx_queue in /sys/class/net/$IFACE/queues/rx-*/rps_cpus; do
        echo $core_mask > $rx_queue 2>/dev/null || true
    done
    for tx_queue in /sys/class/net/$IFACE/queues/tx-*/xps_cpus; do
        echo $core_mask > $tx_queue 2>/dev/null || true
    done
    
    # 设置RFS
    echo 32768 > /proc/sys/net/core/rps_sock_flow_entries 2>/dev/null || true
    for rx_queue in /sys/class/net/$IFACE/queues/rx-*/rps_flow_cnt; do
        echo 4096 > $rx_queue 2>/dev/null || true
    done
fi

# 关闭流控
ethtool -A $IFACE rx off tx off 2>/dev/null || true
EOF

    # 设置执行权限
    chmod +x /etc/network/if-up.d/network-optimize
    
    # 立即对当前网卡执行优化
    for interface in $(ls /sys/class/net/ | grep -v '^lo$'); do
        IFACE=$interface MODE=start /etc/network/if-up.d/network-optimize
    done
    
    OUT_SUCCESS "[成功] 网卡优化配置完成"
}

# 系统参数优化
optimize_system() {
    OUT_INFO "[信息] 优化系统参数..."
    
    # 配置sysctl参数
    cat > /etc/sysctl.conf << 'EOF'
# 基础网络参数
net.ipv4.ip_forward = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 20
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_tw_buckets = 550000
net.ipv4.tcp_max_syn_backlog = 30000
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_fastopen = 3

# TCP内存设置
net.ipv4.tcp_mem = 786432 1048576 1572864
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.tcp_wmem = 4096 87380 33554432
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.core.netdev_max_backlog = 50000
net.core.somaxconn = 65535

# TCP拥塞控制
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_dsack = 1

# 路由设置
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# 文件描述符限制
fs.file-max = 2097152
fs.nr_open = 2097152
fs.inotify.max_user_instances = 8192
fs.inotify.max_user_watches = 524288
fs.pipe-max-size = 1048576

# 内存参数
vm.swappiness = 10
vm.min_free_kbytes = 65536
vm.overcommit_memory = 1
vm.max_map_count = 262144
EOF

    # 配置系统限制 - 更高的限制
    cat > /etc/security/limits.conf << 'EOF'
* soft nofile 2097152
* hard nofile 2097152
* soft nproc 2097152
* hard nproc 2097152
root soft nofile 2097152
root hard nofile 2097152
root soft nproc 2097152
root hard nproc 2097152
* soft memlock unlimited
* hard memlock unlimited
EOF
    
    # 确保PAM加载limits配置
    if [[ -f /etc/pam.d/common-session ]]; then
        grep -q '^session.*pam_limits.so$' /etc/pam.d/common-session || \
        echo "session required pam_limits.so" >> /etc/pam.d/common-session
    fi
    
    # 应用sysctl参数
    sysctl -p
    
    OUT_SUCCESS "[成功] 系统参数优化完成"
}

# 主函数
main() {
    OUT_INFO "[信息] 开始系统优化..."
    
    # 基础检查
    check_root
    check_system
    check_virtualization
    install_requirements
    
    # 系统配置
    configure_dns
    configure_ntp
    
    # 性能优化
    optimize_system
    optimize_network
    
    OUT_SUCCESS "[成功] 系统优化完成!"
    OUT_INFO "[信息] 建议重启系统使所有优化生效"
}

# 运行主函数
main
Shell脚本分享 - Linux Proxy服务器优化
https://devniko.com/posts/shell-share-proxyserveroptimize/
作者
Niko
发布于
2024-04-01
许可协议
CC BY-NC-SA 4.0