
最近在一台 CentOS 7.9 服务器上折腾 ModelScope遇到一个特别典型的问题模型下着下着根分区突然满了。查了半天罪魁祸首就是默认下载目录。ModelScope 的 Python 库在下载模型时会把文件默认放到当前用户家目录下的隐藏目录里也就是~/.cache/modelscope/hub。如果你的 CentOS 是早期规划的分区根目录只给了 50GB 甚至更小几十 GB 的模型一旦落进去磁盘告警几乎是必然的。这篇文章就围绕 CentOS 下 ModelScope 模型下载的默认目录展开把默认路径的来龙去脉、修改方式、迁移流程以及常见问题排查一次说清楚。内容偏实操适合在 CentOS 上做模型下载、推理部署的算法工程师和运维同学也适合刚接触 ModelScope 的新手少走弯路。1. 先搞清楚ModelScope的默认目录到底在哪1.1 默认缓存路径与目录结构先用最简单的方式解释默认目录你执行pip install modelscope装好官方 Python SDK 后不管是通过代码里的snapshot_download下载模型还是用AutoModel.from_pretrained这类接口加载模型只要没有显式指定存放位置ModelScope 就会把文件缓存到当前用户家目录下的固定位置。对于绝大多数 CentOS 用户来说当前用户是 root所以实际路径就是/root/.cache/modelscope/hub如果你是用普通用户登录的那就是/home/用户名/.cache/modelscope/hub。这跟你用什么 Python 环境没关系关键看运行进程的操作系统用户是谁。目录里面不是一锅粥ModelScope 会按资源类型继续分~/.cache/modelscope/hub/ ├── models/ │ └── Qwen/ │ └── Qwen2-7B/ │ ├── 版本快照目录 │ ├── 配置文件 │ └── 模型权重文件 └── datasets/ └── 某些数据集模型文件并不一定直接铺在models下面有些版本会多一层 owner 名称也就是模型 ID 的命名空间。比如Qwen/Qwen2-7B这个 ID实际缓存路径就是models/Qwen/Qwen2-7B。如果你下载的是damo/nlp_structbert_backbone_base_std那路径就变成models/damo/nlp_structbert_backbone_base_std。这个逻辑跟 HuggingFace 的~/.cache/huggingface/hub很像只是目录前缀从huggingface换成了modelscope。ModelScope 下载并不是简单地把文件往里一丢。它会先创建临时文件写入完成后再做重命名或者创建软链接同时还会记录一些版本、校验相关的元数据。这样做的好处是支持断点续传也能避免下载到一半把已有文件弄坏。但副作用是同一份文件可能会在缓存目录里占两份空间最典型的是快照目录里的一个模型文件实际对应一个 blob 存储对象。如果你不关心内部实现只需要记住一个结论下载大模型时缓存目录的临时峰值空间可能比模型实际大小还要大预留给根分区的空间一定要留足。1.2 为什么CentOS上这个问题特别容易踩坑有的同学可能想问明明 Ubuntu 上也会缓存到这个目录为什么偏偏 CentOS 上这个问题更突出答案不在 ModelScope而在 CentOS 的磁盘分区习惯。早期部署 CentOS 服务器时很多运维为了省事直接按默认分区来装系统。默认方案通常会单独分一个/boot然后把根分区/和 home 分区分开但根分区本身并不会给很大。50GB、80GB 的根分区在跑传统 Web 服务时绰绰有余可放到今天的大模型场景里连模型带缓存很容易就塞满了。数据盘倒是往往很大但挂在/data或者/home下和模型默认目录八竿子打不着。另外CentOS 的存量用户基数确实大。现在热词里经常有人问“为什么 Ubuntu 现在比 CentOS 多”这背后有很多原因包括 CentOS 8 停服、CentOS 7 也进入维护末期等等。但大量已经在跑的生产服务器还是 CentOS 7尤其是企业内部对稳定性格外看重不会轻易整个重装系统。于是新需求撞上旧系统模型下载这种高磁盘占用业务碰到了根分区规划不足的老问题。我举一个实际场景下载一个 7B 参数的模型光原始权重文件就是 15GB 左右。如果下载工具还要保留校验副本再算上运行时的临时文件占用轻松翻倍。再加上 CentOS 本身有系统日志、YUM 缓存根分区剩余几 GB 空间可能转眼就被大模型打满。这也是为什么很多人遇到“下载到一半失败”“磁盘满了”第一反应是查网络最后发现其实是目录放错了地方。1.3 查看当前实际目录的方法不管你是刚遇到问题还是想提前排查下面这几个命令建议先跑一遍。第一步是看环境变量里有没有人为改过默认目录echo $MODELSCOPE_CACHE如果输出为空说明 ModelScope 还在用默认目录如果有路径说明之前有人设置过环境变量后面排查要围绕这个路径来看。然后看默认缓存是否存在以及占用多大ls -lah ~/.cache/modelscope/hub 2/dev/null du -sh ~/.cache/modelscope 2/dev/null如果模型已经在下载du出来的数值会不断变大。如果目录不存在那说明 ModelScope 可能还没跑过真正的下载流程。还有一种情况是程序已经跑起来但你不知道它到底用的是哪个目录可以全局搜一下名为 modelscope 的目录find / -type d -name modelscope -not -path /proc/* 2/dev/null这个命令会把系统中所有名字叫 modelscope 的目录列出来适合用来排查多个用户、多个环境变量导致的目录混乱。不过要注意如果当前正在下载大文件du和df -h看到的磁盘占用可能并不一致。比如某个文件已经被删掉但还被 Python 进程占用着这时候磁盘空间不会立刻释放。可以用lsof L1或lsof | grep deleted看看有没有僵尸文件占着空间。2. 修改默认目录的几种方式2.1 环境变量设置MODELSCOPE_CACHE最推荐的方式是设置环境变量MODELSCOPE_CACHE。这个变量是 ModelScope 官方留给用户自定义缓存根目录的入口效果跟 HuggingFace 那边的HF_HOME类似。设置之后ModelScope 会把hub目录创建到你指定的位置而不是默认的~/.cache/modelscope。临时生效可以这样export MODELSCOPE_CACHE/data/modelscope如果要长期生效建议写到当前用户的.bashrc里echo export MODELSCOPE_CACHE/data/modelscope ~/.bashrc source ~/.bashrc如果你希望这台机器上所有用户都统一走同一个目录可以写到/etc/profile.d/modelscope.sh这个文件里加一行export语句即可所有用户重新登录后都会加载。需要留意的是如果用 systemd 管理模型服务普通.bashrc里的环境变量可能不会传给 systemd 服务进程。正确的做法是在 service 文件里加EnvironmentMODELSCOPE_CACHE/data/modelscope或者用 EnvironmentFile 指定一个配置文件。设置完之后先别急着下载大模型用echo $MODELSCOPE_CACHE确认路径生效再跑一个小模型试试避免白折腾一趟。2.2 代码里指定cache_dir有些场景不适合全局改环境变量。比如你同时跑多个项目一部分模型希望放在/data/models另一部分希望放在/data/tmp_models那在代码里显式指定目录更灵活。ModelScope 核心下载函数是snapshot_download它支持cache_dir参数from modelscope.hub.snapshot_download import snapshot_download model_dir snapshot_download( Qwen/Qwen2-7B, cache_dir/data/modelscope ) print(model_dir)这样模型就会下到/data/modelscope下不会碰默认目录。如果你是通过AutoModel.from_pretrained这类高层接口加载模型有些版本也会把cache_dir参数透传下去具体要看当前 ModelScope 版本的 API 签名。拿不准的时候可以先help(snapshot_download)看参数列表或者直接print一下返回的路径确认模型到底落在哪。代码里显式指定目录的优点是清晰可控缺点是要改业务代码而且团队其他成员如果不注意还是可能走默认目录。2.3 CLI下载工具指定目录如果你不喜欢写 PythonModelScope 也提供了命令行工具。新版 SDK 安装后一般自带modelscope命令典型用法是modelscope download --model Qwen/Qwen2-7B --local_dir /data/models/ Qwen/Qwen2-7B--local_dir参数会直接把模型文件放到指定位置而不是按默认缓存目录的复杂结构来组织。这很适合部署场景你希望最终模型文件就在某个固定目录路径简单后续给推理服务引用也方便。需要注意两点。第一modelscope命令不一定在 PATH 里尤其当你用虚拟环境或者用户级 pip 安装时。如果提示command not found可以用python -m modelscope代替或者把 Python 的 bin 目录加到 PATH。第二不同版本的命令行参数可能有差异最稳妥的方式是:modelscope download --help先看帮助信息再执行免得参数拼错。2.4 几种方式的优先级和建议我把常用方式整理成一个对比表方便你按场景选择。方式生效范围优点适合场景环境变量 MODELSCOPE_CACHE全局/用户级一次设置所有代码和命令行默认生效服务器长期跑多个模型的场景snapshot_download 的 cache_dir单次调用灵活可精确控制目录临时测试、不同项目分流CLI 的 --local_dir单次下载目录直观便于部署需要固定模型路径的部署场景软链接或 mount bind文件系统级无需改代码和环境变量目录已占用且程序改起来麻烦关于优先级我自己的实测经验是代码里显式传的cache_dir优先于环境变量环境变量优先于默认目录。不过 ModelScope 不同版本对参数的处理不完全一样如果你发现设置了环境变量但代码里没有传参模型还是下到了别的地方第一件事就是检查是不是代码里传了cache_dir第二件事是检查有没有另一个环境变量覆盖了你设置的路径。3. 实操把已下载的模型从根分区迁到数据盘3.1 迁移前检查如果你的根分区已经告急最实际的方案不是重新下载一遍模型而是把已经下好的文件整体迁移到数据盘再做软链接让 ModelScope 继续以原路径访问。动手之前先做三件事。第一看磁盘空间df -h重点看根分区/的使用率以及目标数据盘有没有足够空间。模型缓存有多大、目标盘剩多少至少要有 1.2 倍余量因为迁移过程需要临时空间。第二看缓存目录实际大小du -sh /root/.cache/modelscope如果这个数值很大比如几十 GB迁移分两步更安全先用 rsync 同步再切换。如果只有几 GB直接 mv 也行。第三确认没有进程正在使用缓存目录。最好先停掉正在下载或推理模型的 Python 进程ps aux | grep python如果担心有文件占用用lsof /root/.cache/modelscope查看。迁移过程中如果文件持续被写复制出来的目录结构可能是残缺的后面加载模型时会出现莫名其妙的报错。这个坑我踩过当时图省事没停进程结果模型权重文件复制到一半等复制完才发现文件大小不对白白多花了半小时排查。3.2 用rsync复制并软链接迁移我推荐用 rsync 而不是直接 mv因为缓存目录可能在根分区而目标在数据盘这属于跨文件系统搬迁。跨文件系统的 mv 本质上也是先复制再删除但中途如果断了恢复起来很麻烦。rsync 支持断点续传还能保留权限和时间戳更稳妥。第一步把缓存完整同步到数据盘rsync -av --partial /root/.cache/modelscope/ /data/modelscope/命令里的--partial很关键它允许保留部分传输的文件网络中断或者终端断了之后重新执行会继续传输而不是从头再来。耐心等它跑完看到传输完成再进入下一步。第二步把原目录改个名留作备份mv /root/.cache/modelscope /root/.cache/modelscope.bak第三步建立软链接ln -s /data/modelscope /root/.cache/modelscope第四步验证目录是否能正常访问ls -la /root/.cache/modelscope ls -la /root/.cache/modelscope/hub/models 2/dev/null | head如果能列出模型目录说明软链接生效了。紧接着可以跑一个小的模型加载或者下载任务确认 ModelScope 能正常读写新目录。第五步确认一切正常后删除备份rm -rf /root/.cache/modelscope.bak备份不要急着删最好让模型任务跑一段时间确认没有问题再清理。如果迁移的是好几 GB 甚至几十 GB 的模型备份太早删掉等真出问题时重新下载反而更花时间。3.3 SELinux和权限问题CentOS 默认可能开启了 SELinux这一点和 Ubuntu 很不一样。很多人在迁移目录后遇到“明明权限是 755文件也有就是报权限拒绝”第一反应是chmod但真正的问题可能是 SELinux 上下文不对。软链接本身一般不会拦但目标目录的 SELinux 标签如果和进程类型不匹配访问就会被拦截。可以先看看目录的上下文ls -Z /data/modelscope如果发现类型和普通目录不一样可以尝试恢复默认上下文restorecon -Rv /data/modelscope如果还不行用ausearch -m avc -ts recent查一下最新的拒绝日志看看具体是哪一步被拦。临时关闭 SELinux 可以用来做对比实验但生产环境不建议长期关掉:setenforce 0测完记得setenforce 1恢复。另外目录权限要匹配运行用户。如果你用 root 迁移那目录属主是 root如果后面想用其他用户跑模型最好 chown 过去chown -R 用户名:用户组 /data/modelscope否则会看到“Permission denied”。3.4 用mount --bind替代软链接软链接也不是唯一办法。如果某个程序把/root/.cache/modelscope写死得非常深或者你不想让逻辑路径变成链接目标可以考虑用mount --bind直接把数据盘目录绑定到原目录上。先建好目标目录然后绑定mkdir -p /root/.cache/modelscope mount --bind /data/modelscope /root/.cache/modelscope执行之后应用访问/root/.cache/modelscope时实际上就是在访问/data/modelscope路径完全无感。这个方式比软链接更透明很多对路径要求苛刻的框架不会因为符号链接出问题。缺点是重启服务器后挂载关系会丢失需要写入/etc/fstab/data/modelscope /root/.cache/modelscope none bind 0 0写完建议用mount -a测试一遍避免重启后才发现挂载失败。这个方案和软链接各有各的适用场景我自己更习惯用软链接因为直观好排查但如果你的程序对软链接有奇怪的行为mount bind 是不错的备选。4. 常见问题与排查技巧4.1 磁盘空间突然满了怎么办这是最典型的问题。报错可能五花八门但底层往往是磁盘满了。比如No space left on device、模型下载到一半卡住、Python 进程被 kill甚至 MySQL 突然写不进去都有可能是根分区被模型缓存塞满。排查顺序我建议这样df -h看哪个分区满了。du -sh /root/.cache/modelscope确认缓存占用。lsof | grep deleted看有没有删除但仍被进程占用的文件。如果确认是模型缓存按照第 3 节迁移或者清理掉不再用的大模型文件。可以用一个表格快速对照现象可能原因快速处理下载报 No space left on device默认目录所在分区打满清理缓存或迁移目录模型加载时文件校验失败缓存文件不完整删除对应模型重新下载程序被 kill退出码 137内存或磁盘不足df -h 查磁盘dmesg 查 OOM下载特别慢网络或磁盘 IO 问题换网络环境考虑换 SSD 数据盘4.2 模型下载慢、总是中断热搜词里“模型下载加速”“ComfyUI 下载模型很慢”“Ollama 下载模型慢”这类问题经常出现。其实很多慢的根源不是网速本身而是下载链路上绕了远路。ModelScope 本身就是国内平台直连它的下载速度通常比绕到国外站点快得多。如果你之前习惯了从 HuggingFace 拉模型到了 ModelScope 这边可以直接用尽量不要用“中转”方式再绕一圈。如果确实还是慢建议用后台任务跑下载避免终端断开就前功尽弃tmux new -s model_download modelscope download --model Qwen/Qwen2-7B --local_dir /data/models/Qwen/Qwen2-7B按Ctrlb然后按d退出会话模型下载在后台继续。重新连接时用tmux attach -t model_download查看进度。ModelScope SDK 一般支持断点续传网络中断后重新执行同一命令会接着下载而不是从头开始。但如果中途磁盘满了可能导致缓存文件损坏所以下载大模型之前一定要先确认目录空间。4.3 CPU环境长时间跑任务莫名退出有人问“ModelScope 的 CPU 环境不能运行长时间任务吗”从我实际经验来看不是不能跑而是容易触到系统资源上限。CPU 推理本身很慢如果模型参数又不小跑了几个小时之后内存可能越占越多最后被 OOM Killer 杀掉。排查时先看系统日志dmesg | grep -i oom如果有Out of memory相关记录说明是内存不够。对策是限制并发、分批推理、或者加 swapfallocate -l 16G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile但注意swap 文件本身也要占磁盘空间这又绕回到磁盘规划的问题。如果根分区本来就紧张加 swap 前先把模型目录迁移走否则 swap 一开磁盘立刻又满了。4.4 pip install modelscope后命令找不到这是个很入门但也有点烦人的问题。尤其是 CentOS 7 这种自带 Python 2.7 的系统很多同学直接用pip装结果装的可能是 Python 2 的包而自己平时用的是 Python 3当然找不到命令。建议先确认你用的 pip 属于哪个 Pythonwhich python python --version which pip pip --version如果你用的是 Python 3最好用虚拟环境或 conda 环境隔离。安装完 ModelScope 后如果modelscope命令找不到检查一下 Python 的 bin 目录是否在 PATHpython -m modelscope --help用python -m这种调用方式通常能绕开 PATH 问题。4.5 缓存文件损坏导致加载异常有时候模型文件明明就在默认目录里而且占了几十 GB但加载时总说文件缺失或校验失败。这种情况多半是缓存文件损坏。ModelScope 的缓存目录里存在临时文件和正式文件之间的关联如果你手动把模型文件从别处复制进缓存目录但目录结构不符合规范很容易翻车。最稳妥的解决办法是找出对应模型的缓存子目录删掉再重新下载rm -rf /root/.cache/modelscope/hub/models/Qwen/Qwen2-7B modelscope download --model Qwen/Qwen2-7B --local_dir /data/models/Qwen/Qwen2-7B不建议直接往缓存目录里手动放文件除非你完全了解它的结构。如果模型是从别处拷来的二进制文件建议放到自己的业务目录然后用--local_dir或者代码里的路径去加载而不是伪装成默认缓存。5. 一些个人体会和补充建议5.1 新项目到底还要不要用CentOS既然热词里反复出现“为什么 Ubuntu 现在比 CentOS 多”我也说说自己的看法。如果是从零搭服务器我真的不建议新项目继续选 CentOS 了Ubuntu、Debian 在社区活跃度、软件包版本、驱动兼容性上都更省心很多 AI 框架也优先适配新系统。但如果你手头有大量还在稳定运行的 CentOS 7 服务器没必要因为模型下载这种小问题推倒重来。把默认目录、权限、SELinux 这些点理顺CentOS 跑模型下载和推理完全没问题。5.2 团队共享缓存的最佳实践多个人共用一台 CentOS 服务器时最怕的是每个人都在自己的家目录里下载一份模型。一两个模型还好模型多了之后每个用户重复占几十 GB磁盘很快就爆。我的做法是设置一个公共缓存目录比如/opt/modelscope_cache然后让所有用户的环境变量MODELSCOPE_CACHE都指向这里。配合目录权限保证同一个用户组下的人都能读写mkdir -p /opt/modelscope_cache chgrp -R ai-group /opt/modelscope_cache chmod -R 775 /opt/modelscope_cache这样模型下载任务可以由管理员统一跑一次其他用户直接复用磁盘占用会大幅下降。需要注意并发下载同一个模型时ModelScope 内部通常会做文件锁或幂等处理但如果你手动管理目录还是尽量避免多个进程同时写同一个目标文件。5.3 最后的几点小技巧最后分享几个我用下来比较受益的小习惯。第一设置环境变量后先下载一个小模型验证路径别一上来就拉几十 GB 的大模型。花一分钟跑个几百 MB 的小模型能确认目录变更没写错避免浪费流量和时间。第二模型和数据集尽量分开。ModelScope 的缓存根目录同时管模型和数据集如果你想分别放到不同分区可以不用统一的环境变量而是在代码里分别给snapshot_download传不同的cache_dir。比如模型放/data/models数据集放/data/datasets这样即使某一个分区满了也不影响另一个。第三定期清理旧版本的模型。ModelScope 会为同一模型保留不同版本的快照目录时间长了会发现缓存目录越来越大。检查一下hub/models/xxx下面的子目录把已经用不到的版本删掉能释放不少空间。第四如果你用 systemd 管理服务环境变量别只写在.bashrc里。systemd 进程不会自动读取 shell 的环境变量需要在 service 文件里显式声明。这个坑特别隐蔽有时候你手动执行程序一切正常但服务一启动就下载到默认目录根分区又被填满查了很久才发现是环境变量没传进去。ModelScope 的默认目录本身不复杂但落在 CentOS 这个老派系统上牵扯到分区、权限、SELinux、多用户共享问题就变得立体了。我自己的经验是先把目录逻辑想清楚再动手改配置最后用小模型验证。这套流程走顺之后CentOS 上跑 ModelScope 也能非常省心。