可以通过其inode检索文件吗?


27

我以指定的顺序运行了以下命令:

$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b

从该测试中得出的结论是,该命令rm实际上仅删除了文件名(a在此测试中)而不是文件,因为inode仍然存在并且可以通过另一个文件名(b)检索。

我的问题是,如果一个文件仅硬链接到一个文件名,则在rm执行该文件时,真实文件(即inode)是否已完全删除?如果不是,是否可以不通过文件名而是仅通过索引节点来检索文件索引节点?


听起来对我来说操作系统特定。
伊格纳西奥·巴斯克斯

@Ignacio Vazquez-Abrams。您是说它取决于版本?
user43312 2013年

不,我的意思是这取决于操作系统。每种都有不同的(如果有的话)进入VFS的方式。
伊格纳西奥·巴斯克斯

@Ignacio Vazquez-Abrams您对RHL或RHEL有任何想法吗?
user43312 2013年

1
@BruceEdiger Os X可以做到这一点。您可以使用“文件引用URL”访问文件系统对象,该URL基本上是根据文件系统号和节点号构建的。但是,官方不支持自己构建这些文件。取而代之的是,您获取文件的“文件引用URL”,然后使用它而不是路径名来进行同一运行时会话中的后续访问,这样您的应用程序就可以忽略文件在同一卷上的其他位置。
Analog

Answers:


29

如果您尝试通过文件的inode打开文件,这将绕过所有目录遍历。必须遍历目录才能确定文件和指向该目录的目录的权限。如果没有目录遍历,内核将无法确定是否允许调用进程访问文件。

Linux内核中有一个建议的补丁程序,允许从文件描述符创建指向文件的链接。它被拒绝了,因为要安全地执行此操作将非常困难

在Linux下(出于相同的原因,可能在其他unix变体上),您无法创建指向已删除文件的链接,因此,如果文件不再具有名称,则无法重新添加该文件。¹您可以打开已删除文件通过打开下的魔术链接打开文件/proc/$pid/fd/

如果文件不再具有任何链接并且不再打开,则该文件将不再存在,并且可以随时回收其数据以前使用的空间。

¹ 您可以通过以与文件系统相关的方式直接在文件系统中纠缠字节来做到这一点,例如debugfsext2 / ext3 / ext4。这需要访问安装了文件系统的设备(即,通常只有root才能尝试)。但是,尽管debugfs可以通过inode访问文件,但是如果删除该文件则无济于事:如果应用程序关闭该文件,则该文件将被真正删除,并且在已安装的文件系统上以读写模式运行debugfs可以解决此问题。灾害。


11

在Linux上,debugfs交互式ext2 / ext3 / ext4文件系统调试器提供了一个ln命令,该命令可以将inode编号作为filespec并创建到相应文件的新硬链接。不过实际上,这要求未链接的文件由进程保持打开状态,并在中保持打开文件描述符/proc/[pid]/fd/[n]。尝试在已删除的文件上执行此操作很可能导致文件系统损坏。

这是因为为了确保ext3(以及ext4中的扩展名)在崩溃后可以安全地恢复取消链接,实际上是将inode中的块指针清零,而ext2只是将这些块在块位图中标记为未使用,并标记为索引节点为“已删除”,并将块指针保留下来。即使这样,由于需要以读写方式挂载文件系统以创建硬链接,为删除的文件保留的块可能已经被重新分配。

在内核版本2.6.39之前,过去,如果未链接文件和新的硬链接都位于tmpfs文件系统中,可以使用GNU coreutils v8.0中引入的选项通过打开的文件描述符恢复未链接的文件。正如Gilles指出的那样,此功能已被禁用,这是因为直接从文件描述符创建硬链接所涉及的安全性考虑。ln -L|--logical/proc/[pid]/fd/[n]


我只是尝试使用ln -L从/ proc恢复已删除的文件,并收到错误:“没有这样的文件或目录”,所以我认为它实际上不支持此功能。我有coreutils 8.21。
wingedsubmariner 2013年

1
ln -L不按照你说的去做。它ln表明如果源是符号链接,则应硬链接目标。其中的符号链接/proc/$pid/fd是特殊的,并且硬链接(deleted)链接无效。
吉尔(Gilles)'所以

debugfs如果文件已被删除,这也无济于事-除非您要冒风险在已装载的文件系统上以读写模式运行它,这可能会完全破坏整个文件系统。
吉尔(Gilles)'所以

