重新链接已删除的文件


33

有时人们会删除不该删除的文件,但长时间运行的过程仍然会打开该文件,而通过分类来恢复数据/proc/<pid>/fd/N还不够好。如果您可以通过对ln运行一些魔术选项来“撤消”删除操作,那么就足够了不起了,这将使您重新链接到inode编号(通过lsof恢复)。

我找不到任何Linux工具可以做到这一点,至少可以通过粗略的Googling来实现。

您得到了什么,serverfault?

EDIT1:删除文件的原因不够出色,/proc/<pid>/fd/N是因为仍然打开文件的进程仍在写入文件。删除将从文件系统名称空间中删除对索引节点的引用。我想要的是一种重新创建参考的方法。

编辑2:'debugfs ln'可以工作,但是风险太大,因为它会破坏原始文件系统数据。恢复的文件也疯狂不一致。链接计数为零,我无法向其添加链接。这样我会更糟,因为我可以使用它/proc/<pid>/fd/N来访问数据而不会破坏我的fs。

Answers:


14

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

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

ln -L /proc/<pid>/fd/<handle> /path/to/deleted/file

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


7
这行不通;如果文件被删除,它将失败。
Random832

1
不,不会。我经常使用它来恢复已删除但仍打开的文件。但是,您需要确保新文件与该文件在删除前的文件系统/path/to/deleted/file位于同一文件系统上,否则确实会失败。(您可以使用来获取旧的路径ls -l /proc/<pid>/fd/<handle>
tnimeu 2011年

2
此类功能(请参阅此问题和答案)被拒绝作为安全风险[针对一种围绕特权进程的假想安全方案,该方案为您的进程提供了您拥有的文件的只读文件句柄,但无权访问]; 我尝试了一下(尽管使用小型C程序直接使用了相关的系统调用),但是它没有用。
2011年

7
我当然在发布解决方案之前进行了测试,当时它实际上对我有用。我不知道的是它仅适用于tmpfs文件系统,而不适用于eg ext3。此外,此功能已在2.6.39中完全禁用,请参阅commit。因此,此解决方案不再适用于内核2.6.39或更高版本,在早期版本中,它取决于文件系统。
tnimeu 2012年

7
@tnimeu ln -L对我不起作用。我有一个已删除的文件,我试图将其重新链接到原始路径。ln给我一个ln: failed to create hard link /my/path/file.pdf => /proc/19674/fd/16: No such file or directory。但我可以成功完成cat /proc/19674/fd/16
举报

13

听起来您已经了解很多,所以我不会赘述。有几种方法可以找到索引节点,通常可以使用cat并重定向STDOUT。您可以使用debugfs。在以下位置运行此命令:

ln <$INODE> FILENAME

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

如果该文件与ext3中的未打开文件取消链接,则数据将丢失。我不确定这是多么的真实,但是我的大部分数据恢复经验是在ext2上进行的。从ext3常见问题解答:

问:如何从ext3分区中恢复(删除)已删除的文件?实际上,您不能!这就是开发人员之一Andreas Dilger所说的:

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

您唯一的希望是“ grep”文件中已删除的部分,并希望是最好的。

此问题中还有相关信息:

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


希望删除该评论,因为它不真实。
mdpc

1
对于已删除但仍处于打开状态的文件,我认为它不会使索引节点中的指针归零。另外,我不会在debugfs中使用“ ln”,而是使用“ undel”,以便正确更新inode引用计数。
马克·瓦格纳

我不是故意这样暗示的,embobo。否,我测试了性能。我已经澄清了我的语言。
华纳

聪明,但是破坏了我的文件系统。:)
mbac32768 2010年

这是您描述的方案的唯一解决方案。在几乎所有情况下,对以rw挂载并主动写入的低级别文件系统进行操作都可能导致损坏。
华纳

8

如您所见,debugfs方式并没有真正起作用,并且最好在重启后自动删除文件(由于日志),并且在最坏的情况下您可能会浪费文件系统,从而导致“重启死机”。正确的解决方案(TM)是在VFS级别执行取消删除操作(这还具有与几乎所有当前Linux文件系统一起使用的额外好处)。每次在LKML中出现时,系统调用方式(flink)都会被击落,因此最好的方法是通过模块+ ioctl。

一个实现此方法并且代码相当简洁的项目是fdlink(对于使用ubuntu maverick内核测试的版本,https://github.com/pkt/fdlink.git )。有了它,在插入模块(sudo insmod flink_dev.ko)之后,您只需执行“ ./flinkapp / proc // fd / X / my / link / path”,它将完全按照您的要求进行。

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


3

我不知道该怎么做,但我要做的是:

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

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


debugfs link命令根本不支持该用例。
mbac32768 2010年

tldp.org/HOWTO/Ext2fs-Undeletion-11.html建议这样做。我没有尝试过,但这似乎很合理。
比尔·韦斯

link在我的测试中不起作用,但是可以ln
华纳2010年

3

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

% tail -n +0 -f /proc/<pid>/fd/<fd> /path/to/deleted_file

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


2
如接受的答案中所示,链接到原始文件应该可以。
克里斯S

1
这个问题没有公认的答案,您指的是哪个?
哈曼·塞缪尔

是否不需要将(>)重定向到已删除的文件?
ncasas

1

有趣的问题。面试官在面试中向我问了同样的问题。我告诉他的是,没有一个简单的方法可以完成此操作,并且通常不值得花费时间和精力。我确实问过他,他认为解决此问题的方法是...。

  1. 使用lsof在磁盘上查找该进程的索引节点号,因为即使文件已被删除,该索引号仍会出现...关键是它仍然处于打开状态。
  2. 通过文件系统调试器基于此从文件系统中提取信息。

我可以从/ proc / <pid> / fd / N中提取数据,但这不是我想要的。
mbac32768 2010年

1

使用Sleuthkit icat。

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file

通过绕过操作系统的文件系统功能并直接解析磁盘字节来工作。
Flimm

0

对我有用的快速解决方案,没有令人生畏的工具:

1)直接在/ proc中查找process + fd:

ls -al /proc/*/fd/* 2>/dev/null | grep {filename}

2)然后使用类似于@nickray的技术,并pv抛出:

tail -c +0 -f /proc/{procnum}/fd/{fdnum} | pv -s {expectedsize} > {recovery_filename}

完成后,您可能需要按Ctrl-C(ls /proc/{procnum}/fd/{fdnum}会告诉您该文件不再存在)),但是如果您知道确切的字节大小,则可以使用pv -S它在达到计数时退出。

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.