@ユメイ9 月前

12/17
00:54
internet

Linux tuning

查看状态:/usr/local/sbin/vps-proxy-tune status

bash <<'VPS_INSTALL'
set -e

if [ "$(id -u)" -ne 0 ]; then
    echo "请先执行 sudo -i 切换到 root,再粘贴本段。"
    exit 1
fi

mkdir -p /usr/local/sbin
VPS_SCRIPT_TMP=$(mktemp /usr/local/sbin/.vps-proxy-tune.XXXXXX)
trap 'rm -f "$VPS_SCRIPT_TMP"' EXIT

cat > "$VPS_SCRIPT_TMP" <<'VPS_SCRIPT'
#!/usr/bin/env bash
# VPS proxy network tuning v2.0.0
# Debian 10+ / Ubuntu 18.04+ / Bash 4.4+

ETC=/etc
PROC=/proc
STATE=/var/lib/vps-proxy-tune
RUN=/run
CONF_NAME=99-zz-vps-proxy-tune.conf
PROFILE=balanced
CC=auto
QDISC=fq
TFO=keep
NOFILE=65536
BUFFER_MIB=0
SERVICE_MODE=auto
ALLOW_CONTAINER=0
ACTION=plan
TXN=
ACTIVE_TXN=0
SYSTEMD=0
SKIPPED=0
declare -a SERVICES=() KEYS=()
declare -A VALUES=() SEEN_SERVICES=()

info() { printf '[INFO] %s\n' "$*"; }
warn() { printf '[WARN] %s\n' "$*" >&2; }
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
normalize() { awk '{$1=$1; print}'; }
read_key() { sysctl -n "$1" 2>/dev/null | normalize; }
has_cc() {
    [[ " $(read_key net.ipv4.tcp_available_congestion_control) " == *" $1 "* ]]
}

usage() {
    cat <<'HELP'
VPS 代理网络调优

用法:
  vps-proxy-tune plan               只读预览
  vps-proxy-tune apply              应用配置
  vps-proxy-tune status             查看状态
  vps-proxy-tune restore            撤销最近一次应用

选项:
  --profile balanced|throughput    默认 balanced
  --buffer-mib 1..256              显式设置缓冲上限 MiB
  --cc auto|bbr|cubic|keep          默认 auto
  --qdisc fq|keep                  默认 fq
  --tfo keep|on|off                默认 keep
  --service UNIT                   指定服务,可重复
  --no-services                    不新增服务限制
  --nofile 1024..1048576            默认 65536
  --allow-container                显式允许容器内尽力应用

示例:
  vps-proxy-tune apply --service realm.service
  vps-proxy-tune apply --profile throughput --buffer-mib 32

说明:
  无参数只读预览;apply/restore 需要 root。
  不安装代理软件,不重启代理,不改防火墙、路由、转发和 RPS/XPS。
  NOFILE 在服务下次重启后生效;BBR 主要影响新建 TCP 连接。
  default_qdisc=fq 不代表当前网卡队列已经被替换。
  balanced 按内存分档使用 4/8/16/32 MiB,throughput 翻倍。
  缓冲上限可能比原设置低,应结合带宽、RTT 和并发数实测。
  keep 表示本次不管理对应键;重新 apply 会重建本工具的 sysctl 文件。
  要彻底撤销上次配置,请先 restore,再应用新的参数。
  服务限制增量管理;--no-services 不删除上次创建的限制。
  外部配置可能在开机后覆盖参数,请重启后用 status 核验。
  回滚不卸载内核模块,不重启代理进程。
  回滚会覆盖已记录键/文件在 apply 后的人工修改。
HELP
}

