专栏首页QB杂货铺cp: 无法创建普通文件 : 文件已存在

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创建好了

stracelog 看到的就是

由于 cp 不是原子的,如果两个 cp 刚好几乎同时执行,则可能两个 cpstat都判断到文件不存在,那最终只有一个 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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一种分片更新ubi卷的方式(基于ubiupdatevol,拓展fifo支持)

    对于ubi卷,不能像普通块设备一样进行随机读写。每次更新需要从头写入。 具体的,需要在打开对应的设备之后,先执行一个ioctl UBI_IOCVOLUP,同时...

    zqb_all
  • 命令行工具PathMarker

    大概的意思就是,显示在终端上的数据会经过匹配,如果符合一定的规则,则可以按住ctrl,使用鼠标单击以触发指定操作。

    zqb_all
  • 自己封装Linux命令行万能解压命令

    既然记不住,那就换一种思路,假如有一条命令能解压所有文件,那就只需要记住这一条了。似乎可以写个脚本来处理,上网一搜,果然这么现实的需求早就有人想过并实现了。

    zqb_all
  • 数据分析实例:统计学在数据分析中的应用实例

    最近数据分析真的很火,很多人想学,在大数据这个概念的催生下,数据分析俨然成为了职场的必备技能之一,而很多教育培训机构或者个人也非常会抓住商机,在普遍焦虑的情况下...

    沉默的白面书生
  • 函数参数python

    函数中的默认参数,调用的时候可以给参数 赋值,也可以使用默认值 修改add函数如下

    py3study
  • 【SpringBoot DB 系列】Mybatis基于AbstractRoutingDataSource与AOP实现多数据源切换

    前面一篇博文介绍了 Mybatis 多数据源的配置,简单来讲就是一个数据源一个配置指定,不同数据源的 Mapper 分开指定;本文将介绍另外一种方式,借助Abs...

    一灰灰blog
  • 抢占云先机 Nutanix将网络规模带向企业

    目前,数据中心正在发生一股颠覆性的力量,磁盘向闪存的演进,虚拟化服务器向虚拟化数据中心扩展,私有数据中心走向混合云,企业的大规模服务器采购转向部分消费。 传统存...

    静一
  • 【SpringBoot DB 系列】Mybatis 基于 AbstractRoutingDataSource 与 AOP 实现多数据源切换

    前面一篇博文介绍了 Mybatis 多数据源的配置,简单来讲就是一个数据源一个配置指定,不同数据源的 Mapper 分开指定;本文将介绍另外一种方式,借助Abs...

    一灰灰blog
  • C++标准库里的二分查找算法剖析

    作为后台开发团队,服务性能优化是我们持续在做的事情,涵盖面比较广,包括锁优化、缓存优化、查找优化等等。这里举一个查找优化方面的例子进行说明。

    levinllin
  • 修复kubectl cp出现tar: Removing leading `/' from member names

    今天修复线上问题, 需要在pod动态修改配置文件, 发现pod里面没有安装vim, 于是先把他拷贝到本地, 修改后再覆盖回去.

    扫地工程师

扫码关注云+社区

领取腾讯云代金券

,,