Autodl算力云数据盘清理实战:从手动操作到自动化脚本

1次阅读
没有评论

共计 2508 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景痛点

最近在用 Autodl 跑深度学习训练时,突然收到 ”No space left on device” 的报错,发现 200GB 的数据盘居然被塞满了。手动清理时又遇到各种坑:

Autodl 算力云数据盘清理实战:从手动操作到自动化脚本

  • 直接 rm -rfDevice or resource busy,不知道哪个进程在占用文件
  • 误删了还没备份的 checkpoint 文件
  • 清理后没多久空间又爆满,需要反复人工介入

技术方案

第一步:定位占用进程

遇到文件删不掉时,先用这两个工具查凶手:

# 查看正在使用指定文件的进程
lsof +D /path/to/directory  

# 更直接的方式(推荐)fuser -vm /path/to/mount_point

会显示类似这样的输出:

                     USER        PID ACCESS COMMAND
/mnt/data:           user1     12345 ..c.. python
                     user2     67890 F.... jupyter-lab

第二步:安全卸载文件系统

确认无重要进程后,标准卸载流程:

# 正常卸载(推荐首选)sudo umount /mnt/data

# 遇到顽固占用时(慎用)sudo umount -l /mnt/data  # lazy 卸载

# 终极手段(可能损坏数据)sudo umount -f /mnt/data  # 强制卸载

第三步:自动化清理脚本

新建cleaner.py(记得 chmod +x):

#!/usr/bin/env python3
import os
import time
import logging
from datetime import datetime, timedelta

# 配置区域 ===========================
TARGET_DIR = "/mnt/data/temp"  # 监控目录
THRESHOLD = 80  # 磁盘使用百分比阈值
MAX_AGE_DAYS = 7  # 文件最大保留天数
LOG_FILE = "/var/log/cleaner.log"  # 日志路径
# ===================================

def setup_logging():
    logging.basicConfig(
        filename=LOG_FILE,
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s'
    )

def check_disk_usage():
    stat = os.statvfs(TARGET_DIR)
    used_percent = 100 - (stat.f_bavail * 100 / stat.f_blocks)
    return used_percent

def should_delete(filepath):
    # 跳过隐藏文件和当前目录
    if os.path.basename(filepath).startswith('.'):
        return False

    # 检查文件年龄
    file_mtime = datetime.fromtimestamp(os.path.getmtime(filepath))
    return (datetime.now() - file_mtime) > timedelta(days=MAX_AGE_DAYS)

def safe_remove(filepath):
    try:
        if os.path.isfile(filepath):
            os.remove(filepath)
            logging.info(f"Deleted file: {filepath}")
        elif os.path.isdir(filepath):
            os.rmdir(filepath)  # 确保目录为空
            logging.info(f"Deleted dir: {filepath}")
    except Exception as e:
        logging.error(f"Failed to delete {filepath}: {str(e)}")

if __name__ == "__main__":
    setup_logging()

    if check_disk_usage() > THRESHOLD:
        logging.warning("Disk space over threshold! Starting cleanup...")

        for root, dirs, files in os.walk(TARGET_DIR, topdown=False):
            [safe_remove(os.path.join(root, f)) for f in files if should_delete(os.path.join(root, f))]
            [safe_remove(os.path.join(root, d)) for d in dirs if should_delete(os.path.join(root, d))]

        logging.info(f"Cleanup completed. Current usage: {check_disk_usage():.1f}%")

避坑指南

模型 checkpoint 保护

  • 给重要文件添加 .keep 后缀
  • 使用专用目录存放(如/mnt/data/checkpoints
  • 在脚本中添加白名单逻辑:
WHITELIST = ['model.pt', 'checkpoint']

def should_delete(filepath):
    return not any(w in filepath for w in WHITELIST)

处理 Docker 占用

常见报错:rm: cannot remove 'file': Device or resource busy

解决方案:

# 1. 找出关联容器
docker ps -q | xargs docker inspect --format '{{.State.Pid}} {{.Name}}' | grep $(fuser -vm /mnt/data)

# 2. 临时停用容器
docker stop container_name

# 3. 清理后重启
docker start container_name

IO 负载控制

大规模删除时用 ionice 降低优先级:

ionice -c 3 ./cleaner.py  # 设置为空闲级别

延伸思考

长期解决方案可以结合对象存储:

  1. 将训练数据预先存放在 OSS/S3
  2. rclone 挂载到实例
  3. 设置生命周期策略自动清理旧数据

下次可以聊聊怎么用 rclone mount 实现这个方案~

正文完
 0
评论(没有评论)