重新链接已删除的文件

mba*_*768 38 linux inode

有时人们删除他们不应该删除的文件,长时间运行的进程仍然打开文件,通过 catting 恢复数据/proc/<pid>/fd/N还不够棒。如果您可以通过对 ln 运行一些魔术选项来“撤消”删除,这将让您重新链接到 inode 编号(通过 lsof 恢复),那就太棒了。

我找不到任何 Linux 工具来做到这一点,至少用粗略的谷歌搜索。

你有什么,服务器故障?

EDIT1:从文件中捕获文件的原因/proc/<pid>/fd/N还不够棒,因为仍然打开文件的进程仍在写入文件。删除会从文件系统命名空间中删除对 inode 的引用。我想要的是一种重新创建参考的方法。

EDIT2: 'debugfs ln' 有效,但风险太高,因为它会破坏原始文件系统数据。恢复的文件也疯狂不一致。链接数为零,我无法向其添加链接。我的情况更糟,因为我可以/proc/<pid>/fd/N用来访问数据而不会破坏我的 fs。

tni*_*meu 18

如果您可以通过对 ln 运行一些魔术选项来“撤消”删除,这将让您重新链接到 inode 编号(通过 lsof 恢复),那就太棒了。

lnv8.0 (GNU/coreutils)中引入了这种令人敬畏的功能,并带有-L|--logical导致ln首先取消引用的选项/proc/<pid>/fd/<handle>。所以一个简单的

ln -L /proc/<pid>/fd/<handle> /path/to/deleted/file
Run Code Online (Sandbox Code Playgroud)

足以重新链接已删除的文件。

  • 这不起作用;如果文件被删除,它将失败。 (11认同)
  • 当然,我在发布我的解决方案之前确实对此进行了测试,当时它确实对我有用。我不知道的是它只适用于`tmpfs` 文件系统而不适用于例如`ext3`。此外,此 _feature_ 在 2.6.39 中完全禁用,请参阅 [提交](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=aae8a97d3ec30788790d1720b71d76fd8eb44b73) . 因此,此解决方案不再适用于内核 2.6.39 或更新版本,并且在早期版本中它取决于文件系统。 (9认同)
  • @tnimeu `ln -L` 对我不起作用。我有一个已删除的文件,我尝试将其重新链接到原始路径。`ln` 给我一个 `ln: 无法创建硬链接 /my/path/file.pdf =&gt; /proc/19674/fd/16: No such file or directory`。但我可以例如成功`cat /proc/19674/fd/16` (9认同)
  • 这种功能(见[这个问题](http://stackoverflow.com/questions/4171713/relinking-an-anonymous-unlinked-but-open-file)和答案)特别被_拒绝_作为[对一个假设的安全方案围绕特权进程,为您的进程提供一个只读文件句柄,指向您拥有但无权访问的文件];我试过了(虽然用一个小的 C 程序直接使用相关的系统调用),但没有奏效。 (4认同)
  • 不,不会。我经常使用它来恢复已删除但仍打开的文件。但是您需要确保新的 `/path/to/deleted/file` 与文件在删除之前的 ** 相同文件系统** 上,否则这将 - 实际上 - 失败。(您可以使用`ls -l /proc/&lt;pid&gt;/fd/&lt;handle&gt;` 获取旧路径) (2认同)
  • 不要理会`ln -L`,它已经**[disabled](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id= aae8a97d3ec30788790d1720b71d76fd8eb44b73)** 由于安全问题,自 2011 年以来在 Linux 内核中。 (2认同)

War*_*ner 14

听起来你已经了解了很多,所以我不会过多赘述。有多种方法可以找到 inode,您通常可以 cat 和重定向 STDOUT。您可以使用debugfs. 在以下范围内运行此命令:

ln <$INODE> FILENAME

确保您有文件系统的备份。之后您可能需要运行 fsck。我使用仍在写入的 inode 成功地测试了它,并且它确实可以创建一个指向取消引用的 inode 的新硬链接。

如果文件与 ext3 中未打开的文件取消链接,则数据将丢失。我不确定这是多么一致,但我的大部分数据恢复经验都是使用 ext2。来自 ext3 常见问题解答:

问:如何从 ext3 分区恢复(取消删除)已删除的文件?事实上,你不能!这是其中一位开发人员 Andreas Dilger 所说的:

为了确保 ext3 在崩溃后可以安全地恢复取消链接,它实际上将 inode 中的块指针归零,而 ext2 只是在块位图中将这些块标记为未使用,并将 inode 标记为“已删除”并离开块单独指点。

您唯一的希望是“grep”已删除的部分文件,并希望一切顺利。

这个问题也有相关信息:

我在 linux 服务器上用空白覆盖了一个大文件。我可以恢复现有文件吗?

  • 对于已删除但仍然打开的文件,我认为它不会将索引节点中的指针清零。另外,我不会在 debugfs 中使用“ln”,而是使用“undel”,以便 inode 引用计数能够正确更新。 (2认同)

小智 9

您所看到的 debugfs 方式并没有真正起作用,充其量您的文件将在重新启动后自动删除(由于日志),最坏的情况是您可以丢弃文件系统,从而导致“重新启动死亡循环”。正确的解决方案 (TM) 是在 VFS 级别执行取消删除(这还具有使用几乎所有当前 Linux 文件系统的额外好处)。系统调用方式(flink)每次出现在LKML中都被击落,所以最好的方式是通过一个模块+ioctl。

实现这种方法并具有相当小和干净的代码的项目是 fdlink(https://github.com/pkt/fdlink.git,用于使用 ubuntu Maverick内核测试的版本)。有了它,在插入模块 (sudo insmod flink_dev.ko) 后,您只需执行“./flinkapp /proc//fd/X /my/link/path”,它就会完全按照您的意愿执行操作。

您还可以使用 vfs-undelete.sourceforge.net 的前向移植版本,该版本也可以工作(并且还可以自动重新链接到原始名称),但是 fdlink 的代码更简单,而且效果也一样,所以这是我的偏好。


小智 8

今天遇到了同样的问题。我能想到的最好办法就是跑步

% tail -n +0 -f /proc/<pid>/fd/<fd> >/path/to/write/restored_file
Run Code Online (Sandbox Code Playgroud)

在 tmux/screen 会话中,直到进程结束。

  • 难道这不需要重定向(`&gt;`)到已删除的文件吗? (5认同)
  • 正如已接受的答案中那样,链接到原始文件应该可行。 (2认同)

Bil*_*iss 5

我不知道如何做你想要的,但我会做的是:

  • 从另一个进程打开文件RO
  • 等待原进程退出
  • 将数据从打开的 FD 复制到文件

显然,这并不理想,但有可能。另一种选择是使用 debugfs(使用命令link),但这在生产机器上有点可怕!