改了 swappiness 却不生效:sysctl 配置的加载顺序
起因
一台 2 核、不到 2 GB 内存的云服务器,上面要跑好几个容器,内存很紧。先加了 2 GB 的交换文件(内存不够时,把暂时不用的数据挪到磁盘上的一块空间):
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab # 开机自动挂上
接着想把 vm.swappiness 设成 10。这个值在 0 到 100
之间,越小越不愿意用交换空间,设成 10 的意思是内存快用完了才用。于是新建了
/etc/sysctl.d/99-zz-swap.conf,写上 vm.swappiness = 10,再执行
sysctl --system。
结果一查,还是 0:
$ cat /proc/sys/vm/swappiness
0
原因
sysctl --system 会把输出里每个读到的文件都打印出来,看一眼就明白了:它先读
/etc/sysctl.d/ 等几个目录里的文件,最后再读一遍 /etc/sysctl.conf。同一个参数写了好几次,以最后读到的为准。
这台机器的系统镜像在 /etc/sysctl.conf 第一行就写了
vm.swappiness = 0,所以我在 sysctl.d 里写的 10 刚生效就被盖回去了。
开机时的情况又不一样:开机由 systemd-sysctl 处理,它只按文件名排序读
/etc/sysctl.d/,而 Ubuntu 在那里放了一个
99-sysctl.conf,它其实是指向
/etc/sysctl.conf 的链接。也就是说,开机和手动执行
sysctl --system 两种情况,读文件的顺序不同。文件名起成 99-zz
能保证开机时排在后面,手动执行时照样被盖掉。
解决
- 先备份:
cp /etc/sysctl.conf /etc/sysctl.conf.bak-日期。 -
直接把
/etc/sysctl.conf里那一行改成vm.swappiness = 10,上面加一行注释写明为什么改。 - 删掉 sysctl.d 里自己加的那个文件,免得以后两处的值对不上。
-
执行
sysctl --system,再看/proc/sys/vm/swappiness,变成 10 了。
记住
-
改内核参数之前,先搜一遍有没有别处已经写了:
grep -rn swappiness /etc/sysctl.conf /etc/sysctl.d/。 - 改完一定要读一下实际生效的值,别只看配置文件。
- 云厂商的系统镜像经常自带一些调优参数,在它们的基础上改,比另起一个文件可靠。