[转载]sysctl加载配置顺序问题

1 minute read

背景

原文

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作为最后导入覆盖的配置文件了.

如果这么做, 那么这么文件就最好全部注释掉. 感觉这块挺坑的.

Flag Counter

digoal’s 大量PostgreSQL文章入口