pacman/Pacnew 和 Pacsave

来自 ArchWiki

pacman 移除一个包含配置文件的软件包时,通常会创建该配置文件的备份副本,并在文件名后附加 .pacsave。同样,当 pacman 升级一个软件包,并且该软件包包含一个由维护者创建的、与当前已安装文件不同的新配置文件时,它会保存一个 .pacnew 文件,其中包含新的配置。当这些文件被写入时,pacman 会发出通知。

为何创建这些文件

.pacnew 文件可能在软件包升级期间(pacman -Syu, pacman -Supacman -U)创建,以避免覆盖已存在且先前被用户修改的文件。当这种情况发生时,类似以下的消息将出现在 pacman 的输出中

warning: /etc/pam.d/usermod installed as /etc/pam.d/usermod.pacnew

.pacsave 文件可能在软件包移除期间(pacman -R)或软件包升级期间(软件包必须先被移除)创建。当 pacman 数据库记录了软件包拥有的某个文件应该被备份时,它将创建一个 .pacsave 文件。当这种情况发生时,pacman 会输出类似以下的消息

warning: /etc/pam.d/usermod saved as /etc/pam.d/usermod.pacsave

这些文件需要用户手动干预,并且最好在每次软件包升级或移除后立即处理它们。如果未处理,不正确的配置可能导致软件功能异常或软件完全无法运行。

软件包备份文件

软件包的 PKGBUILD 文件指定了在软件包升级或移除时应保留或备份的文件。例如,pulseaudio 的 PKGBUILD 包含以下行

backup=(etc/pulse/{daemon.conf,default.pa,system.pa})

安装后,可以使用 pacman -Qii package_name 从 pacman 数据库中查询此列表。

要防止任何软件包覆盖特定文件,请参阅 Pacman#跳过文件升级

类型解释

.pacnew

对于每个正在升级的 #软件包备份文件,pacman 交叉比较从文件内容生成的三个 md5sum:一个用于软件包最初安装的版本,一个用于文件系统中当前的版本,另一个用于新软件包中的版本。如果文件系统中当前文件的版本已从软件包最初安装的版本修改过,pacman 无法知道如何将这些更改与新版本的文件合并。因此,pacman 不会覆盖修改后的文件,而是在升级时将新版本保存为 .pacnew 扩展名,并保持修改后的版本不变。

注意: 软件包的安装可能会导致其他软件包拥有的文件发生更改。例如,请参阅 FS#77404。因此,即使对于您未手动更改的文件,也可能创建 .pacnew 文件。

更详细地说,3 路 MD5 校验和比较会导致以下结果之一

原始 = X,当前 = X,新的 = X
文件的所有三个版本都具有相同的内容,因此覆盖不是问题。将当前版本覆盖为新版本,并且不通知用户(尽管文件内容相同,但此覆盖将更新文件系统有关文件的安装、修改和访问时间的信息,并确保应用任何文件权限更改)。
原始 = X,当前 = X,新的 = Y
当前版本的内容与原始版本相同,但新版本不同。由于用户未修改当前版本,并且新版本可能包含改进或错误修复,因此将当前版本覆盖为新版本,并且不通知用户。这是 pacman 能够执行的唯一自动合并新更改的操作。
原始 = X,当前 = Y,新的 = X
原始软件包和新软件包都包含完全相同的文件版本,但是文件系统中当前的版本已被修改。保留当前版本,并丢弃新版本,而不通知用户。
原始 = X,当前 = Y,新的 = Y
新版本与当前版本相同。将当前版本覆盖为新版本,并且不通知用户(尽管文件内容相同,但此覆盖将更新文件系统有关文件的安装、修改和访问时间的信息,并确保应用任何文件权限更改)。
原始 = X,当前 = Y,新的 = Z
所有三个版本都不同,因此保留当前版本,将新版本安装为 .pacnew 扩展名,并警告用户有关新版本的信息。预计用户将手动将新版本中的任何必要更改合并到当前版本中。

