通过在不同的主机上更新 debian 操作系统 ( apt-get dist-upgrade
),我看到同一屏幕上有许多通常很小的变化;当配置文件被修改时,它会告诉您有新版本可用,并要求您解决问题:您已经修改了文件,并且 apt/dpkg 无法可靠地将您的更改与新版本集成。
现在这个选项菜单在不同的文件之间是不同的。有时甚至在同一个包内。
某些文件将具有“包配置”控制台 UI,其他文件将使用纯控制台输出。包配置 UI 中可用的选项并不总是相同。
修改/新版本文件的名称并不总是相同。新文件的存储位置并不总是它应该在的位置(有时它在“tmp”中)。新文件的命名方案也不一致(有些包使用随机名称,有些使用 -new,其他包使用 -dpkg-new,等等。)
有些软件包拒绝告诉您 dpkg 默认值在哪里。有些软件包不为您提供带有扩展名 dpkg-old 或 -old 或 -dist 或 -dpkg-dist 或 -old-nameofpackage 的先前版本,但其他软件包则提供。 (所以在某些情况下您可以手动进行三向合并,在其他情况下则不能)。有些软件包添加了一个方便的“在版本之间进行 3 路合并”(这始终是我尝试的第一件事,因为它通常可以自动解决问题:配置文件中的大多数更改通常只是注释中的拼写错误修复。
程序或并排差异显示的方式也可能因包/文件而异。
所以我想整个目的包管理系统的核心是创建一种一致的安装和卸载程序的方式。用户易于管理。
这里出了什么问题;为什么会这样可怕在它的用户界面/用户体验中?用户可以做些什么来更改/修改 apt 吗?
- “进行三向合并”可用
- 新文件总是以一致的方式重命名/放置?
由于当归结为相同的死记硬背的过程时,做同样的事情有 1,000 个微小的变化,因此必须手动重新阅读并弄清楚如何准确地处理每个配置文件是很痛苦的。
为了说明我的意思,这里有两个升级版;
Configuration file '/etc/ssh/ssh_config'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer's version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.
A new version (/tmp/tmp.3RoEfdEm3M) of configuration file /etc/ssh/sshd_config is available, but the version installed currently has been locally modified.
What do you want to do about modified configuration file sshd_config?
install the package maintainer's version
keep the local version currently installed
show the differences between the versions
show a side-by-side difference between the versions
show a 3-way difference between available versions
do a 3-way merge between available versions
start a new shell to examine the situation
第二个变体中的那些选项?它们并不总是按这个顺序出现。
感觉这几乎就是为了绊倒你而设计的。
答案1
我将首先解决您问题中“面向用户”的问题:
“进行三向合并”可用
这无法由用户控制,这取决于包如何管理其配置文件(见下文)。
新文件总是以一致的方式重命名/放置?
不,但在实践中这应该不重要。特别是,第二个示例(第一个示例sshd_config
)中显示的临时文件确实是临时文件:它们是可用的配置文件的变体,以便比较工具等可以找到它们需要比较的数据。 (这里可以通过以下方式改善用户体验不是默认情况下显示临时文件名,并且仅在用户启动 shell“检查情况”时才显示。)
至于为什么会出现这种情况,特别是在 Debian 中,是因为配置文件可以通过多种方式处理。
正如您所期望的,包管理器dpkg
提供了自己的配置文件管理。这就是您的示例中产生第一个变体(ssh_config
升级)的原因。它只有两条信息可供使用:磁盘上当前存在的配置文件,以及它尝试安装的包中附带的新配置文件。因此,它无法提供三向合并。对于包维护者来说,它的使用非常简单(事实上,在大多数情况下,它根本不需要任何工作)。dpkg
的配置文件处理会在事后产生一致的文件名:以.dpkg-dist
和结尾的文件.dpkg-old
取决于用户是否保留现有文件(在这种情况下,保留新文件以供以后参考,带有扩展名.dpkg-dist
)或安装新文件(在这种情况下,旧文件将保留.dpkg-old
扩展名)。
为了改善这种状况,工具ucf
发展了。它存储配置文件的原始版本,这就是为什么它可以提供三向比较和合并。然而,它需要包维护者做一些工作,这就是许多包不使用它的原因。此外,对三向合并的支持是可选的。你可以看到openssh-server
ucf
在这里集成。
最重要的是,还有debconf
,Debian配置管理系统。这是安装过程中需要交互的软件包是应该使用,但同样,这需要软件包维护者的工作,因此虽然现在很常见,但仍然存在一些例外(包括尚未更新以使用的非常旧的软件包debconf
)。
当然,一些维护者不喜欢上述任何内容,或者在上述某些内容可用之前开发了自己的解决方案,因此一些软件包做了自己的事情。
Joey Hess 写了一篇关于他从 1999 年开始参与 Debian VA Linux 套装的文章,它提供了有关包配置的创建debconf
和修改的一些背景信息。
答案2
在进行任何更新之前,请先安装distro-info
,否则如果无法访问 Web 浏览器,则从 CLI 查找以前的版本名称会很棘手。
命令:
diff3 -m config.file config.file.dpkg-old config.file.dpkg-new > config.file.merged
diff config.file config.file.merged
然后编辑,或者,如果合并有效:
mv config.file.merged config.file
是手动执行 debconf/ucf 相同操作的一种方法。
这只会留下不通知用户他们将旧/新配置文件留在何处的软件包。要从旧版本的软件包中下载丢失的配置文件,在升级过程进行到一半时,您可以安装整个单独的系统并在其中安装软件包。或者,您可以通过浏览器手动下载它,然后将其 ftp 到 Linux 计算机。但是,如果必须在升级机器的命令行上完成,事情就会变得有点复杂。
这就是我到目前为止所得到的。还有一件事未实现:
GETPACKAGERELEASEVER
--> 哪个版本的软件包是“buster”的一部分?我该如何打印这个?另外,如何确定它是“main”还是“contrib”?
(这部分的相关问题;如何从 cli 检查给定发行版本的软件包版本?)
# Todo: Look this up in some way using apt. (main, non-free, or contrib).
pkgType=main
previousReleaseName = $(distro-info -o)
# If not possible to use distro-info:
# This is rather hacky, and will fail when debian updates this webpage.
# release=$(cat /etc/issue | sed -E 's/[^0-9]*([0-9]+).*/\1/')
# previousRelease=$(($release-1))
# wget -O- https://www.debian.org/releases/ > releases.html
# previousReleaseName = $(cat releases.html | grep "Debian $previousRelease" | sed -E 's/.*Debian [0-9]+ \(<q>([a-z]+).*/\1/'))
firstLetter="$(echo $packagename | head -c 1)"
packageVersion=GETPACKAGERELEASEVER($packagename,$previousReleaseName)
mkdir /tmp/$packagename/
cd /tmp/$packagename
rm -r /tmp/$packagename/*
wget -O package.deb "https://deb.debian.org/pool/$pkgType/${firstLetter}/${packageName}/${packagename}_${packageVersion}_amd64.deb"
ar x package.deb
tar -xvf data.tar.xz
diff3 -m /etc/$packagename/$configfile /tmp/$packagename/etc/$configfile /etc/$packagename/$newconfigfile > /etc/$packagename/$configfile.merged`