number_in_range() {
    [[ $1 =~ ^[0-9]{1,10}$ ]] &&
        (( 10#$1 >= $2 && 10#$1 <= $3 ))
}

parse_args() {
    if (($#)) && [[ $1 != --* ]]; then
        ACTION=$1
        shift
    fi

    case "$ACTION" in
        help|-h) usage; exit 0 ;;
        plan|apply|status|restore) ;;
        *) die "未知操作:$ACTION" ;;
    esac

    while (($#)); do
        case "$1" in
            --help|-h) usage; exit 0 ;;
            --allow-container)
                ALLOW_CONTAINER=1
                shift
                continue
                ;;
            --no-services)
                SERVICE_MODE=none
                shift
                continue
                ;;
            --profile|--cc|--qdisc|--tfo|--nofile|--buffer-mib|--service)
                (($# >= 2)) || die "$1 缺少值"
                ;;
            *) die "未知选项:$1" ;;
        esac

        case "$1" in
            --profile) PROFILE=$2 ;;
            --cc) CC=$2 ;;
            --qdisc) QDISC=$2 ;;
            --tfo) TFO=$2 ;;
            --nofile)
                number_in_range "$2" 1024 1048576 ||
                    die 'NOFILE 超出范围'
                NOFILE=$((10#$2))
                ;;
            --buffer-mib)
                number_in_range "$2" 1 256 ||
                    die 'buffer-mib 超出范围'
                BUFFER_MIB=$((10#$2))
                ;;
            --service)
                [[ $2 =~ ^[a-zA-Z0-9_:][a-zA-Z0-9_.:@-]*\.service$ &&
                   $2 != *@.service ]] ||
                    die '服务名须为具体 .service 单元'
                SERVICES+=("$2")
                ;;
        esac
        shift 2
    done

    case "$PROFILE" in
        balanced|throughput) ;;
        *) die '未知 profile' ;;
    esac
    case "$CC" in
        auto|bbr|cubic|keep) ;;
        *) die '未知 cc' ;;
    esac
    case "$QDISC" in
        fq|keep) ;;
        *) die '未知 qdisc' ;;
    esac
    case "$TFO" in
        keep|on|off) ;;
        *) die '未知 tfo' ;;
    esac

    if ((${#SERVICES[@]})); then
        [[ $SERVICE_MODE != none ]] ||
            die '--service 与 --no-services 不可同时使用'
        SERVICE_MODE=explicit
    fi
}

detect() {
    local ID=unknown PRETTY_NAME=unknown VERSION_ID=unknown
    local unit status

    [[ -r $ETC/os-release ]] || die '缺少 /etc/os-release'
    . "$ETC/os-release"

    case "$ID" in
        debian|ubuntu) ;;
        *) die "仅面向 Debian / Ubuntu;检测为 $ID" ;;
    esac

    info "$PRETTY_NAME | kernel $(uname -r) | $(uname -m)"

    RAM_MB=$(awk '/^MemTotal:/ {printf "%.0f", $2/1024}' "$PROC/meminfo")
    [[ $RAM_MB =~ ^[0-9]+$ ]] || die '无法读取内存容量'
    info "内存 ${RAM_MB} MiB;按实际内核能力检测"

    CONTAINER=0
    if command -v systemd-detect-virt >/dev/null 2>&1 &&
        systemd-detect-virt --container --quiet; then
        CONTAINER=1
    elif [[ -e /.dockerenv || -e /run/.containerenv || -e $PROC/vz ]]; then
        CONTAINER=1
    fi

    if ((CONTAINER)); then
        warn '容器可能共享宿主内核或受 cgroup 限制'
        RAM_MB=256
        if [[ $ACTION == apply && $ALLOW_CONTAINER == 0 ]]; then
            die '容器应用须显式传入 --allow-container'
        fi
    fi

    if [[ -d $RUN/systemd/system ]] &&
        command -v systemctl >/dev/null 2>&1; then
        SYSTEMD=1
    fi

    if [[ $SERVICE_MODE == explicit && $SYSTEMD == 0 ]]; then
        die '显式服务配置需要正在运行的 systemd'
    fi

    if ((SYSTEMD)) && [[ $SERVICE_MODE == auto ]]; then
        while read -r unit _; do
            case "$unit" in
                realm.service|realm-server.service|realm@?*.service|shadowsocks-rust.service|shadowsocks-rust@?*.service|shadowsocks.service|shadowsocks@?*.service|ssserver.service|ssserver@?*.service|xray.service|xray@?*.service|sing-box.service|sing-box@?*.service|hysteria-server.service|hysteria-server@?*.service|tuic.service)
                    SERVICES+=("$unit")
                    ;;
            esac
        done < <(
            systemctl list-unit-files --type=service \
                --no-legend --no-pager 2>/dev/null
            systemctl list-units --type=service --all \
                --no-legend --no-pager --plain 2>/dev/null
        )
    fi

    local -a valid=()
    for unit in "${SERVICES[@]}"; do
        [[ -z ${SEEN_SERVICES[$unit]:-} ]] || continue
        SEEN_SERVICES[$unit]=1

        status=$(systemctl show "$unit" -p LoadState 2>/dev/null) ||
            status=

        if [[ $status != LoadState=loaded ]]; then
            [[ $SERVICE_MODE != explicit ]] ||
                die "服务未加载或不存在:$unit"
            continue
        fi
        valid+=("$unit")
    done
    SERVICES=("${valid[@]}")

    if [[ -e $ETC/sysctl.d/99-ss-optimization.conf ||
          -e $ETC/systemd/system/ss-network-tuning.service ]]; then
        warn '检测到原版 ss-network 配置'
        [[ $ACTION != apply ]] ||
            die '请先核查旧版备份、停用旧调优服务并处理旧配置,避免两套配置相互覆盖'
    fi
}

