Rails7应用ActionController::MissingFile异常排查(文件存在但不可读)
问题描述
我有一个Rails 7应用部署在两台独立机器上(无资源共享),其中一台可正常渲染PDF文件,因此代码本身无问题。核心代码如下:
task_list = CompletedTaskList.find(params[:id]) send_file "#{Rails.root}/reports/completed-task_report-#{task_list.code}.pdf", disposition: 'attachment'
另一台机器无法打开文件:
- 最初出现错误:
Errno::EACCES: Permission denied @ rb_sysopen - /application/reports/completed-task_report-111.pdf - 修改reports目录权限后,又出现异常:
ActionController::MissingFile: Cannot read file /application/reports/completed-task_report-111.pdf,但文件实际存在 - 文件状态检测结果:
"path: /application/reports/completed-task_report-111.pdf" "file: true" "readable: false"
尝试执行chmod -R 777修改目录权限后,问题仍未解决,文件依然不可读。
解决方案
以下是按优先级排查的步骤:
1. 匹配Rails进程用户与文件所有者/组
- 找出Rails应用的运行用户:执行
ps aux | grep puma(用Puma服务器时)或ps aux | grep rails,输出第一列即为进程所属用户(如deploy或www-data) - 查看PDF文件的所有者和组:执行
ls -l /application/reports/completed-task_report-111.pdf,观察输出第三、第四列(例如root root) - 若两者不匹配,修改文件及目录的所有者:
chown <rails进程用户>:<rails进程组> /application/reports/completed-task_report-111.pdf # 示例:chown deploy:deploy /application/reports/completed-task_report-111.pdf chown -R <rails进程用户>:<rails进程组> /application/reports/
2. 排查SELinux限制(仅CentOS/RHEL系系统)
- 查看SELinux状态:执行
getenforce,若输出为Enforcing,则SELinux可能阻止了文件访问 - 临时关闭测试:执行
setenforce 0,重新尝试访问文件。若问题解决,添加永久规则:chcon -R -t httpd_sys_rw_content_t /application/reports/
3. 检查文件系统挂载属性
- 查看
/application挂载状态:执行mount | grep /application - 若挂载选项含
ro(只读),重新挂载为读写:mount -o remount,rw /application - 确认无
noexec等影响读取的挂载选项
4. 移除文件特殊权限位
- 查看文件特殊属性:执行
lsattr /application/reports/completed-task_report-111.pdf - 若输出含
i(不可修改)或a(仅可追加),移除属性:chattr -i /application/reports/completed-task_report-111.pdf # 含a属性则执行 chattr -a <文件路径>
5. 确保父目录的遍历权限
文件所在父目录(/application、/application/reports)需要执行权限(允许用户进入目录):
- 检查父目录权限:执行
ls -ld /application /application/reports - 若权限不足,添加执行权限:
chmod o+x /application chmod o+x /application/reports
内容的提问来源于stack exchange,提问作者Sig
相关产品推荐
相关产品推荐

