[转载]sysctl加载配置顺序问题
背景
原文
https://blog.tankywoo.com/2015/01/29/sysctl-load-order.html
正文
系统Gentoo, 最近遇到一个比较离奇的问题.
网关机器的sysctl运行时配置中,net.ipv4.ip_forward被改为0, 原来是1; net.ipv4.conf.default.rp_filter 和 net.ipv4.conf.all.rp_filter也都被设置为1了.
因为最近系统出现过几次异常, 所有服务不可用, 怀疑是某个服务造成, 不排除影响到这块, 虽然感觉不太可能.
昨天恰好又出现了, 于是今天准备写一个监控net.ipv4.ip_forward值的脚本, 才写到一半, 跳闸了, 网关机器启动后, 发现无法转发, nat表都是正常的, 继而发现ip_forward也被改为0了.
改回来后, 过了一会, 又跳闸, 启动后确认, 基本确定了是重启会造成这个问题. 因为之前网关机器的服务异常时, 同事都是重启了机器.
继续排查, Gentoo的默认/etc/sysctl.conf配置(主要部分):
# Disables packet forwarding
net.ipv4.ip_forward = 0
# Disables IP dynaddr
#net.ipv4.ip_dynaddr = 0
# Disable ECN
#net.ipv4.tcp_ecn = 0
# Enables source route verification
net.ipv4.conf.default.rp_filter = 1
# Enable reverse path
net.ipv4.conf.all.rp_filter = 1
可以看到, 这里恰好都是被修改的配置.
继续看/etc/sysctl.d/default.conf配置, 里面有对这几个项的修改. 不过检查发现其它项的值都是和配置的一样, 唯独这几个被修改为和/etc/sysctl.conf中一样了.
按理来说, 应该是先加载/etc/sysctl.conf, 然后加载/etc/sysctl.d/*.conf中以ascii首字母排序的配置, 后者会覆盖前者的配置.
本地直接测试:
sysctl --system
这个会加载所有的sysctl配置(sysctl -p默认无参数只加载/etc/sysctl.conf)
发现它的顺序是先加载/etc/sysctl.d/*.conf, 最后加载/etc/sysctl.conf.
man sysctl:
--system
Load settings from all system configuration files.
/run/sysctl.d/*.conf
/etc/sysctl.d/*.conf
/usr/local/lib/sysctl.d/*.conf
/usr/lib/sysctl.d/*.conf
/lib/sysctl.d/*.conf
/etc/sysctl.conf
但是以前重启都是没问题的.
继续看/etc/init.d/sysctl:
# … 省略其它代码
start()
{
ebegin "Configuring kernel parameters"
sysctl --system
eend $? "Unable to configure some kernel parameters"
}
启动这块是调用的这个sysctl –system命令.
那为何之前没问题?
后来同事发现近期这个脚本更新过, 于是我看了下我本地Gentoo系统上的这个启动脚本(主要代码):
# … 省略其它代码
start()
{
local conf= retval=0 err errs
ebegin "Configuring kernel parameters"
eindent
for conf in /etc/sysctl.conf /etc/sysctl.d/*.conf; do
if [ -r "$conf" ]; then
vebegin "applying $conf"
if ! err=$(sysctl -p "$conf" 2>&1 >/dev/null) ; then
errs="${errs} ${err}"
sysctl -e -p "${conf}" >/dev/null
fi
veend $? || retval=1
fi
done
eoutdent
if [ ${retval} -eq 0 ] && [ -n "${errs}" ] ; then
ewarn "Unknown keys:${errs}"
fi
eend $retval "Some errors were encountered: ${errs}"
}
这个是老的sysctl启动脚本, 里面就设置了导入配置的顺序, 先导入/etc/sysctl.conf, 然后用/etc/sysctl.d/*.conf中的配置覆盖.
感觉后者是合理的顺序, 不明白为何更新后, 将/etc/sysctl.conf作为最后导入覆盖的配置文件了.
如果这么做, 那么这么文件就最好全部注释掉. 感觉这块挺坑的.