#!/usr/bin/env bash
set -euo pipefail

# ===============================
# 基础信息
# ===============================
arch=$(getconf LONG_BIT)
memory_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
memory_mb=$((memory_kb / 1024))
memory_gb=$((memory_mb / 1024))
a=$((arch / 32))

# ===============================
# 工具函数
# ===============================
max() {
    if [ "$1" -gt "$2" ]; then
        echo "$1"
    else
        echo "$2"
    fi
}

sysctl_get() {
    sysctl -n "$1" 2>/dev/null || echo 0
}

# ===============================
# 读取系统默认值
# ===============================
DEF_fs_file_max=$(sysctl_get fs.file-max)
DEF_conntrack_max=$(sysctl_get net.netfilter.nf_conntrack_max)
DEF_rmem_max=$(sysctl_get net.core.rmem_max)
DEF_wmem_max=$(sysctl_get net.core.wmem_max)
DEF_netdev_max_backlog=$(sysctl_get net.core.netdev_max_backlog)
DEF_somaxconn=$(sysctl_get net.core.somaxconn)
DEF_tcp_max_tw_buckets=$(sysctl_get net.ipv4.tcp_max_tw_buckets)

# ===============================
# 动态计算值
# ===============================
CALC_fs_file_max=$((memory_mb * 256))
CALC_conntrack_max=$((memory_mb / 16 / a))
CALC_rmem_max=$((memory_mb * 1024 * 4))
CALC_wmem_max=$((memory_mb * 1024 * 4))
CALC_netdev_max_backlog=$((memory_mb * 128))
CALC_somaxconn=$((memory_mb * 16))
CALC_tcp_max_tw_buckets=$((memory_mb * 4))

# ===============================
# 与默认值取最大
# ===============================
fs_file_max=$(max "$CALC_fs_file_max" "$DEF_fs_file_max")
conntrack_max=$(max "$CALC_conntrack_max" "$DEF_conntrack_max")
rmem_max=$(max "$CALC_rmem_max" "$DEF_rmem_max")
wmem_max=$(max "$CALC_wmem_max" "$DEF_wmem_max")
netdev_max_backlog=$(max "$CALC_netdev_max_backlog" "$DEF_netdev_max_backlog")
somaxconn=$(max "$CALC_somaxconn" "$DEF_somaxconn")
tcp_max_tw_buckets=$(max "$CALC_tcp_max_tw_buckets" "$DEF_tcp_max_tw_buckets")

# ===============================
# 安全上限（防止极端值）
# ===============================
[ "$fs_file_max" -gt 20000000 ] && fs_file_max=20000000
[ "$conntrack_max" -gt 8388608 ] && conntrack_max=8388608
[ "$tcp_max_tw_buckets" -gt 2000000 ] && tcp_max_tw_buckets=2000000

buckets=$((conntrack_max / 4))

# ===============================
# 颜色输出
# ===============================
CSI=$'\033['
CEND="${CSI}0m"
CYELLOW="${CSI}1;33m"
CCYAN="${CSI}1;36m"
CRED="${CSI}1;31m"

info() { echo -e "${CCYAN}[INFO] $*${CEND}"; }
warn() { echo -e "${CYELLOW}[WARN] $*${CEND}"; }
error() { echo -e "${CRED}[ERROR] $*${CEND}"; }

# ===============================
# 系统识别
# ===============================
if [[ -f /etc/redhat-release ]]; then
    release="centos"
elif grep -qiE "debian|ubuntu" /etc/os-release; then
    release="debian"
else
    error "不支持的系统"
    exit 1
fi

# ===============================
# 更新系统
# ===============================
info "更新系统中..."
if [[ $release == "centos" ]]; then
    yum makecache -y
    yum install -y epel-release
    yum update -y
else
    apt update -y
    apt autoremove -y
fi

# ===============================
# 内核参数写入
# ===============================
info "写入 sysctl 参数..."
modprobe nf_conntrack || true

cat > /etc/sysctl.conf <<EOF
vm.swappiness = 0

fs.file-max = $fs_file_max

net.core.rmem_max = $rmem_max
net.core.wmem_max = $wmem_max
net.core.netdev_max_backlog = $netdev_max_backlog
net.core.somaxconn = $somaxconn
net.core.default_qdisc = fq_pie

net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 10
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_abort_on_overflow = 1
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_max_tw_buckets = $tcp_max_tw_buckets
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_rmem = 4096 87380 $rmem_max
net.ipv4.tcp_wmem = 4096 65536 $wmem_max

net.netfilter.nf_conntrack_max = $conntrack_max
net.netfilter.nf_conntrack_buckets = $buckets
net.netfilter.nf_conntrack_tcp_timeout_established = 300
net.netfilter.nf_conntrack_udp_timeout = 2
net.netfilter.nf_conntrack_udp_timeout_stream = 30

net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
EOF

# ===============================
# limits.conf
# ===============================
cat > /etc/security/limits.conf <<EOF
* soft nofile 512000
* hard nofile 512000
* soft nproc 512000
* hard nproc 512000
root soft nofile 512000
root hard nofile 512000
root soft nproc 512000
root hard nproc 512000
EOF

# ===============================
# journald
# ===============================
cat > /etc/systemd/journald.conf <<EOF
[Journal]
SystemMaxUse=384M
SystemMaxFileSize=128M
ForwardToSyslog=no
EOF

# ===============================
# 应用
# ===============================
sysctl -p
systemctl restart systemd-journald || true

info "优化完成 ✔"
info "内存: ${memory_gb}G | conntrack: $conntrack_max | buckets: $buckets"
