我不知道如何apt 升级确实升级正在运行的程序。
它是否等到程序终止?
它只是在程序运行时覆盖文件吗?这不会干扰正在运行的程序吗?
那么共享库又如何呢?
答案1
在 POSIX 中(Linux 是一个 POSIX 系统),至少在使用 POSIX 文件系统时,文件在被删除后(即在被未链接,通过删除从特定文件名到底层 inode 对象的链接,该对象实际上将特定字节串标识为文件的内容)。处于此状态的文件仍可供具有打开句柄的代码访问(用户空间中的文件描述符,内核空间中的其他结构),尽管它们不再具有名称1,并且任何尝试打开旧名称的东西都将无法再获取它们。这意味着如果您执行以下操作:
$ cat /tmp/foo.txt # step 1
foo
$ rm /tmp/foo.txt # step 2
$ echo "bar" > /tmp/foo.txt # step 3
你实际上并没有改变 的内容/tmp/foo.txt
,而是在创建一个新的,不相关且独立可以使用相同名称访问的文件,但旧文件不再可用。
此外,POSIX 还规定原子重命名,其中文件立即重命名为现有名称,并替换原始文件,中间没有中间状态。本质上,它是一种机制,可确保在上述步骤 2 和步骤 3 之间不会发生任何事情,导致旧文件被删除但新文件尚未到位。
当apt
升级正在运行的二进制文件时,它实际上不会更改文件的内容;相反,它使用原子重命名立即将新文件(如上所述,完全独立)从临时名称移到旧文件的位置。任何打开旧文件(这包括将其作为可执行文件运行的进程)将继续查看和使用旧内容,就像什么都没发生过一样。但是当进程终止并重新启动时,将按名称查找其代码,因此将使用新内容。这也意味着有可能让进程执行同名的二进制文件,但运行不同的代码。
但请注意,上述内容仅适用于单个文件。如果应用程序的资源分散在多个文件中,则无法对其进行原子替换,因此,例如,如果二进制文件动态加载共享库,或者在启动后按名称打开某些数据,则它很可能会看到一些意想不到的东西,从而出现故障和/或崩溃。这就是为什么在升级 Firefox 后会弹出一个提示框,提示您重新启动 Firefox,“否则您将遇到问题”。
1更确切地说,他们不再拥有那个特定的名字因为文件(即 inode)允许以多个名称访问。然而,绝大多数文件只有一个名称,当它们不再与该名称关联时,只要没有其他东西可以打开它们,它们就会被删除2 。
2这种延迟删除也是为什么在某些情况下,您可能会删除文件以回收磁盘空间,结果却发现没有释放任何空间。这是因为某些东西打开了这些文件,并让它们处于僵尸状态,无名但活着。
答案2
apt upgrade
覆盖文件。它不会影响正在运行的程序,因为它们已加载到 RAM。如果您重新启动程序,则会启动新版本。
当升级某些包时,如果需要,可能会运行一些触发器或脚本来重新启动某些服务。
答案3
它是否等到程序终止?
也许,取决于包裹。
它只是在程序运行时覆盖文件吗?这不会干扰正在运行的程序吗?
可以,这取决于程序和文件。
那么共享库又如何呢?
这取决于它是否已被加载到内存中。https://stackoverflow.com/a/7767402/1212596
完整答案
Apt(其实是底层的 dpkg)在卸载和安装软件包时会运行脚本。如果软件包中包含一个长时间运行的程序(守护进程),它通常会在删除旧版本的软件包时停止,并在安装新版本的软件包时启动。
预安装 此脚本在所属软件包从其 Debian 档案 (.deb) 文件中解压之前执行。许多“preinst”脚本会停止正在升级的软件包的服务,直到其安装或升级完成(在成功执行“postinst”脚本之后)。
后安装 一旦将 foo 从 Debian 存档 (.deb) 文件中解压出来,此脚本通常会完成对 foo 软件包的任何必需配置。通常,“postinst”脚本会要求用户输入,并/或警告他们,如果他们接受默认值,则应记住根据需要返回并重新配置该软件包。然后,许多“postinst”脚本执行启动或重新启动服务所需的任何命令一旦安装或升级了新的包。
普雷姆 此脚本通常会停止所有守护进程与软件包关联的文件。它在删除与软件包关联的文件之前执行。
后 此脚本通常修改与 foo 关联的链接或其他文件,和/或删除包创建的文件。(另请参阅什么是虚拟包?,第 7.8 节。)
https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html
当然,启动和停止 postinst 和 prerm 中的服务由软件包维护者决定。