使用 rsync 覆盖正在使用的 .so 文件或可执行文件是否安全?
Is it safe to overwrite a .so file or an executable in use using rsync?
这不是真正的编程问题。我们有一个用 c++ 编写的大型系统,并在 Redhat Enterprise Linux 上使用许多共享对象 (.so) 和本机可执行文件。系统在多个主机上运行,我们使用 rsync 来保存部署的二进制文件(共享对象和可执行文件)
如果我们必须修复 .so(或可执行文件)中的错误,我们会将其部署到一个位置,然后在所有其他主机上进行 rsync
覆盖正在使用的 .so(或可执行文件)是否安全(或 运行)?我读到 rm
& cp
是安全的,因为 *nix 如何处理 inode
(某种引用计数)。但是当涉及到 rsync
时,我找不到满意的答案
简答
如果您不使用 --in-place
.
,它在单个文件中是绝对安全的
对于多个相互依赖的文件来说,它基本上是安全的,但是有一些风险,使用 --delay-updates
可以将风险降到最低。
长答案
默认(即不使用--in-place
时),rsync
实际上会在新文件中创建内容,以临时名称命名(类似于 .__your_file
),然后在完成后将其重命名为原始文件。
这个重命名是一个完全原子的操作:任何试图打开文件的人都会得到原始文件或替换文件(在替换完全完成之后)。
此外,如果原始文件正在使用中,那么即使在指向它的目录条目被指向不同 inode 的新条目覆盖之后,它的引用计数也将不为零,因此内容将保留在磁盘上(未删除)直到原始文件不再打开。
但是,对于多个文件, 您 运行 有这样的风险,即只有其中一些文件会被自动替换。如果您同时复制新的 foo
和 libfoo.so
,那么旧的 foo
将无法与新的 libfoo.so
和新的 foo
一起使用将无法与旧 libfoo.so
一起使用,如果您在新 libfoo.so
已 rename()
就位后尝试启动可执行文件,则情况很糟糕,但是 foo
还没有。
rsync 可用的最接近此问题的修复方法是 --delay-updates
选项,它将等到它具有 .__foo
和 .__libfoo.so
完成,然后将它们并排重命名。仍然没有操作系统级别的保证,您看不到一个文件的更新版本而不是另一个文件,但是发生这种情况的时间 window 大大缩短了。
如果使用 --in-place
,则操作系统将由于文件正在使用而拒绝写入权限(并非对 UNIX 上的所有访问都强制执行,但特别使用 mmap(MAP_PRIVATE)
强制执行,用于可执行文件和共享库);这将是一个 "Text file busy" 错误。如果您的操作系统 没有 强制执行此操作,任何 mmap()
用于提供反映文件内容的内存区域(这通常是加载共享库的方式)的任何场景都会导致 Bad Things在就地覆盖的情况下发生。
这不是真正的编程问题。我们有一个用 c++ 编写的大型系统,并在 Redhat Enterprise Linux 上使用许多共享对象 (.so) 和本机可执行文件。系统在多个主机上运行,我们使用 rsync 来保存部署的二进制文件(共享对象和可执行文件)
如果我们必须修复 .so(或可执行文件)中的错误,我们会将其部署到一个位置,然后在所有其他主机上进行 rsync
覆盖正在使用的 .so(或可执行文件)是否安全(或 运行)?我读到 rm
& cp
是安全的,因为 *nix 如何处理 inode
(某种引用计数)。但是当涉及到 rsync
简答
如果您不使用 --in-place
.
对于多个相互依赖的文件来说,它基本上是安全的,但是有一些风险,使用 --delay-updates
可以将风险降到最低。
长答案
默认(即不使用--in-place
时),rsync
实际上会在新文件中创建内容,以临时名称命名(类似于 .__your_file
),然后在完成后将其重命名为原始文件。
这个重命名是一个完全原子的操作:任何试图打开文件的人都会得到原始文件或替换文件(在替换完全完成之后)。
此外,如果原始文件正在使用中,那么即使在指向它的目录条目被指向不同 inode 的新条目覆盖之后,它的引用计数也将不为零,因此内容将保留在磁盘上(未删除)直到原始文件不再打开。
但是,对于多个文件, 您 运行 有这样的风险,即只有其中一些文件会被自动替换。如果您同时复制新的 foo
和 libfoo.so
,那么旧的 foo
将无法与新的 libfoo.so
和新的 foo
一起使用将无法与旧 libfoo.so
一起使用,如果您在新 libfoo.so
已 rename()
就位后尝试启动可执行文件,则情况很糟糕,但是 foo
还没有。
rsync 可用的最接近此问题的修复方法是 --delay-updates
选项,它将等到它具有 .__foo
和 .__libfoo.so
完成,然后将它们并排重命名。仍然没有操作系统级别的保证,您看不到一个文件的更新版本而不是另一个文件,但是发生这种情况的时间 window 大大缩短了。
如果使用 --in-place
,则操作系统将由于文件正在使用而拒绝写入权限(并非对 UNIX 上的所有访问都强制执行,但特别使用 mmap(MAP_PRIVATE)
强制执行,用于可执行文件和共享库);这将是一个 "Text file busy" 错误。如果您的操作系统 没有 强制执行此操作,任何 mmap()
用于提供反映文件内容的内存区域(这通常是加载共享库的方式)的任何场景都会导致 Bad Things在就地覆盖的情况下发生。