本质是底层文件系统异常,需先查磁盘空间(df -h)、挂载状态(mount | grep ro)、inode耗尽(df -i)、SELinux/AppArmor拦截、open_basedir限制及父目录x权限缺失,再针对性修复。

PHP 中 mkdir() 失败报 “Read-only file system” 或磁盘满,本质不是 PHP 代码问题,而是底层文件系统状态异常。直接改权限或重试 mkdir 没用,得先定位真实原因再处理。
先确认是不是真磁盘满了
很多人看到 mkdir 失败就急着调权限,但实际可能是磁盘空间耗尽触发了只读保护:
- 运行
df -h,重点看 PHP 写入路径所在分区(比如/var/www或/www),别只看/根目录 - 如果使用的是 Docker、宝塔或 NAS 挂载点,还要单独查对应挂载路径:
df -h /nas或df -h /www - 若显示
Use% 100%,但du -sh统计目录大小远小于此,大概率是“幽灵文件”——被删除但进程仍在写入,用lsof +L1查找并重启相关服务(如 php-fpm、mysqld)
检查挂载状态是否为只读(ro)
Linux 在检测到文件系统错误、异常断电或人为配置后,会自动以 ro(只读)方式重新挂载分区,这是保护机制:
- 执行
mount | grep "$(df . | tail -1 | awk '{print $1}')",看输出中是否有ro字样 - 如果是根分区只读,临时恢复可用:
sudo mount -o remount,rw / - 如果是其他挂载点(如
/nas、/boot),先sudo umount /nas,再用sudo mount -o defaults,dmask=000,fmask=111 /dev/sdb1 /nas重新挂载(注意替换设备名) - 若提示
device is busy,用fuser -m /nas查占用进程,必要时fuser -mk /nas强制终止
排查权限与挂载参数干扰
即使显示 drwxrwxr-x,PHP(如 www-data 用户)仍可能因挂载层限制无法写入:
- NTFS/FAT/exFAT 或某些 NAS 共享挂载默认带
umask=022,导致非 root 用户实际无写权;必须显式加umask=000或dmask=000,fmask=111 - 父目录缺少执行权限(x)也会失败:PHP 要进入
/var/www/html/app/cache,则/var、/var/www、/var/www/html每一级都得有 x 权限,用namei -l /var/www/html/app/cache逐级检查 - SELinux(CentOS/RHEL)或 AppArmor(Ubuntu)可能拦截,临时验证可运行
setenforce 0,恢复即说明是策略问题,需加对应规则 - open_basedir 限制 PHP 只能访问指定路径,检查
phpinfo()中该项值是否包含目标目录
别忽略 inode 耗尽和配额限制
磁盘空间还有几十 GB,但新建目录仍失败?很可能是 inode(文件索引节点)用完了:
- 执行
df -i,看IUse%是否超过 95%;常见于大量 session 文件、日志碎片 - 查 PHP session 目录:
php -i | grep session.save_path,然后find /www/sess -name "sess_*" -type f | wc -l看数量 - 安全清理:
find /www/sess -name "sess_*" -type f -print0 | xargs -0 rm -f,再systemctl restart php-fpm - 若报错含
Disk quota exceeded,运行quota -u www,末尾带 * 就是配额超限,用setquota -u www 0 0 0 0 /dev/vda1临时解除
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











