如何以事务方式复制文件?

Eva*_*enn 10 linux bash cp

我想将一个文件从 A 复制到 B,它可能位于不同的文件系统上。

还有一些额外的要求:

  1. 副本是全有或全无,崩溃时没有部分或损坏的文件 B 留在原地;
  2. 不要覆盖现有的文件 B;
  3. 不要与同一命令的并发执行竞争,最多一个可以成功。

我认为这很接近:

cp A B.part && \
ln B B.part && \
rm B.part
Run Code Online (Sandbox Code Playgroud)

但是 3. 如果 B.part 存在(即使使用 -n 标志),则 cp 不会失败。随后 1. 如果另一个进程“赢得”cp 并且链接到位的文件不完整,则可能会失败。B.part 也可能是一个不相关的文件,但我很高兴在这种情况下没有尝试其他隐藏名称而失败。

我认为 bash noclobber 有帮助,这是否完全有效?有没有办法在没有 bash 版本要求的情况下获得?

#!/usr/bin/env bash
set -o noclobber
cat A > B.part && \
ln B.part B && \
rm B.part
Run Code Online (Sandbox Code Playgroud)

后续,我知道一些文件系统无论如何都会失败(NFS)。有没有办法检测这样的文件系统?

其他一些相关但不完全相同的问题:

跨文件系统的近似原子移动?

我的 fs 上的 mv 是原子的吗?

有没有办法在 eMMC 上以原子方式将文件和目录从 tempfs 移动到 ext4 分区

https://rcrowley.org/2010/01/06/things-unix-can-do-atomically.html

Her*_*ann 12

rsync做这个工作。O_EXCL默认情况下会创建一个临时文件(仅在您使用时禁用--inplace),然后renamed覆盖目标文件。使用--ignore-existing如果存在不覆盖B中。

在实践中,我从未在 ext4、zfs 甚至 NFS 挂载上遇到任何问题。

  • 这是最好的答案。Rsync 是原子文件传输的行业标准首选,并且在各种配置中可以满足您的所有要求。 (2认同)