add_key() {
    local old
    if old=$(read_key "$1") && [[ -n $old ]]; then
        KEYS+=("$1")
        VALUES[$1]=$2
    else
        warn "内核未提供 $1,跳过"
    fi
}

raise_key() {
    local old
    old=$(read_key "$1") || return 0
    [[ $old =~ ^[0-9]+$ ]] || return 0

    if ((old > $2)); then
        add_key "$1" "$old"
    else
        add_key "$1" "$2"
    fi
}

buffer_triplet() {
    local key=$1 cap=$2 low middle high
    read -r low middle high <<< "$(read_key "$key")"

    if [[ $low =~ ^[0-9]+$ &&
          $middle =~ ^[0-9]+$ &&
          $high =~ ^[0-9]+$ ]]; then
        ((cap >= middle)) || cap=$middle
        ((cap >= low)) || cap=$low
        add_key "$key" "$low $middle $cap"
    fi
}

build_plan() {
    local mib cap fast
    KEYS=()
    VALUES=()

    if ((RAM_MB <= 512)); then
        mib=4
    elif ((RAM_MB <= 1024)); then
        mib=8
    elif ((RAM_MB <= 4096)); then
        mib=16
    else
        mib=32
    fi

    if [[ $PROFILE == throughput ]]; then
        mib=$((mib*2))
    fi
    if ((BUFFER_MIB)); then
        mib=$BUFFER_MIB
    fi

    cap=$((mib*1024*1024))
    info "socket 上限:${mib} MiB;不是预分配内存"

    add_key net.core.rmem_max "$cap"
    add_key net.core.wmem_max "$cap"
    buffer_triplet net.ipv4.tcp_rmem "$cap"
    buffer_triplet net.ipv4.tcp_wmem "$cap"

    add_key net.ipv4.tcp_moderate_rcvbuf 1
    add_key net.ipv4.tcp_window_scaling 1
    add_key net.ipv4.tcp_sack 1

    raise_key net.core.somaxconn 4096
    raise_key net.ipv4.tcp_max_syn_backlog 4096

    case "$CC" in
        auto)
            if has_cc bbr; then
                add_key net.ipv4.tcp_congestion_control bbr
            else
                info 'BBR 未注册;apply 会尝试加载模块,不可用时保留原算法'
            fi
            ;;
        bbr|cubic)
            if has_cc "$CC"; then
                add_key net.ipv4.tcp_congestion_control "$CC"
            elif [[ $ACTION == plan ]]; then
                warn "$CC 当前未注册,apply 将探测模块"
            else
                die "内核未提供要求的 $CC"
            fi
            ;;
    esac

    [[ $QDISC != fq ]] || add_key net.core.default_qdisc fq

    if [[ $TFO != keep ]]; then
        fast=$(read_key net.ipv4.tcp_fastopen) || fast=
        if [[ $fast =~ ^[0-9]+$ ]]; then
            if [[ $TFO == on ]]; then
                fast=$((fast | 3))
            else
                fast=0
            fi
            add_key net.ipv4.tcp_fastopen "$fast"
        fi
    fi
}

show_plan() {
    local key unit

    printf '\n%-42s %-24s %s\n' 'sysctl' 'current' 'planned'
    for key in "${KEYS[@]}"; do
        printf '%-42s %-24s %s\n' \
            "$key" "$(read_key "$key")" "${VALUES[$key]}"
    done

    for unit in "${SERVICES[@]}"; do
        info "$unit: soft NOFILE 至少 $NOFILE,保留已有更高限制"
    done

    info '预览不验证写权限;apply 逐项写入并回读'
    info 'RPS/XPS、转发、MTU 等保持现状'
}