更新了有关的答案ln -L/proc/[pid]/fd/[n]在某些特殊情况下,以前可以通过使用它来创建硬链接,但是此问题已得到解决。
Thomas Nyman 2013年

1
debugfsln级别很低,只会创建一个名称,不会更新计数,也不会将这些块取消标记为未使用,因此非常危险。身高debugfsundel其中DES一切。警告:debugfs不是要运行一个安装的文件系统,除非你想利用在燃烧你的FS为灰烬的机会。
Lloeki '17

9

自1970年代初以来,在每个UNIX文件系统中,'ln'和'rm'命令的工作方式都完全相同。Mac OSX,BSD和Linux都继承了此原始设计。

UNIX文件本身没有名称,只有一个索引节点号或inum。但是,您只能通过特殊的“目录”文件中的条目来访问它,该文件将名称与所讨论的inum关联;您不能直接指定inum。

目录是本身一个文件,所以你也必须访问通过(另一个)目录等,通过一系列被称为“路径名称”由正斜杠分隔目录名(/)的。路径从进程的“当前工作目录”开始,除非名称以“ /”开头,在这种情况下,路径以文件系统根目录开头。例如,如果路径名不包含“ /”字符,那么它应该是当前目录中的一个条目。

非目录文件可以具有任意数量的路径名,称为“硬链接”,并且它将继续存在,直到其所有路径名都被删除并且最后一个进程已关闭该文件为止。然后,实际上删除该文件,并将其空间标记为可重复使用。也就是说,您可以creat()或open()一个单链接的文件,然后取消链接(),使其不再出现在文件系统名称空间中,但是该文件将继续存在,直到您将其关闭。这对于任何其他程序都不会读取的临时暂存文件很有用。

尽管目录具有索引节点号,但是大多数文件系统都不允许对其进行硬链接。它们只能出现在另一个目录中。(Mac OSX HFS +文件系统是一个不寻常的例外;这使Time Machine备份可以工作。)您仍然可以创建指向目录(或任何其他文件)的“软链接”。软链接类似于目录条目,只不过它包含另一个路径名而不是inum。

每个UNIX文件都有一个所有者,组和访问权限。他们让您打开文件是必要的但还不够;您还必须至少对用于引用它的路径名中的每个目录具有执行权限。这就是为什么没有标准的方法可以通过其inode号打开UNIX文件。这将绕过重要的,广泛使用的安全机制。

但是,这并不能解释为什么root(特权)用户无法通过inode编号打开文件的标准方法,因为总会绕过权限检查。这对于某些系统管理功能(例如备份)非常有用。据我所知,确实存在这样的机制,但是它们都是特定于文件系统的。没有针对任何UNIX文件系统执行此操作的通用方法。


1
前进音/是无声的,因此被称为“斜线”。
ctrl-alt-delor 2016年

4

这个问题可以从理论上解决(可以通过解决debugfs),也可以从实用上解决(紧急情况)。在后一种情况下,我认为这样做可能是为了节省时间并恢复文件的内容,这可能是紧急的(这是我着手解决此问题的方式,因此我认为它仍然相关且有用)。

由于没有内核API,因此debugfs不应在实时文件系统上运行,因为它会直接操纵FS结构。因此,要实时运行它,您必须拥有另一个文件名。假设文件仍通过某个进程(任何进程)打开,则可以在以下位置访问更方便的文件描述符/proc

$ lsof -F pf "$PWD/a" | sed 's/^p//' # find pid and file descriptor number of any process having the file open
$ pid=1234
$ ls -l /proc/$pid/fd/* | grep "$PWD/a" # find file descriptor number
$ fd=42
$ cat /proc/$pid/fd/$fd > "$PWD/a.restored" # read contents to a new filename

提示:

  • 如果您有合适的FD一个疑问,您可以运行诸如命令file就可以了
  • 如果有正在写入文件的进程,请确保尽快停止该进程,否则您将无法获取最新数据。(未试用的)技巧可能是使用其他一些进程打开仅通过fd读取的文件(try tail -f < /proc/$pid/fd/$fd > /dev/null,退出写入过程,以使其干净退出,然后使用新进程的fd。

2
那应该tail -f < /proc/...在第二个技巧中。
Murray Jensen

或者,如果写入过程只是追加(而不是查找和重写),则使用 tail -c +0 -f复制而不是复制来代替cat。在退出之前tail,请退出其他进程,然后等待tail直到文件末尾。
Peter Cordes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.