极少数情况下,当升级后的软件包包含先前版本中没有的备份文件时,情况会被正确处理为 X/Y/Y 或 X/Y/Z,其中 X 是一个不存在的值。

.pacsave

如果用户修改了 backup 中指定的文件之一,则该文件将被重命名为 .pacsave 扩展名,并在软件包的其余部分被移除后保留在文件系统中。

注意:-n 选项与 pacman -R 一起使用将导致完全移除指定软件包中的所有文件,因此不会创建 .pacsave 文件。

定位 .pac* 文件

Pacman 不会自动处理 .pacnew 文件:您必须自行维护这些文件。下一节将介绍一些工具。要手动执行此操作,您首先需要定位它们。当升级或移除大量软件包时,可能会遗漏更新的 .pac* 文件。要发现是否已安装任何 .pac* 文件,请使用以下方法之一

  • /etc 中搜索,其中存储了大多数全局配置
    # find /etc -name '*.pacnew' -o -name '*.pacsave'
    或者在整个磁盘中搜索,将上述命令中的 /etc 替换为 /(在这种情况下,您可能需要选择性地跳过某些目录以加快搜索速度)。
  • 如果已安装,也可以使用 locate。首先重新索引数据库
    # updatedb
    然后运行
    $ locate --existing '*.pacnew' '*.pacsave'
  • 使用 pacman 的日志查找它们
    $ grep '\.pacnew\|\.pacsave' /var/log/pacman.log
    请注意,日志不会跟踪文件系统中当前的文件,也不会跟踪已移除的文件;以上命令将列出系统上曾经存在的所有 .pac* 文件。为了仅获取最近 10 个 .pac* 文件,请将结果通过管道传递给 tail

管理 .pac* 文件

注意: 即使您没有手动编辑文件,也不要盲目地使用其 .pacnew 版本覆盖活动文件。始终手动比较和合并更改。

pacdiff

pacman-contrib 提供了简单的 pacdiff(8) 工具,用于管理 .pac* 文件。

它将搜索 .pacnew.pacsave.pacorig 文件,然后提示您对它们采取操作。

默认情况下,它使用 --pacmandb,以使用当前已安装软件包中的 backup 数组信息进行搜索。如果这不足以满足您的用例,您可以指定 --find--locate 来进行更彻底的搜索。

默认情况下,它使用 vimdiff,但您可以使用 DIFFPROG=your_editor pacdiff 指定其他工具。有关其他常用比较工具,请参阅 应用程序列表/实用程序#比较、差异、合并

第三方实用程序

一些第三方实用程序为这些任务提供了不同程度的自动化

  • dotpac — 带有基于 ncurses 的文本界面的基本交互式脚本和有用的演练。没有合并或自动合并功能。
https://github.com/AladW/dotpac || dotpacAUR
  • etc-updateGentoo 的实用程序,与其他发行版(包括 Arch)兼容。它提供了一个简单的 CLI 来查看、合并和交互式编辑更改。琐碎的更改(例如注释)可以自动合并。
Gentoo:Handbook:Parts/Portage/Tools#etc-update || etc-update
  • p3wm — 三路合并 .pacnew 文件。它可以自动合并琐碎的更改。如果发生冲突,它将启动 vimdiff、meld 或 kdiff3 来解决它们。
https://github.com/5long/p3wm || p3wmAUR
  • pacnews-git — 一个简单的脚本,旨在查找所有 .pacnew 文件,然后使用 vimdiff 编辑它们。
https://github.com/pbrisbin/scripts/blob/master/pacnews || pacnews-gitAUR
  • pacfiles-mode — 用于 Emacs 的软件包,用于管理和合并 .pacnew 文件。
https://github.com/UndeadKernel/pacfiles-mode || 在 melpa 中可用
  • pacdiff-pacman-hook-git — Pacman 钩子,用于自动运行 pacdiff。
https://github.com/desbma/pacman-hooks || pacdiff-pacman-hook-gitAUR

参见