save_file() {
    local file=$1
    [[ ! -L $file ]] || die "拒绝覆盖符号链接:$file"

    if [[ -e $file ]]; then
        [[ -f $file ]] || die "不是常规文件:$file"
        mkdir -p "$TXN/files$(dirname "$file")"
        cp -a -- "$file" "$TXN/files$file"
        printf 'present\t%s\n' "$file" >> "$TXN/files.tsv"
    else
        printf 'absent\t%s\n' "$file" >> "$TXN/files.tsv"
    fi
}

atomic_file() {
    local source=$1 destination=$2 tmp
    mkdir -p "$(dirname "$destination")"
    tmp=$(mktemp "${destination}.tmp.XXXXXX")

    if ! install -m 0644 -- "$source" "$tmp" ||
        ! mv -f -- "$tmp" "$destination"; then
        rm -f -- "$tmp"
        return 1
    fi
}

restore_txn() {
    local dir=$1 kind file key value current failure=0

    while IFS=$'\t' read -r kind file; do
        [[ -n $file ]] || continue

        if [[ $kind == present ]]; then
            if ! cp -a --remove-destination -- \
                "$dir/files$file" "$file"; then
                failure=1
            fi
        elif [[ $kind == absent ]]; then
            if ! rm -f -- "$file"; then
                failure=1
            fi
        else
            warn "无效备份记录:$kind"
            failure=1
        fi
    done < "$dir/files.tsv"

    while IFS=$'\t' read -r key value; do
        [[ -n $key ]] || continue
        current=$(read_key "$key") || current=
        [[ $current != "$value" ]] || continue

        if ! sysctl -q -w "$key=$value"; then
            warn "无法恢复 $key"
            failure=1
            continue
        fi

        if [[ $(read_key "$key") != "$value" ]]; then
            warn "恢复后回读不一致:$key"
            failure=1
        fi
    done < "$dir/sysctl.tsv"

    if [[ -s $dir/services.txt ]] && ((SYSTEMD)); then
        if ! systemctl daemon-reload; then
            failure=1
        fi
    fi

    return "$failure"
}

on_exit() {
    local code=$? parent
    trap - EXIT INT TERM

    if ((ACTIVE_TXN)); then
        warn "应用未完成,回滚本次修改:$TXN"

        if restore_txn "$TXN"; then
            parent=$(cat "$TXN/parent")
            if [[ -n $parent ]]; then
                printf '%s\n' "$parent" > "$STATE/latest.tmp"
                mv -f "$STATE/latest.tmp" "$STATE/latest"
            else
                rm -f "$STATE/latest"
            fi
            rm -f "$STATE/pending"
        else
            warn '自动回滚未完全成功,请重新运行 restore'
        fi

        ((code != 0)) || code=1
    fi

    exit "$code"
}

lock_state() {
    mkdir -p "$STATE"
    [[ ! -L $STATE && $(stat -c %u "$STATE") == 0 ]] ||
        die '状态目录必须为 root 所有的非符号链接目录'

    chmod 0700 "$STATE"
    exec 9>"$STATE/lock"
    flock -n 9 || die '另一调优或恢复任务正在运行'
}

