NFS共享根目录is_writable返回false但子项可写的技术求助
排查NFS共享根目录
is_writable()返回false的问题 从你给出的一堆测试结果来看,这个问题确实有点反常——权限对、UID匹配,能改里面的文件和子目录,唯独共享根目录的is_writable()偏偏返回false。结合我之前处理NFS权限坑的经验,咱们可以从这几个方向一步步排查:
1. 先清PHP的文件状态缓存试试
PHP的is_writable()这类文件状态函数会自动缓存结果,避免频繁调用系统接口。如果之前这个目录曾经不可写,缓存可能没及时更新。你可以在调用is_writable()前手动清缓存:
clearstatcache(true, 'files/crm-upload/'); var_dump(is_writable('files/crm-upload/'));
2. 别光信PHP函数,直接验证目录能不能真的写
你已经能修改已有文件了,那试试创建新文件或者目录,直接用Apache的运行用户(UID33,也就是www-data)执行命令:
# 先切到www-data用户 sudo -u www-data bash # 试试创建新文件 touch files/crm-upload/new_test_file # 再试试创建新目录 mkdir files/crm-upload/new_test_dir
如果这俩操作都能成,说明目录实际是可写的,问题出在PHPis_writable()的判断逻辑(大概率是NFS的stat返回值和本地目录不一样导致的);如果创建失败,那就得去NFS服务器端找原因了。
3. 查NFS服务器的exports配置
虽然客户端挂的时候用了rw,但服务器端的/etc/exports可能藏着限制:
- 看看服务器端这个共享的配置,有没有
root_squash(默认是开的)?不过你的UID是33不是root,所以这个影响不大,但如果开了all_squash,会把所有客户端用户都映射成服务器的nobody,这时候你客户端看到的权限可能和服务器实际权限对不上。 - 确认服务器端这个目录的真实权限:在NFS服务器上跑
ls -ld /path/to/crm-upload,看看是不是真的是drwxrwxrwt(对应权限40777),同时所有者UID是不是也是33。
4. 检查NFS挂载的版本和选项
- 先看看客户端挂载的详情:
mount | grep crm-upload,确认用的是NFSv3还是v4。这俩版本的权限处理逻辑不一样,你可以试试换个版本挂载,比如指定用v3:sudo umount files/crm-upload sudo mount -t nfs -o rw,sec=sys,vers=3 [你的NFS服务器IP]:[服务器上的共享路径] files/crm-upload - 另外,要是服务器端开了ACL,客户端挂载没加
acl选项,也可能导致权限检查出问题。可以试试加acl选项重新挂载。
5. 排查目录的特殊文件属性
虽然你能改里面的文件,但还是确认下根目录有没有特殊属性:
lsattr files/crm-upload/
如果输出里有i(不可修改)或者a(只能追加),那会导致目录不可写,但这种情况一般也改不了里面的文件,所以可能性不高,但查一下总没坏处。
最后总结下
如果清完缓存is_writable()就正常了,那就是PHP缓存的锅;如果实际能创建文件但函数还是返回false,你可以绕开这个函数,直接尝试创建临时文件来判断(比如生成一个唯一文件名,创建成功就说明可写,然后删掉);如果创建文件都失败,那就重点盯NFS服务器的exports配置和目录真实权限。
内容的提问来源于stack exchange,提问作者Sentenza
相关产品推荐
相关产品推荐

