打开一个 rpm spec 文件,在 %files 段有一个指令很常见:%config(noreplace),这个指定到底是干什么用的呢?

答案是,该指令决定如果一个文件被管理员修改过后,下次更新该文件所在的rpm包时,该文件的存在状态。例如,一般升级软件时,配置文件是不会变化的,而主程序则一般需要被升级(替换)。

对于 spec 文件中在 %files 段的某一个文件,我们要讨论三种情况:

  1. 没有带 %config 指令。例如:%{_sbindir}/redis-server
  2. 带了 %congfig 指令。例如:%config %{_sysconfdir}/redis/redis.conf
  3. 带了 %config(noreplace) 指令。例如:%config(noreplace) %{_sysconfdir}/redis/redis.conf

具体一点,包含如下场景:

1. 一个文件没有被 %config%config(noreplace) 指令配置

此时,不管该文件在安装完成后,有没有在本地被修改过,当升级该 rpm 包时,该文件会被这个新的 rpm 包的里的同名文件替换,(旧文件被删除)。

2. 一个文件被 %config 指令配置

此时包含如下情况:

  • 该文件在新的 rpm 包里相对之前的 rpm 有变化,且在本地没有被修改过。

此时执行rpm -Uvh xxxx时,新rpm包里的该文件会替换旧的文件。(旧文件被删除)

  • 该文件在新的 rpm 包里相对之前的 rpm 有变化,且在本地被修改过。

此时执行 rpm -Uvh xxxx 时,新 rpm 包里的该文件会替换掉掉旧的文件,旧的文件会被保存为 xx.rpmsave,如 /etc/redis/redis.conf.rpmsave。

  • 该文件在新的 rpm 包里相对之前的 rpm 没有变化,且在本地没有被修改过。

此时执行r pm -Uvh xxxx 时,新 rpm 包里的该文件会替换掉旧的文件。(旧文件被删除)

  • 该文件在新的 rpm 包里相对之前的 rpm 没有变化,且在本地被修改过。

此时执行 rpm -Uvh xxxx 时,新 rpm 包里的该文件不会覆盖旧的文件,旧文件保持不变。

3. 一个文件被 %config(noreplace) 指令配置

此时包含如下情况:

  • 该文件在新的 rpm 包里相对之前的 rpm 有变化,且在本地没有被修改过。

此时执行 rpm -Uvh xxxx 时,新 rpm 包里的该文件会替换旧的文件。(旧文件被删除)

  • 该文件在新的 rpm 包里相对之前的 rpm 有变化,且在本地被修改过。

此时执行 rpm -Uvh xxxx 时,旧文件保持不变,新 rpm 包里的该文件并重命名为 xx.rpmnew,例如/etc/redis/redis.conf.rpmnew。

  • 该文件在新的 rpm 包里相对之前的 rpm 没有变化,且在本地没有被修改过。

此时执行 rpm -Uvh xxxx 时,新 rpm 包里的该文件会替换旧的文件。(旧文件被删除)

  • 该文件在新的 rpm 包里相对之前的 rpm 没有变化,且在本地被修改过。

此时执行 rpm -Uvh xxxx 时,新rpm包里的该文件不会覆盖旧的文件,旧文件保持不变。

4.总结

  1. 如果一个文件在 %files 段没有被 %config%config(noreplace) 指令配置,则执行 rpm -Uvh 时,该文件会无条件被新文件替换。
  2. 无论一个文件有没有被 %config%config(noreplace) 指令配置,只要改文件在本地没有被编辑过,则执行 rpm -Uvh 时,该文件会被新文件替换。
  3. 一个被 %config%config(noreplace) 指令配置的文件,如果被编辑过,那么在 rpm 更新时,如果新的 rpm 包中该文件没有修改,则该文件不会被新 rpm 包中的文件替换,之前做的编辑依然有效。
  4. 一个被 %config 指令配置的文件,如果被编辑过,且新的 rpm 包中该文件有修改,则该文件会被重命名为 xx.rpmsave,新文件会替代原文件。
  5. 一个被 %config(noreplace) 指令配置的文件,如果被编辑过,且新的 rpm 包中该文件有修改,则该文件不会被新的 rpm 包中的文件替换,之前做的编辑依然有效;但新 rpm 包中的同名文件会被重命名为 xx.rpmnew。

参考: