【问题标题】:Is it safe to overwrite a .so file or an executable in use using rsync?使用 rsync 覆盖 .so 文件或正在使用的可执行文件是否安全?
【发布时间】:2016-12-20 11:38:22
【问题描述】:

这不是一个真正的编程问题。我们有一个用 C++ 编写的大型系统,并在 Redhat Enterprise Linux 上使用许多共享对象 (.so) 和本机可执行文件。系统在多台主机上运行,​​我们使用 rsync 来保存部署的二进制文件(共享对象和可执行文件)

如果我们必须修复 .so(或可执行文件)中的错误,我们会将其部署到单个位置,然后跨所有其他主机进行 rsync

在使用(或运行)时覆盖 .so(或可执行文件)是否安全?我读到rmcp 是安全的,因为*nix 处理inode(某种引用计数)。但是说到rsync,却找不到满意的答案

【问题讨论】:

  • 如果进程已经将.so 加载到内存中,这是非常安全的。
  • @OregonTrail,不管它是否已经加载——即使它只是打开但还没有读取,你仍然可以保持你的句柄在原始 inode 上,防止其释放。
  • 顺便说一句,对于未来的非真正编程问题,请考虑unix.stackexchange.com(与操作系统相关时)或superuser.com
  • ...了解什么是inode 实际上是 并没有什么坏处——基本上,它是文件系统中实际存储文件内容的部分。要理解的重要一点是,inode 和目录条目是两个不同的东西——你可以让一个 inode 有多个目录条目(硬链接),或者根本没有目录条目。在最后一种情况下,将在没有人打开该文件后将其删除,但由于该规定(在实际删除之前等待所有预先存在的句柄关闭),可以在使用时安全地删除或替换文件。
  • ...现在,更大的问题是,虽然 rsync 可以安全且原子地替换 just one 可执行文件,但它不能替换 multiple 可执行文件作为原子操作,因此您可以拥有一个只完成部分更新的地方,并且任何重新启动服务的尝试都会失败。

标签: linux rsync inode


【解决方案1】:

简答

如果你不使用--in-place,在单个文件中是完全安全的。

对于多个相互依赖的文件来说,这基本上是安全的,但使用--delay-updates 可以将一些风险降到最低。


长答案

默认情况下(即不使用--in-place时),rsync 实际上会在一个以临时名称命名的新文件中创建内容(类似于.__your_file),并且然后在完成后将其重命名为原始文件。

这个重命名是一个完全原子操作:任何试图打开文件的东西要么得到原始文件,要么得到替换文件(在替换完全完成之后)。

此外,如果原始文件正在使用,那么即使指向它的目录条目被指向不同 inode 的新条目覆盖,它的引用计数也将非零,因此内容将保留在磁盘上(未删除)直到原始文件不再打开。

但是,如果有多个文件,您将面临只有其中一些文件会被原子替换的风险。如果您同时复制新的foolibfoo.so,这样旧的foo 将无法与新的libfoo.so 一起使用,而新的foo 将无法与旧的libfoo.so 一起使用,如果您在新的libfoo.so 已经到位但foo 还没有到位之后尝试启动可执行文件,那么您的处境很糟糕。

rsync 最接近解决此问题的方法是 --delay-updates 选项,该选项将等到 两个 .__foo.__libfoo.so 都完成,然后接下来将它们重命名对彼此。仍然没有操作系统级别的保证,您不能看到一个文件的更新版本,而不是另一个,但是发生这种情况的时间窗口大大缩短了。


如果使用--in-place,则操作系统将拒绝写入权限,因为该文件正在使用中(并非对 UNIX 上的所有访问强制执行,而是通过 mmap(MAP_PRIVATE) 专门强制执行,如用于可执行文件和共享库);这将是“文本文件繁忙”错误。如果您的操作系统没有强制执行此操作,则任何使用mmap() 提供反映文件内容的内存区域(通常是共享库的加载方式)的情况都会导致事件发生就地覆盖。

【讨论】:

  • 多个文件本身不是问题。可执行文件主要作为守护进程运行,我们通常不会在一周内覆盖多个文件。感谢您指出多个文件的事情。如果导出的现有函数的签名发生更改,我从没想过它会首先工作
猜你喜欢
  • 2010-10-17
  • 2019-09-18
  • 2019-09-14
  • 2018-11-05
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多