在CentOS系统中使用firewall-cmd配置防火墙规则时,"永久生效"和"立即生效"的核心区别就一句话:不加--permanent参数的命令会同时写入运行时规则和永久配置文件,但如果你只加了--permanent而没有加--reload或--runtime-to-permanent,那条规则只存在于配置文件里,当前防火墙根本不认它。换句话说,立即生效是让规则马上起作用,永久生效是让规则在重启后依然存在,而最稳妥的做法是两步都做,或者一条命令同时搞定。
很多运维人员在实际操作中容易混淆这两个概念,导致配置完规则后发现端口没开、服务不通,排查半天发现是规则根本没加载到运行时。今天这篇文章就把这个问题彻底讲透,从原理到实操,从常见错误到最佳实践,全部覆盖。
一、firewall-cmd的工作机制到底是什么CentOS 7及以上版本默认使用firewalld作为防火墙管理工具,firewall-cmd是它的命令行客户端。firewalld采用了"运行时(runtime)"和"永久(permanent)"两套配置体系。运行时配置存放在内存中,系统重启或firewalld服务重启后会丢失;永久配置存放在/etc/firewalld/目录下的XML文件中,重启后依然有效。
当你执行一条不带任何参数的firewall-cmd命令时,它默认操作的是运行时配置。比如:
firewall-cmd --add-port=8080/tcp
这条命令会立即把8080端口加入当前运行中的防火墙规则,但如果你重启firewalld服务,这个端口就会被关闭,因为它没有被写入永久配置文件。
而当你加上--permanent参数时:
firewall-cmd --permanent --add-port=8080/tcp
这条命令只会把规则写入/etc/firewalld/zones/目录下对应zone的XML文件中,当前运行时的防火墙并不会马上加载这条规则。你必须额外执行reload或runtime-to-permanent操作才能让它生效。
二、立即生效的具体操作和适用场景立即生效的操作非常简单,就是不加--permanent参数直接执行规则添加。例如开放80端口:
firewall-cmd --add-port=80/tcp
执行后可以用以下命令验证:
firewall-cmd --list-ports
如果看到80/tcp出现在列表中,说明规则已经立即生效。这种方式适合临时测试、紧急开放端口、调试阶段使用。但要注意,一旦执行了firewall-cmd --reload或者重启了firewalld服务,这些没有写入永久配置的规则就会全部消失。
立即生效还有一个变体操作,就是在加了--permanent之后再执行--reload:
firewall-cmd --permanent --add-port=443/tcp firewall-cmd --reload
这种方式的效果是:规则先被写入永久配置文件,然后通过reload让运行时重新加载所有永久配置,从而实现立即生效加永久保存的双重效果。这是生产环境中最推荐的标准操作方式。
三、永久生效的具体操作和常见误区永久生效的核心就是--permanent参数,但很多人犯的错误是:只执行了带--permanent的命令就以为规则已经生效了,结果去测试发现端口根本不通。
典型的错误操作流程:
firewall-cmd --permanent --add-service=http # 以为完成了,实际上当前防火墙并没有加载这条规则
正确的完整流程应该是:
firewall-cmd --permanent --add-service=http firewall-cmd --reload
或者你也可以分两步理解:先写永久配置,再让运行时同步。还有一种方式是使用--runtime-to-permanent,它的作用是把当前运行时的所有规则覆盖写入永久配置文件:
firewall-cmd --runtime-to-permanent
这个命令适合你已经在运行时配置好了一堆规则,想一次性全部保存为永久规则的场景。但要注意,它是覆盖式写入,之前永久配置中有但运行时没有的规则会被清除。
四、两种方式的本质区别对比为了让大家更直观地理解,我把核心区别整理成对比:
不加--permanent:规则只存在于运行时内存中,立即生效,重启后丢失。适合临时操作、快速测试。
加--permanent不reload:规则只存在于XML配置文件中,当前不生效,重启后保留。适合预先配置、批量写入。
加--permanent再reload:规则同时存在于运行时和配置文件中,立即生效且重启后保留。这是生产环境的标准做法。
从文件层面来看,永久配置存储在以下路径:
/etc/firewalld/zones/public.xml /etc/firewalld/zones/drop.xml /etc/firewalld/zones/work.xml
你可以直接用文本编辑器打开这些XML文件查看已写入的规则,这是验证永久配置是否成功的最直接方法。
五、实际生产环境中的最佳实践在真实的服务器运维中,我建议大家养成一个习惯:所有防火墙规则的变更都按照"先永久写入,再reload生效"的流程来操作。具体步骤如下:
第一步,确认当前zone:
firewall-cmd --get-active-zones
第二步,添加永久规则:
firewall-cmd --permanent --add-port=3306/tcp --zone=public
第三步,重新加载使其立即生效:
firewall-cmd --reload
第四步,验证规则是否正确加载:
firewall-cmd --list-all
这四步走完,规则就既立即生效又永久保存了。如果你在做批量配置,比如一次性开放多个端口,可以把多条--permanent命令写在一个脚本里,最后统一reload一次,效率更高。
还有一个容易被忽略的点:如果你修改了zone的配置文件后不想reload整个防火墙,可以只针对某个zone进行reload:
firewall-cmd --reload --zone=public
这样可以减少对其他zone规则的影响,在多zone环境下更精细可控。
六、删除规则时永久与立即的区别同样重要添加规则时要注意永久和立即的区别,删除规则时同样如此。如果你只执行了:
firewall-cmd --remove-port=8080/tcp
这只是从运行时删除了规则,永久配置文件里还留着。下次reload或者重启后,这个端口又会被打开。正确的删除方式应该是:
firewall-cmd --permanent --remove-port=8080/tcp firewall-cmd --reload
或者如果你想同时清理运行时和永久配置:
firewall-cmd --remove-port=8080/tcp firewall-cmd --permanent --remove-port=8080/tcp
这种双删操作在安全审计、合规检查时非常重要,确保规则被彻底清除,不留隐患。
七、查看当前规则到底属于哪一层有时候你需要确认某条规则到底是在运行时还是在永久配置中,可以用以下方法区分:
查看运行时规则:
firewall-cmd --list-all
查看永久配置规则:
firewall-cmd --permanent --list-all
对比两个输出结果,差异部分就是只存在于某一层的规则。这个对比在排查问题时非常实用,比如你发现某个端口在list-all里有但在permanent --list-all里没有,说明这是一条临时规则,重启后会消失,需要及时补写永久配置。
八、总结与核心要点回到最初的问题,firewall-cmd中永久生效和立即生效的区别本质上就是"写不写配置文件"和"当不当前加载"的组合关系。不加--permanent就是只改运行时,加了--permanent就是只改配置文件,两者都不完整。只有--permanent配合--reload,或者不加--permanent直接操作(临时场景),才是完整的操作逻辑。
作为运维人员,记住一个原则:生产环境永远用--permanent + --reload的组合,临时测试可以只用立即生效。养成操作后验证的习惯,用--list-all确认规则状态,用查看XML文件确认写入结果,这样才能避免配置遗漏和安全隐患。
CentOS的firewalld虽然比早期的iptables命令更易用,但这套双配置体系如果理解不透彻,很容易在实际工作中踩坑。希望这篇文章能帮你把这个知识点彻底吃透,在日常运维中做到配置精准、安全可靠。
