这不是一个真正的编程问题。我们有一个用c++编写的大型系统,在Redhat Enterprise Linux上使用了许多共享对象(.so)和本地可执行文件。系统运行在多个主机上,我们使用rsync来保存已部署的二进制文件(共享对象&;可执行文件)
如果我们必须修复。so(或可执行文件)中的错误,我们将其部署到一个位置,然后在所有其他主机上rsync
覆盖一个。so(或可执行文件)是安全的,而它是在使用(或运行)?我读过rm
&cp
是安全的,因为*nix如何处理inode
(某种引用计数)。但是当谈到rsync
简短回答
如果不使用--in-place
,在单个文件中是完全安全的。
对于多个相互依赖的文件来说,这是最安全的,但是使用--delay-updates
会最小化一些风险。
长回答
默认(即,当不使用--in-place
时),rsync
实际上将在新文件中创建内容,并使用临时名称(如.__your_file
)命名,然后在完成后将其重命名为原始文件。
这个重命名是一个完全的原子操作:任何试图打开文件的操作要么得到原始文件,要么得到替换文件(在替换完全完成之后)。
此外,如果原始文件正在使用中,那么即使指向它的目录条目被指向不同索引节点的新条目覆盖,它的引用计数也将是非零的,因此该内容将保留在磁盘上(未删除),直到原始文件不再打开。
然而,对于多个文件,您冒着只有其中一些文件将被自动替换的风险。如果你复制了一个新的foo
和libfoo.so
,使得旧的foo
不能与新的libfoo.so
一起工作,新的foo
不能与旧的libfoo.so
一起工作,如果你试图在新的libfoo.so
已经rename()
'd到位而foo
还没有到位之后启动一个可执行文件,你就处于一个糟糕的情况。
--delay-updates
选项,它将等待 .__foo
和.__libfoo.so
都完成,然后将它们重新命名为彼此相邻。操作系统级仍然不能保证您不能看到一个文件的更新版本而看不到另一个文件的更新版本,但是发生这种情况的时间窗口大大缩短了。
如果使用--in-place
,则操作系统将由于文件正在使用而拒绝写权限(在UNIX上不是对所有访问都强制,但mmap(MAP_PRIVATE)
特别强制,用于可执行文件和共享库);这将是一个"文本文件繁忙"错误。如果您的操作系统没有强制执行此操作,那么任何使用mmap()
来提供反映文件内容的内存区域(这通常是加载共享库的方式)的场景都会导致在本地覆盖事件中发生不良事件。