cp: 无法创建普通文件 : 文件已存在
背景
碰到一个偶现的编译出错问题,如图
报错的信息是
cp: 无法创建普通文件"xxx": 文件已存在
排查原因
看了下 Makefile
,这句非常简单,就是 cp ./xxx ../xxx
而已,本身没什么问题。
那再结合上下文出现的打印,一个异常之处就是 Makfeile
被并行重复执行了,猜测是并行导致 cp
操作出错。
只考虑解决问题,那无疑是修改外层 Makefile
,避免此处被并行重复执行,至少这句 cp
不要被并行,就可以解决了。
但为什么 cp
并行执行会出错呢?如果在另外的场景下确实有并行执行cp
的可能,有没有办法规避这个错误呢?这就得探究下了。
单独执行 cp
,默认的行为就是覆盖已存在的文件,并不会因为 “文件已存在” 这样的原因出错,随便做下实验,touch a b; cp a b
就可以确认正常是不会报错的。
那问题还是得结合并行来分析,碰到这种情况,要么是从搜索资料获得提示,要么就是实践出真知,自己设计一个可快速复现的方式,然后使用调试工具来追踪问题发生时的具体情况。
具体到这个问题,我是搜索到相同的stackexchange问题,那就省点工夫不用自己去复现分析了。
这里插下题外话,搜索优先使用google
,对于中文报错信息查不到的可改成英文查询。例如中文的 cp: 无法创建普通文件 文件已存在
就不好找到答案,换成 cp cannot create regular file file exists
就好找了。(只敲一部分,搜索引擎就能提示完整的信息)
stackexchage
上给出了一个脚本,用于复现问题并使用 strace
将追踪的系统调用记录下来
#!/bin/bash
touch a
f() {
while true; do
rm -f b
strace -o /tmp/cp${BASHPID}.trace cp a b || break
done
}
cleanup() {
kill -9 %1 %2
}
f &
f &
trap cleanup exit
wait
附上我自己的实验结果,可以看出cp
的实现上,会先用stat
来判断目标文件b
是否存在,如果不存在则会使用 open("b", O_WRONLY|O_CREAT|O_EXCL, 0664)
来创建目标文件并将源文件写入目标文件,完成复制。
那么如果两个 cp
并发,就可能出现
cp1 cp2
stat判断b不存在
stat判断b不存在
open成功,创建文件b
open失败,因为此时文件已经被cp1创建好了
从 strace
的 log
看到的就是
由于 cp
不是原子的,如果两个 cp
刚好几乎同时执行,则可能两个 cp
的stat
都判断到文件不存在,那最终只有一个 cp
能创建文件,另一个就失败了。
顺便看看,文件存在和不存在的open
参数差异
解决办法
既然两个cp
同时执行会出错,那就加锁呗。
如果所有调用 cp
的地方都是我们可控的,那劝告锁就足够了,在 shell
中可以直接使用 flock
。
约定好一个文件锁x
, 将原来的cp a b
改成 flock x cp a b
即可。
例如正常在两个控制台中,执行top
是可以并行的,但如果改成执行 flock /tmp/toplock top
,那就只有控制台1
会执行top
,控制台2
则处于等待文件锁的状态。此时若控制台1
退出top
,则控制台2
获得锁,开始执行top
。
更多文件锁的细节,可以看看 man flock
。
blog: https://www.cnblogs.com/zqb-all/p/12942556.html
公众号:https://sourl.cn/S42YSr
cp: 无法创建普通文件 : 文件已存在的更多相关文章
- [转]iOS学习笔记(2)--Xcode6.1创建仅xib文件无storyboard的hello world应用
转载地址:http://www.mamicode.com/info-detail-514151.html 由于Xcode6之后,默认创建storyboard而非xib文件,而作为初学,了解xib的加载 ...
- iOS学习笔记(2)--Xcode6.1创建仅xib文件无storyboard的hello world应用
http://www.mamicode.com/info-detail-514151.html 由于Xcode6之后,默认创建storyboard而非xib文件,而作为初学,了解xib的加载原理很重要 ...
- JAVA之旅(二十八)——File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤
JAVA之旅(二十八)--File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤 我们可以继续了,今天说下File 一.File概述 文件的操作是非常 ...
- Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件
写在前面 从大四实习至今已一年有余,作为一个程序员,一直没有用心去记录自己工作中遇到的问题,甚是惭愧,打算从今日起开始养成写博客的习惯.作为一名java开发人员,Spring是永远绕不过的话题,它的设 ...
- [Swift]在Swift项目中创建桥接头文件,Swift文件和Objective-C文件相互调用
创建一个Swift项目[demo],以下内容Swift文件和Objective-C文件相互调用都是在Swift项目中. 一.Swift文件调用Objective-C文件 新建文件夹[SupportFi ...
- 【练习】Java中的读文件,文件的创建,写文件
前言 大家好,给大家带来Java中的读文件,文件的创建,写文件的概述,希望你们喜欢 读文件 public static void read(String path,String filename){ ...
- Excel催化剂开源第4波-ClickOnce部署要点之导入数字证书及创建EXCEL信任文件夹
Excel催化刘插件使用Clickonce的部署方式发布插件,以满足用户使用插件过程中,需要对插件进行功能升级时,可以无痛地自动更新推送新版本.但Clickonce部署,对用户环境有较大的要求,前期首 ...
- Java中的读文件,文件的创建,写文件
前言 大家好,我是 Vic,今天给大家带来Java中的读文件,文件的创建,写文件的概述,希望你们喜欢 示意图 读文件 public static void read(String path,Strin ...
- 为什么vue-cli创建的build文件下没有dev-server.js文件
在新版本的Vue开发中,通过vue-cli创建的build文件夹下面已经没有了旧版本中的dev-server.js文件新版本的vue已将dev-server.js与webpack.dev.conf.j ...
随机推荐
- Ceph 12.2.0 实践osd 智能分组功能
以前我们需要对ssd和hdd进行分组的时候,需要大量的修改crush map,然后绑定不同的存储池到不同的 crush 树上面,现在这个逻辑简化了很多.以上是官方宣传听起来很不错等到12.2.0稳定版 ...
- ajax学习摘抄笔记
2019独角兽企业重金招聘Python工程师标准>>> AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). A ...
- iOS自定义tabBar
在我们的项目中经常会自己自定义tabBar因为苹果自带的真的太丑了!也不满足我们的项目需求. 好 开始行动吧! 先上图看下我们最终实现的效果: 继承UItabBar自定义一个自己的tabBar .h# ...
- Codeforce-Ozon Tech Challenge 2020-D. Kuroni and the Celebration(交互题+DFS)
After getting AC after 13 Time Limit Exceeded verdicts on a geometry problem, Kuroni went to an Ital ...
- [UWP]推荐一款很Fluent Design的bilibili UWP客户端 : 哔哩
UWP已经有好几个Bilibili的客户端,最近有多了一个: 哔哩 - Microsoft Store 作者云之幻是一位很擅长设计的UWP开发者,我也从他那里学到了很多设计方面的技巧.它还是一位Bil ...
- JavaWeb----Servler
Servlet简介 Servlet就是sun公司开发动态web的一门技术 Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤: 编写一个类, ...
- E. Sasha and Array 矩阵快速幂 + 线段树
E. Sasha and Array 这个题目没有特别难,需要自己仔细想想,一开始我想了一个方法,不对,而且还很复杂,然后lj提示了我一下说矩阵乘,然后再仔细想想就知道怎么写了. 这个就是直接把矩阵放 ...
- 软路由OpenWrt(LEDE)2020.5.10更新 UPnP+NAS+多拨+网盘+DNS优化
近期更新:2020.05.10更新-基于OpenWrt R2020.5.9版本,源码截止2020.05.10. 交流群:QQ 1030484865 电报 t.me/t_homelede 版本说 ...
- 【源码】RingBuffer(二)——消费者
消费者如何读取数据? 前一篇是生产者的处理,这一篇讲消费者的处理 我们都知道,消费者无非就是不停地从队列中读取数据,处理数据.但是与BlockedQueue不同的是,RingBuffer的消费者不会对 ...
- JDK/Java 14 发布
3 月 17 日,JDK/Java 14 正式 GA. 此版本包含的 JEP(Java/JDK Enhancement Proposals,JDK 增强提案)比 Java 12 和 13 加起来的还要 ...