本文目录导读:

在脚本中调优 sysctl 内核参数,通常有以下几种常用方法,最佳实践取决于你的操作系统(Linux)和脚本语言(Shell、Python、Ansible 等)。
核心原则
- 临时生效:
sysctl -w <参数>=<值>(重启后失效) - 永久生效:修改
/etc/sysctl.conf或/etc/sysctl.d/下的 .conf 文件 - 立即加载:
sysctl -p(读取配置文件并应用) - 查看当前值:
sysctl <参数名>或cat /proc/sys/...
Shell 脚本(最常用)
适用于快速部署、自动化运维脚本(如 bash、sh)。
直接设置(临时 + 永久)
#!/bin/bash
# ----- 定义需要设置的参数(建议按功能分组) -----
# 网络优化
NET_CORE_PARAMS=(
"net.core.somaxconn=1024"
"net.core.rmem_max=134217728"
"net.core.wmem_max=134217728"
)
# 内存/虚拟内存
VM_PARAMS=(
"vm.swappiness=10"
"vm.dirty_ratio=30"
"vm.dirty_background_ratio=5"
)
# 安全/内核常规
KERNEL_PARAMS=(
"kernel.pid_max=65535"
"net.ipv4.tcp_tw_reuse=1"
"net.ipv4.ip_local_port_range=1024 65000"
)
# ----- 执行函数 -----
set_sysctl() {
local param=$1
local param_name="${param%%=*}" # 提取参数名(等号左边)
local param_value="${param#*=}" # 提取参数值(等号右边)
echo "设置: $param_name = $param_value"
# 1. 临时生效(立即生效)
sysctl -w "$param" 2>/dev/null || {
echo "警告: 临时设置 $param_name 失败"
return 1
}
# 2. 永久生效(写入 /etc/sysctl.d/ 下单独文件,避免冲突)
local config_file="/etc/sysctl.d/99-custom-params.conf"
# 如果不希望重复写入,可以先检查是否已经存在
if grep -q "^${param_name}\s*=" "$config_file" 2>/dev/null; then
# 替换已有行
sed -i "s|^${param_name}\s*=.*|$param|" "$config_file"
else
# 追加新行
echo "$param" >> "$config_file"
fi
}
# ----- 主流程 -----
echo "开始设置内核参数..."
# 合并所有参数并遍历设置
for param_group in "NET_CORE_PARAMS[@]" "VM_PARAMS[@]" "KERNEL_PARAMS[@]"; do
for param in "${!param_group}"; do
set_sysctl "$param"
done
done
echo "全部设置完成。"
# 可选:重新加载配置文件以确保所有文件都已应用
sysctl --system # systemd 系统推荐,会加载所有 /etc/sysctl.d/ 和 /etc/sysctl.conf
安全增强:备份 + 检查
# 备份当前 /etc/sysctl.conf
cp /etc/sysctl.conf /etc/sysctl.conf.backup.$(date +%Y%m%d)
# 写入前检查值是否合理(防止错误配置导致系统无法启动)
check_value() {
local param=$1
if [[ "$param" =~ ^net\.ipv4\.ip_local_port_range ]]; then
local min=$(echo "$param" | awk '{print $2}')
local max=$(echo "$param" | awk '{print $3}')
if [ "$min" -ge "$max" ]; then
echo "错误: ip_local_port_range 最小值($min)必须小于最大值($max)"
exit 1
fi
fi
}
Ansible 自动化(适用于大规模运维)
如果使用 Ansible,可以利用 sysctl 模块,这是最推荐的幂等方式(重复执行不会出错,只会确保参数正确)。
---
- name: 系统内核参数优化
hosts: all
become: yes
vars:
# 定义需要的参数
sysctl_network:
net.core.somaxconn: 1024
net.core.rmem_max: 134217728
net.core.wmem_max: 134217728
net.ipv4.tcp_tw_reuse: 1
net.ipv4.ip_local_port_range: "1024 65000"
sysctl_vm:
vm.swappiness: 10
vm.dirty_ratio: 30
sysctl_kernel:
kernel.pid_max: 65535
# 禁用 IPv6 重定向(安全)
net.ipv6.conf.all.accept_redirects: 0
tasks:
- name: 应用 sysctl 参数
ansible.posix.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present # 确保参数存在
reload: yes # 立即生效
sysctl_set: yes # 同时写入 sysctl.d 永久生效
sysctl_file: "/etc/sysctl.d/99-custom-params.conf" # 写入单独文件
loop: "{{ sysctl_network | dict2items + sysctl_vm | dict2items + sysctl_kernel | dict2items }}"
# 注意: 参数值类型:字符串用引号,数字不用(Ansible 会自动处理)
- name: 验证设置 (可选)
command: sysctl "{{ item.key }}"
loop: "{{ sysctl_network | dict2items + sysctl_vm | dict2items + sysctl_kernel | dict2items }}"
register: output
- debug:
msg: "{{ output.results | map(attribute='stdout_lines') | list }}"
Python 脚本
#!/usr/bin/env python3
import subprocess
import os
import sys
def set_sysctl(param_name, param_value, make_permanent=True):
"""
设置内核参数
:param param_name: 参数名称,如 'net.core.somaxconn'
:param param_value: 参数值,如 '1024'
:param make_permanent: 是否写入配置文件永久生效
"""
# 1. 临时生效
try:
subprocess.run(['sysctl', '-w', f'{param_name}={param_value}'], check=True,
capture_output=True, text=True)
print(f"临时生效: {param_name} = {param_value}")
except subprocess.CalledProcessError as e:
print(f"错误: 设置 {param_name} 失败 - {e.stderr.strip()}", file=sys.stderr)
return False
# 2. 永久生效(追加或替换)
if make_permanent:
config_dir = '/etc/sysctl.d'
config_file = os.path.join(config_dir, '99-custom-params.conf')
# 如果文件不存在则创建,存在则检查是否已有该参数
if not os.path.exists(config_file):
with open(config_file, 'w') as f:
f.write(f'{param_name} = {param_value}\n')
print(f"创建文件并写入: {config_file}")
else:
with open(config_file, 'r') as f:
lines = f.readlines()
param_exists = False
for i, line in enumerate(lines):
if line.strip().startswith(param_name):
lines[i] = f'{param_name} = {param_value}\n'
param_exists = True
break
with open(config_file, 'w') as f:
f.writelines(lines)
if param_exists:
print(f"替换已有参数: {param_name} = {param_value}")
else:
# 追加到文件末尾
with open(config_file, 'a') as f:
f.write(f'{param_name} = {param_value}\n')
print(f"追加参数: {param_name} = {param_value}")
# 重新加载配置文件(确保永久设置也立即生效)
subprocess.run(['sysctl', '--system'], check=True)
print("重新加载所有 sysctl 配置文件")
return True
# 使用示例
if __name__ == '__main__':
params = {
'net.ipv4.tcp_tw_reuse': '1',
'vm.swappiness': '10',
'kernel.pid_max': '65535',
}
for name, value in params.items():
set_sysctl(name, value, make_permanent=True)
常见内核参数调优建议(脚本中常用)
| 参数 | 建议值 | 说明 |
|---|---|---|
| 网络 | ||
net.core.somaxconn |
1024 ~ 65535 | 高并发连接队列长度 |
net.ipv4.tcp_tw_reuse |
1 | 复用 TIME_WAIT 状态连接(高并发场景) |
net.ipv4.ip_local_port_range |
"1024 65000" | 本地端口范围,扩大后支持更多连接 |
net.core.rmem_max / wmem_max |
134217728(128MB) | 增加网络缓冲区(大流量场景) |
| 内存 | ||
vm.swappiness |
10 | 降低使用交换分区的倾向(服务器建议 10~30) |
vm.dirty_ratio |
30% | 写缓存占内存上限 |
vm.dirty_background_ratio |
5% | 后台异步写回阈值 |
| 文件系统 | ||
fs.file-max |
65535~1000000 | 系统最大文件句柄数 |
fs.nr_open |
1048576 | 进程单进程最大文件句柄(= file-max*2) |
| 安全 | ||
net.ipv4.conf.all.rp_filter |
1 | 开启反向路径过滤(防 IP 欺骗) |
kernel.randomize_va_space |
2 | ASLR 保护(安全建议) |
注意事项
- 测试环境先试:
sysctl -a | grep <参数>先查看当前值。 - 一致性检查:如果使用
sysctl.d/下的多个文件,注意优先级(按字母顺序加载,后加载的会覆盖先加载的)。 - 重启验证:永久配置写入后,最好
sysctl --system立即生效,然后重启服务器验证配置是否持久。 - 不要使用
sysctl -w写入/proc/sys而不写文件:这样重启会丢失。 - 避免写错:
vm.swappiness写成vm.swapiness,不会报错但不会生效。
根据你的使用场景,选择 Shell 脚本(灵活、部署快)、Ansible(大规模、幂等)或 Python(程序化控制)。