IOException:关闭文件流时权限被拒绝

IOException: Permission denied when closing file stream

在远程机器上,我观察到无法重现或解释的异常。

同样的过程 运行 多年来一直没有问题。正在从 SCP 下载多个类似文件到 RedHat Linux 上的共享网络位置,磁盘上肯定有空闲 space,所有权限都很好。只有几个文件描述符打开。今天,突然间,在写入最后一个文件时 java.io.IOException: Permission denied 关闭 流时出现,但文件已正确保存。

这种异常的可能原因是什么? 除了 Permission denied 到 [= 的映射之外,我在 Java 源代码中没有找到任何内容13=]。在浏览互联网时,我只发现人们在打开流时得到 Permission denied 但没有关闭它的情况。

java.io.IOException: Permission denied
  at java.io.FileOutputStream.close0(Native Method)
  at java.io.FileOutputStream.access[=10=]0(FileOutputStream.java:53)
  at java.io.FileOutputStream.close(FileOutputStream.java:356)
  at java.io.FileDescriptor.closeAll(FileDescriptor.java:212)
  at java.io.FileOutputStream.close(FileOutputStream.java:354)
  at java.io.FilterOutputStream.close(FilterOutputStream.java:159)
  at com.aestasit.ssh.dsl.ScpMethods.doGet(ScpMethods.groovy:249)
  at com.aestasit.ssh.dsl.ScpMethods.this$doGet(ScpMethods.groovy)
  at com.aestasit.ssh.dsl.ScpMethods.download(ScpMethods.groovy:162)
  at com.aestasit.ssh.dsl.SshDslEngine.executeSession(SshDslEngine.groovy:70)
  at com.aestasit.ssh.dsl.SshDslEngine$remoteSession.call(Unknown Source)
  at com.aestasit.ssh.DefaultSsh.remoteSession(DefaultSsh.groovy:46)
  at com.aestasit.ssh.DefaultSsh$remoteSession.callStatic(Unknown Source)

这只是一个理论....

查看 Linux 内核源代码,似乎在某些情况下 close(fd) 系统调用会在关闭前尝试进行内部刷新。如果 fd 与 "file system" 上的文件相关联,其中可以在文件打开时更改有效访问权限,那么可以想象关闭的刷新可能会失败,因为 当前 权限限制太多。那会变成 EACCES 系统调用失败。

这样的故障很少见,因为文件的权限仅在 "right" 时间发生变化而触发故障的情况很少见;即在 close 系统调用和之前的 write 系统调用之间。

此外,可以想象这只会发生在某些类型的文件上;例如远程文件服务器上的文件,由远程服务器实现访问控制。


请注意,Linux 手动输入或 POSIX 规范并未设想 close() 因 EACCES 而失败。文档暗示只有在打开文件时才会检查访问权限,这是(至少)是意外行为。

然而,不利的一面是(虚拟)文件系统行为的各个方面取决于文件系统本身的实现。在少数情况下,文件系统不正常 "normally".