You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu环境下os.path.exists与os.makedirs结果不符问题排查求助

问题分析与解决方案

这是一个典型的竞态条件问题,不过结合你提到的AWS EBS存储和Zabbix的I/O等待告警,咱们得从代码和存储两个层面来拆解:

1. 代码层面的核心问题:竞态条件

你写的代码逻辑是先判断父目录是否存在,不存在就创建,但os.path.exists()和os.makedirs()这两个操作之间存在时间窗口——哪怕这个窗口很短,也可能有其他进程(或者你自己程序的其他线程)在这段时间里创建了目标目录。当os.makedirs()执行时,发现目录已经存在,就会抛出OSError: [Errno 17] File exists。

另外还要注意一种极端情况:如果目标路径不是目录而是一个文件,os.path.exists()会返回True,但os.makedirs()还是会报错,不过从你的报错信息看,路径是目录,所以主要还是竞态的锅。

2. AWS EBS与Zabbix告警的关联

Zabbix提示磁盘写入CPU I/O等待时间过高,说明你的EBS卷正处于高负载状态——可能是IOPS不够用、网络延迟高,或者存储本身出现短暂的性能波动。这种情况下,os.path.exists()的元数据检查和os.makedirs()的目录创建操作之间的时间间隔会被拉长,竞态条件触发的概率就会大幅提升。

虽然EBS是强一致性存储,但高负载下元数据的同步可能出现短暂延迟,也可能让os.path.exists()的结果和实际存储状态出现偏差,不过这不是主要原因,核心还是代码的竞态漏洞被存储问题放大了。

3. 是代码问题还是存储问题?

两者都有:

  • 代码本身存在竞态缺陷,这是根本原因——哪怕存储性能再好,只要有并发操作,就可能触发这个错误;
  • EBS的高I/O等待是诱因,它让竞态发生的概率变高,原本很少出现的错误变得频繁。

4. 解决办法

修复代码的竞态问题

最直接的方式是利用Python内置的安全机制,避免先检查后创建的逻辑:

  • 方法一:使用os.makedirs的exist_ok=True参数(Python 3.2+支持),这样即使目录已存在也不会报错:
    parent_dir = os.path.abspath(os.path.join(file_path, os.pardir))
    os.makedirs(parent_dir, exist_ok=True)
    
  • 方法二:用try-except捕获特定错误,兼容更低版本的Python:
    import errno
    parent_dir = os.path.abspath(os.path.join(file_path, os.pardir))
    try:
        os.makedirs(parent_dir)
    except OSError as e:
        # 只忽略"目录已存在"的错误,其他异常正常抛出
        if e.errno != errno.EEXIST:
            raise
    

排查EBS存储问题

  • 检查EBS卷的IOPS配置:如果用的是通用型SSD (gp2/gp3),看看是否达到了IOPS上限,考虑升级到Provisioned IOPS SSD (io1/io2);
  • 检查挂载点状态:确认EBS卷挂载稳定,没有出现短暂的断开重连情况;
  • 分析系统I/O:用iostat、iotop工具排查具体是哪个进程在占用大量I/O,优化读写逻辑。

内容的提问来源于stack exchange,提问作者adamczi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:21:46