猿问

当`unlink`起作用时,为什么`rename`无法删除源文件

我有一个 PHP 脚本使用 function 移动文件rename,但部分失败。调用rename会给出“权限被拒绝”警告。该文件似乎已经复制到目标目录(我在那里看到了它),但它仍然存在于.之后的源目录中rename

file_exists确认旧文件仍然存在。 unlink然后可以成功删除文件 - 它返回truefile_exists确认文件现在已经消失。

该文件来自在 HTTP 请求中上传到/tmp目录中(我使用is_uploaded_file它来满足安全考虑 - 这不是这里的问题)。该文件确实具有rwWeb 服务用户 ( www-data) 的权限。move_uploaded_file也可以正常工作。

目标目录位于已安装的 CIFS 目录中。

Linux Ubuntu,PHP 版本 7.2.24。


慕侠2389804
浏览 142回答 1
1回答

慕哥9229398

(更新: OP 说目标目录是 CIFS 挂载。CIFS 挂载的权限可能更难理解 - 请参阅https://linux.die.net/man/8/mount.cifs部分“文件和目录所有权和权限” )rename不是一个单一的原子动作(在 PHP 中)。它实际上调用(按正常文件的顺序):copy(创建文件的新副本)chown(设置新副本的所有权)chmod(设置新副本的权限)unlink(删除原文)(源代码可在 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.  */我希望目标中父目录的权限(您要复制到的位置)阻止chmodorchown工作。(注意:这不适用于 CIFS 挂载...请参阅答案顶部的链接。)作为一个超级丑陋的黑客,您可以尝试将目标目录的权限设置为777( chmod 777 /my/target/directory/),这是不好的做法,但会证明理论。
随时随地看视频慕课网APP
我要回答