怎么能删除一个文件而“cp”却无法写入它呢?

怎么能删除一个文件而“cp”却无法写入它呢?

我有一个 bash 脚本的一部分,我正在以 root 身份执行它:

rm -f ../../include/profile.h; \
cp profile.h ../../include/profile.h

该文件../../include/profile.h具有权限:

-rw-r--r-- 1 root root 12178 Nov  5 02:00 ../../include/profile.h

大多数情况下,该代码片段执行良好,但极少数情况下无法重现,并且会失败:

cp: cannot create regular file `../../include/profile.h': File exists

我检查了一下,程序中没有其他可以并行执行的部分,可以在两个语句之间写入文件,从而产生竞争条件,这可以解释这种行为。除了上面的只执行一次的地方之外,没有其他地方可以写入此文件。

该系统

核心:

Linux dev64 2.6.32.63+drm33.26-64.128-a10 #6 SMP Fri Jul 25 15:21:56 PDT 2014 x86_64 x86_64 x86_64 GNU/Linux

发行版:

CentOS release 6.3 (Final)

什么可能导致出现此故障?

答案1

使用

strace cp profile.h ../../include/profile.h 2>logfile

并寻找:

stat("../../include/profile.h", 0x7ffdca347950) = -1 ENOENT (No such file or directory)
open("../../include/profile.h", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4

这将告诉您发生了什么。在此示例中,文件在 cp 之前不存在(它已确定),因此出现 O_CREAT|O_EXCL。

答案2

当不同的进程写入同一文件位置时,可能会出现竞争条件。

cp 过程A:

  • action1:发现文件不存在
  • 动作2:创建文件

cp 进程B:

  • action1:发现文件不存在
  • 动作2:创建文件

当B.action2发生在A.action1和A.action2之间时,A会报错“cp:无法创建常规文件‘???’:文件存在”

相关内容