set_limits() {
    local unit file soft hard limit nr

    nr=$(read_key fs.nr_open) || die '无法读取 fs.nr_open'
    number_in_range "$nr" 1024 2147483647 ||
        die '无效 fs.nr_open'

    ((NOFILE <= nr)) ||
        die "--nofile 大于内核 fs.nr_open=$nr"

    for unit in "${SERVICES[@]}"; do
        soft=$(systemctl show "$unit" -p LimitNOFILESoft)
        soft=${soft#*=}
        hard=$(systemctl show "$unit" -p LimitNOFILE)
        hard=${hard#*=}

        [[ $soft != 18446744073709551615 ]] || soft=infinity
        [[ $hard != 18446744073709551615 ]] || hard=infinity

        [[ $soft =~ ^[0-9]+$ || $soft == infinity ]] ||
            die "$unit 无法读取 soft NOFILE"
        [[ $hard =~ ^[0-9]+$ || $hard == infinity ]] ||
            die "$unit 无法读取 hard NOFILE"

        if [[ $soft != infinity ]] && ((soft < NOFILE)); then
            soft=$NOFILE
        fi

        if [[ $hard != infinity ]]; then
            if [[ $soft == infinity ]]; then
                hard=infinity
            elif ((hard < soft)); then
                hard=$soft
            fi
        fi

        limit="$soft:$hard"
        file="$ETC/systemd/system/$unit.d/90-vps-proxy-tune.conf"

        save_file "$file"
        printf '%s\n' "$unit" >> "$TXN/services.txt"
        printf '[Service]\nLimitNOFILE=%s\n' "$limit" > "$TXN/dropin"
        atomic_file "$TXN/dropin" "$file"
    done

    if ((${#SERVICES[@]})); then
        systemctl daemon-reload

        for unit in "${SERVICES[@]}"; do
            soft=$(systemctl show "$unit" -p LimitNOFILESoft)
            soft=${soft#*=}
            [[ $soft != 18446744073709551615 ]] || soft=infinity

            if [[ $soft != infinity ]] &&
                { [[ ! $soft =~ ^[0-9]+$ ]] || ((soft < NOFILE)); }; then
                die "$unit 存在更高优先级覆盖,NOFILE 未达到目标"
            fi
        done
    fi
}

apply_plan() {
    local key old value now
    lock_state

    [[ ! -e $STATE/pending ]] ||
        die '存在中断任务,请先运行 vps-proxy-tune restore'

    TXN=$(mktemp -d "$STATE/txn-XXXXXXXX")
    : > "$TXN/files.tsv"
    : > "$TXN/sysctl.tsv"
    : > "$TXN/services.txt"

    if [[ -f $STATE/latest ]]; then
        cp "$STATE/latest" "$TXN/parent"
    else
        : > "$TXN/parent"
    fi

    printf '%s\n' "${TXN##*/}" > "$STATE/pending"
    ACTIVE_TXN=1
    trap on_exit EXIT
    trap 'exit 130' INT
    trap 'exit 143' TERM

    save_file "$ETC/sysctl.d/$CONF_NAME"

    if ((CONTAINER == 0)) &&
        command -v modprobe >/dev/null 2>&1; then
        case "$CC" in
            auto|bbr)
                has_cc bbr ||
                    modprobe tcp_bbr 2>>"$TXN/modules.log" || true
                ;;
            cubic)
                has_cc cubic ||
                    modprobe tcp_cubic 2>>"$TXN/modules.log" || true
                ;;
        esac
        [[ $QDISC != fq ]] ||
            modprobe sch_fq 2>>"$TXN/modules.log" || true
    fi

    build_plan
    printf '# Managed by vps-proxy-tune; verified keys only.\n' \
        > "$TXN/new.conf"

    for key in "${KEYS[@]}"; do
        old=$(read_key "$key") || {
            warn "$key 不可读,跳过"
            SKIPPED=$((SKIPPED+1))
            continue
        }

        value=${VALUES[$key]}
        printf '%s\t%s\n' "$key" "$old" >> "$TXN/sysctl.tsv"

        if [[ $old == "$value" ]] ||
            sysctl -q -w "$key=$value" 2>>"$TXN/sysctl-errors.log"; then
            now=$(read_key "$key") || now=

            if [[ $now == "$value" ]]; then
                printf '%s = %s\n' "$key" "$value" >> "$TXN/new.conf"
                info "$key = $value"
                continue
            fi
        fi

        warn "$key 写入失败或回读不一致,不持久化"
        now=$(read_key "$key") || now=

        if [[ $now != "$old" ]]; then
            sysctl -q -w "$key=$old" ||
                die "无法恢复失败项 $key"
            [[ $(read_key "$key") == "$old" ]] ||
                die "恢复失败项回读不一致:$key"
        fi

        if [[ $key == net.ipv4.tcp_congestion_control && $CC != auto ]]; then
            die '显式要求的拥塞控制无法生效'
        fi

        SKIPPED=$((SKIPPED+1))
    done

    atomic_file "$TXN/new.conf" "$ETC/sysctl.d/$CONF_NAME"

    if ((${#SERVICES[@]})); then
        set_limits
    fi

    printf '%s\n' "${TXN##*/}" > "$STATE/latest.tmp"
    mv -f "$STATE/latest.tmp" "$STATE/latest"
    rm -f "$STATE/pending"

    ACTIVE_TXN=0
    trap - EXIT INT TERM

    info "配置已保存,跳过 $SKIPPED 项"
    info "备份:$TXN"
    info '未重启代理服务;NOFILE 下次重启生效'
    info 'default_qdisc=fq 不等于当前网卡已经使用 fq'
    info '查看状态:vps-proxy-tune status'
    info '撤销本次:vps-proxy-tune restore'
}

restore_latest() {
    local name dir parent
    lock_state

    if [[ -f $STATE/pending ]]; then
        name=$(cat "$STATE/pending")
    elif [[ -f $STATE/latest ]]; then
        name=$(cat "$STATE/latest")
    else
        die '没有可恢复的本工具备份'
    fi

    [[ $name =~ ^txn-[a-zA-Z0-9]+$ ]] || die '无效备份编号'
    dir="$STATE/$name"

    [[ -f $dir/parent &&
       -f $dir/files.tsv &&
       -f $dir/sysctl.tsv ]] || die '备份不完整'

    if ! restore_txn "$dir"; then
        die "恢复未完全成功,保留备份以便重试:$dir"
    fi

    parent=$(cat "$dir/parent")
    if [[ -n $parent ]]; then
        printf '%s\n' "$parent" > "$STATE/latest.tmp"
        mv -f "$STATE/latest.tmp" "$STATE/latest"
    else
        rm -f "$STATE/latest"
    fi

    rm -f "$STATE/pending"
    info "已恢复本次应用前的文件及 sysctl:$name"
    info '如曾重启代理启用 NOFILE,需再次重启才能恢复进程限制'
}

status_report() {
    local key unit pid

    for key in \
        net.ipv4.tcp_available_congestion_control \
        net.ipv4.tcp_congestion_control \
        net.core.default_qdisc \
        net.core.rmem_max \
        net.core.wmem_max \
        net.ipv4.tcp_rmem \
        net.ipv4.tcp_wmem \
        net.ipv4.tcp_fastopen \
        net.ipv4.ip_forward \
        net.ipv6.conf.all.forwarding; do
        printf '%-45s %s\n' \
            "$key" "$(read_key "$key" || printf unavailable)"
    done

    printf '\n--- IPv4 / IPv6 默认路由 ---\n'
    ip -4 route show default || true
    ip -6 route show default || true

    printf '\n--- 网卡实际 qdisc ---\n'
    if command -v tc >/dev/null 2>&1; then
        tc -s qdisc show || true
    fi

    for unit in "${SERVICES[@]}"; do
        printf '\n--- %s ---\n' "$unit"
        systemctl show "$unit" \
            -p LimitNOFILE -p LimitNOFILESoft -p MainPID || true

        pid=$(systemctl show "$unit" -p MainPID)
        pid=${pid#*=}

        if [[ $pid =~ ^[1-9][0-9]*$ && -r $PROC/$pid/limits ]]; then
            awk '/^Max open files/ {print "运行中进程:", $0}' \
                "$PROC/$pid/limits"
        fi
    done
}

main() {
    set -Eeuo pipefail
    umask 077
    export LC_ALL=C
    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

    (( BASH_VERSINFO[0] > 4 ||
       (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4) )) ||
        die '需要 Bash 4.4+'

    parse_args "$@"

    local cmd
    for cmd in sysctl ip awk uname; do
        command -v "$cmd" >/dev/null ||
            die "缺少命令:$cmd"
    done

    if [[ $ACTION == apply || $ACTION == restore ]]; then
        ((EUID == 0)) || die 'apply / restore 需要 root'

        for cmd in flock mktemp install cp mv rm mkdir chmod stat; do
            command -v "$cmd" >/dev/null ||
                die "缺少命令:$cmd"
        done
    fi

    if [[ $ACTION == restore ]]; then
        if [[ -d $RUN/systemd/system ]] &&
            command -v systemctl >/dev/null; then
            SYSTEMD=1
        fi
        restore_latest
        return
    fi

    detect

    case "$ACTION" in
        plan) build_plan; show_plan ;;
        status) status_report ;;
        apply) apply_plan ;;
    esac
}

if [[ ${BASH_SOURCE[0]} == "$0" ]]; then
    main "$@"
fi
VPS_SCRIPT

bash -n "$VPS_SCRIPT_TMP"
chmod 0755 "$VPS_SCRIPT_TMP"
mv -f -- "$VPS_SCRIPT_TMP" /usr/local/sbin/vps-proxy-tune
bash /usr/local/sbin/vps-proxy-tune apply
VPS_INSTALL

Linux tuning