“Device busy”错误源于文件被进程占用或挂载点限制;需用lsof查占用进程、mount查挂载选项,避免PHP长期持文件句柄,优先将目录移至支持权限的本地ext4分区。
PHP 中调用 chmod() 或通过 shell_exec("chmod ...") 修改文件权限却报 “Device busy”,这通常不是 PHP 本身的问题,而是底层文件系统拒绝操作——最常见原因是该文件正被某个进程(尤其是 Web 服务器或 PHP-FPM 工作进程)以独占方式打开、锁定,或文件位于只读挂载点、NFS/CIFS 等网络文件系统上。
先确认是不是有进程正在读写该文件。在终端执行:
lsof +D /path/to/your/file
或更精准地查具体路径:
lsof /var/www/html/config.php
如果输出中看到 php-fpm、apache2、nginx 或 vim 等进程占着该文件,说明它正被持有句柄——此时 chmod 会被内核拒绝并返回 EBUSY(对应 “Device busy” 错误)。
systemctl restart php-fpm),但生产环境慎用fopen(..., "a+") 或 flock() 后未释放运行 mount | grep $(df . | tail -1 | awk '{print }') 查看当前文件系统挂载参数。若输出含 noexec、nosuid、ro(只读)或 noacl,则 chmod 必然失败。
nosuid,nodev,noexec,且服务端若配了 root_squash,非 root 用户无法改权限
ntfs-3g 挂载)本身不支持 Unix 权限,chmod 会静默忽略或报错:ro 或 host 路径本身是只读挂载,也会触发此错误如果确认文件只是被读取(非写入锁定),且你有 root 权限,可尝试从外部强制更新权限,避开 PHP 进程上下文:
sudo chown www-data:www-data /var/www/html/cache/ && sudo chmod 755 /var/www/html/cache/
但要注意:
chmod() —— 因为它运行在 www-data 用户下,无权修改自身正访问的目录元数据shell_exec() 执行带 sudo 的命令需提前配置免密(visudo 加 www-data ALL=(ALL) NOPASSWD: /bin/chmod),存在安全风险,不推荐线上使用defaults,并让 PHP 进程只在必要时打开文件、立即关闭真正卡住的地方往往不在 chmod 语法,而在文件生命周期管理和存储介质特性。别急着加 try-catch,先看 lsof 和 mount。