#!/bin/bash # game-optimize.sh — оптимизация Debian 12 под игровые серверы / игровой ПК # Минимальный пинг, низкий bufferbloat, быстрые прерывания # Запуск: curl -fsSL https://gitea.creative-tg1.ru/CREATIVE_tg1/for-servers/raw/branch/main/server/game-optimize.sh | sudo bash set -e LIMIT_NOFILE=65535 echo "============================================" echo " Game Server Optimization — Debian 12" echo "============================================" echo "" # ── 1. Сеть (sysctl) ───────────────────────────────────── echo "[1/5] Сетевые оптимизации (sysctl)..." cat >/etc/sysctl.d/99-game-network.conf </dev/null 2>&1 echo " OK" # ── 2. NIC — txqueuelen + coalescing ───────────────────── echo "[2/5] Сетевые интерфейсы (NIC)..." for iface in $(ls /sys/class/net/ | grep -v lo); do # Короткая очередь на интерфейсе ip link set dev "$iface" txqueuelen 1000 2>/dev/null || true # Выключаем coalescing прерываний (rx-usecs=0) — главный буст для пинга ethtool -C "$iface" rx-usecs 0 2>/dev/null || true ethtool -C "$iface" tx-usecs 0 2>/dev/null || true # Увеличиваем кольцевой буфер NIC (если поддерживается) ethtool -G "$iface" rx 4096 2>/dev/null || true ethtool -G "$iface" tx 4096 2>/dev/null || true echo " $iface OK" done # ── 3. ulimit ──────────────────────────────────────────── echo "[3/5] Лимиты файловых дескрипторов (limits.d)..." cat >/etc/security/limits.d/90-nofile.conf </dev/null; then sed -i "s/^#DefaultLimitNOFILE=.*/DefaultLimitNOFILE=${LIMIT_NOFILE}/" "$conf" elif ! grep -q "^DefaultLimitNOFILE=" "$conf" 2>/dev/null; then echo "DefaultLimitNOFILE=${LIMIT_NOFILE}" >> "$conf" else sed -i "s/^DefaultLimitNOFILE=.*/DefaultLimitNOFILE=${LIMIT_NOFILE}/" "$conf" fi done systemctl daemon-reload echo " OK" # ── 5. IRQ affinity (если CPU > 1 ядро) ───────────────── echo "[5/5] IRQ affinity..." CPU_COUNT=$(nproc) if [ "$CPU_COUNT" -gt 1 ]; then # Распределяем сетевые прерывания по ядрам for iface in $(ls /sys/class/net/ | grep -v lo); do irqs=$(grep "$iface" /proc/interrupts 2>/dev/null | awk -F: '{print $1}' || true) core=0 for irq in $irqs; do irq_num="${irq//[^0-9]/}" [ -z "$irq_num" ] && continue if [ -f "/proc/irq/$irq_num/smp_affinity_list" ]; then echo "$core" > "/proc/irq/$irq_num/smp_affinity_list" 2>/dev/null || true core=$(( (core + 1) % CPU_COUNT )) fi done done echo " Распределено по $CPU_COUNT ядрам" else echo " 1 ядро — пропущено" fi # ── Итоги ───────────────────────────────────────────────── echo "" echo "============================================" echo " Итог" echo "============================================" echo "" echo "Очередь:" sysctl net.core.default_qdisc echo "Контроль перегрузки:" sysctl net.ipv4.tcp_congestion_control echo "busy_poll:" sysctl net.core.busy_poll echo "Soft ulimit: $(ulimit -Sn)" echo "Hard ulimit: $(ulimit -Hn)" echo "" echo "NIC:" for iface in $(ls /sys/class/net/ | grep -v lo); do echo " $iface: txqueuelen=$(cat /sys/class/net/$iface/tx_queue_len 2>/dev/null || echo '?')" done echo "" echo "Готово." echo "После перезагрузки сессии / машины — ulimit -n покажет ${LIMIT_NOFILE}"