我有一个 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:无法创建常规文件‘???’:文件存在”