为什么更新正在运行的 Linux 系统没有问题?

为什么更新正在运行的 Linux 系统没有问题?

多年来我每天都使用 Linux 系统,并且在系统运行时更新系统从未遇到过重大问题,但我仍然想知道为什么会出现这种情况。

让我举个例子。

假设某个包中的程序“A”正在系统上运行。该程序在某个时刻需要打开同一包中的另一个文件(“B”)。之后,程序“A”关闭“B”,因为它不再需要它。假设现在我更新了“A”和“B”所属的包。 “A”不会直接受到此操作的影响,至少目前是这样,因为它在 RAM 中运行,并且更新只是替换了硬盘上的“A”。假设文件系统上的“B”也已被替换。现在由于某种原因“A”需要再次读取“B”。问题是:“A”是否有可能找到“B”的不兼容版本并以其他方式崩溃或故障?

为什么没有人通过使用 Live CD 或类似程序重新启动来更新系统?

答案1

更新用户空间很少是一个问题

您经常可以在实时系统上更新软件包,因为:

  1. 共享库存储在内存中,而不是每次调用时从磁盘读取,因此旧版本将继续使用,直到应用程序重新启动。
  2. 打开的文件实际上是从文件描述符,而不是文件名,因此即使移动/重命名/删除,文件内容仍然可供正在运行的应用程序使用,直到扇区被覆盖或文件描述符关闭。
  3. 如果包设计良好,则需要重新加载或重新启动的包通常可以由包管理器正确处理。例如,每当 libc6 升级时,Debian 都会重新启动某些服务。

通常,除非您正在更新内核并且不使用 ksplice,否则可能需要重新启动程序或服务才能利用更新。然而,很少需要重新启动系统来更新用户空间中的任何内容,尽管在桌面上它有时比重新启动单个服务更容易。

也可以看看

http://en.wikipedia.org/wiki/Ring_%28computer_security%29#Supervisor_mode

答案2

是的,您所描述的是可能的,但大多数情况下,如果文件包含在包中,它将是一个库或其他文件,被读取一次且仅一次(因为它不会改变,所以没有理由多读几遍)。此外,如果长期需要该文件,应用程序可能会使文件句柄保持打开状态,其中即使它在实际文件系统上被替换,打开的文件句柄也会使旧版本保持打开状态。

在大多数情况下,在进程生命周期中多次读取的任何数据都是用户/变量数据,并且在包升级期间不会改变。另外,由于数据是可变的,任何头脑正常的程序员都会确保程序可以处理从一次读取到下一次读取的变化。

答案3

假设文件系统上的“B”也已被替换。现在由于某种原因“A”需要再次读取“B”。问题是:“A”是否有可能找到“B”的不兼容版本并以其他方式崩溃或故障?

这是可能的,但在大多数情况下不太可能。如果“B”是代码库,那么原始版本通常不会被关闭。 “A”将继续使用“B”的原始版本。如果您在更新后运行“A”,则将使用新版本的“B”。更新期间,存在加载不兼容版本的风险。然而,由于代码库的加载方式,只有当“A”需要它加载的“B”版本中不存在的功能时,这才应该成为问题。

良好的编码实践可以保持功能接口相同。因此,加载哪个版本并不重要,除非新版本中修复了错误。

配置文件的情况略有不同,但通常在启动期间读取。在这种情况下,“A”不会读取“B”,除非重新加载配置发生更改。同样,更改配置文件的格式或含义将是不好的编码习惯。不兼容版本的配置文件应该有不同的名称,这样就不会导致问题。

为什么没有人通过使用 Live CD 或类似程序重新启动来更新系统?

关闭并从不同版本重新启动将导致服务中断。对于服务器来说,这通常是不希望的。无论如何,正在运行的系统上的包管理器都知道它已安装的软件和版本。 Live CD 有自己的已安装软件列表,可能有不同的版本。这使得从 Live CD 可靠地升级正在运行的系统变得困难。

安装新版本的操作系统时有时会使用 Live CD。在这种情况下,通常会完成操作系统的全新安装。这可以限制保留的先前版本中未使用的文件数量。这可能比升级实时系统更费力。但是,如果使用不同的根分区,则可以限制陷入无法启动的部分更新系统的风险。

答案4

在某些情况下这是一个问题:

  • java-VM 运行时的 JDK 升级:我问了自己同样的问题 - 我有一个正在运行的使用 java 的 tomcat。现在,在对 JDK 进行补丁更新后,它仍然可以正常运行 - 看起来是这样。

现在的解释是高速缓存。好的 - 我启动了一个内存占用程序来耗尽所有可用的 RAM - 然后 tomcat 崩溃了(在我访问在那里运行的应用程序之后)。

  • SuSE 系统上的内核升级:在 SuSE 上,旧内核及其模块在内核补丁升级后立即被删除。如果您想使用新的东西,需要一个内核模块,直到现在才加载,服务将会失败。

相关内容