我有一个 PHP 脚本,使用函数 rename
移动文件,但部分失败。调用rename
会发出“权限被拒绝”警告。该文件似乎已复制到目标目录(我看到它没问题),但在重命名
后它仍然存在于源目录中。
file_exists
确认旧文件仍然存在。
然后,unlink
可以成功删除该文件 - 它返回 true
并且 file_exists
确认该文件现已消失。
该文件通过 HTTP 请求上传到 /tmp
目录(我使用 is_uploaded_file
来满足安全考虑 - 这不是这里的问题) 。该文件确实具有 Web 服务用户 (www-data
) 的 rw
权限。 move_uploaded_file
也可以正常工作,不会出现错误。
目标目录位于已安装的 CIFS 目录中。
Linux Ubuntu,PHP 版本 7.2.24。
最佳答案
(更新: OP 表示目标目录是 CIFS 挂载。CIFS 挂载的权限可能比较难以理解 - 请参阅 https://linux.die.net/man/8/mount.cifs 部分“文件和目录所有权和权限")
rename
不是单个原子操作(在 PHP 中)。它实际上调用(对于普通文件按此顺序):
复制
(创建文件的新副本)chown
(设置新副本的所有权)chmod
(设置新副本的权限)取消链接
(删除原来的)
(源代码为available on GitHub。)
如果这些步骤中的任何一个失败,它将中止并显示错误代码,并且不会回滚(这与您所看到的症状一致)。
旁注:这实际上在源代码中记录为可能的行为:
/* * Try to set user and permission info on the target. * If we're not root, then some of these may fail. * We try chown first, to set proper group info, relying * on the system environment to have proper umask to not allow * access to the file in the meantime. */
我预计目标(您将复制到)中的父目录的权限会阻止chmod
或chown
停止工作。
(注意:这不适用于 CIFS 安装...请参阅答案顶部的链接。)作为一个 super 丑陋的黑客,您可以尝试将目标目录的权限设置为777
(chmod 777/my/target/directory/
),这是不好的做法,但可以证明这一理论。
关于php - 为什么 `rename`删除源文件失败,而 `unlink`有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59859877/