Heroku上ActiveStorage::AnalyzeJob报磁盘空间不足错误如何彻底解决?
问题根因说明
Errno::ENOSPC报错是因为Heroku dyno的/tmp目录磁盘被占满,该目录默认配额仅512MB,且数据会在dyno重启/重新部署时清空。ActiveStorage原生设计确实会在analyze任务执行完成后清理临时文件,但两种场景会导致清理失效:
- 低版本Rails存在ActiveStorage临时文件泄漏的已知bug,任务结束后未执行删除逻辑
- 短时间并发大量analyze任务,临时文件生成速度远高于清理速度,提前占满磁盘
修复方案
1. 修复框架层面的临时文件泄漏
- 优先升级Rails到6.1.4+或7.0+版本,这些版本已修复所有已知的ActiveStorage临时文件未正常清理的问题
- 若暂时无法升级框架,可新增初始化配置强制清理任务临时文件,在
config/initializers/active_storage.rb中添加以下代码:
Rails.application.config.to_prepare do ActiveStorage::AnalyzeJob.around_perform do |job, block| block.call # 任务执行完成后强制删除对应临时文件 temp_file_path = job.blob.service.send(:path_for, job.blob.key) rescue nil FileUtils.rm_f(temp_file_path) if temp_file_path && File.exist?(temp_file_path) end end
2. 限制analyze任务并发量
- 将ActiveStorage的analyze、transform等处理任务单独归入一个专用的后台队列,限制该队列的最大并发数:如果平均处理文件大小在10MB以内,并发数最多设置为5;如果是超过50MB的大文件,并发数控制在2以内
- 批量上传场景下,给analyze任务增加3-5秒的执行延迟,分批触发避免短时间生成大量临时文件
3. 定期自动清理冗余临时文件
- 配置定时任务,每10分钟执行一次清理命令,删除10分钟前生成的ActiveStorage临时文件:
find /tmp -mmin +10 -name "ActiveStorage-*" -type f -delete - 该逻辑不会删除正在执行中的任务的临时文件,不会影响正常业务
4. 优化临时文件存储(可选)
如果需要频繁处理大体积文件,可将ActiveStorage临时文件存储路径修改为dyno的内存挂载点/dev/shm,该路径读写性能更高,且不会和应用其他进程的临时文件抢占磁盘配额,在config/environments/production.rb中添加配置即可:
config.active_storage.tmpdir = "/dev/shm"
内容的提问来源于stack exchange,提问作者Dorian
相关产品推荐
相关产品推荐

