如何恢复在进程一直占用某个文件的时被删除的文件,并保持正常写入?

2021-05-06 16:01:41 +08:00
 zhoudaiyu
场景假设:
进程 pid:1000
文件路径:/foo/bar.txt
被 1000 进程占用的文件描述符:6

当 1000 进程还占用着 /foo/bar.txt 的时候,执行 rm /foo/bar.txt -f,文件被“假删除了”(其实还在写数据),通过 losf |grep deleted|grep 1000|grep "/foo/bar.txt"可以看到被删除的文件(显示 deleted ),这时可以通过找到该进程的文件描述符文件夹里写入的文件名找到描述符,比如定位到了是 6 号文件描述符是被删除的文件的文件描述符,然后可以通过这条命令看到其实进程还在向该文件写数据:tail -F /proc/1000/fd/6 。

然后看了一些教程,直接把 fd 拷贝回被删除的文件,cp /proc/1000/fd/6 /foo/bar.txt ,但是这样的话被删除文件在被创建那一刻后就不再新写入数据了,换句话说复原的文件的数据只保留了我执行 cp /proc/1000/fd/6 /foo/bar.txt 那一刻前的 /proc/1000/fd/6 的数据,而不会写入新数据,但是查看 fd 写入情况 tail -F /proc/1000/fd/6 是正常有新数据写入的。

我的问题就是怎么能在恢复被删除的文件的同时保证新数据正常写入?也就操作后不丢数据。
1520 次点击
所在节点    Linux
11 条回复
AoEiuV020
2021-05-06 16:34:29 +08:00
感觉上没有办法,删除了就是删除了,从 fd 复制出来的也是新文件了,原进程读取的还是原文件,这了是原进程 fd 能复制出已删除文件原原因,
至于 tail 能看到新文件,那只是因为 fd 里是软链接,新的 tail 进程解析软链接得到了新文件,
原进程要读新文件应该只能关闭 fd 重新读了,
zhoudaiyu
2021-05-06 16:46:55 +08:00
@AoEiuV020 #1 谢谢您,我还有个疑问,就是源文件被删除了之后,fd 里面看到的软链文件内容是写到哪里了?
sujin190
2021-05-06 17:09:27 +08:00
这个应该是打开没有完全关闭的文件并不会真的从磁盘删除,只是文件系统不能检索了,也就是删除了名称,实在不行你可以用 tail 啥的再次打开这个文件描述符占着,然后关闭你写文件这个进程,然后用 tail 打开的文件描述符复制文件到新文件,然后再启动刚才那个进程就行吧
AoEiuV020
2021-05-06 17:12:17 +08:00
@zhoudaiyu 原地址吧,毕竟文件删除只是删除文件头,不影响文件本身的数据,原进程拿着原 fd 继续操作的话,动的也还是原来数据所在位置,
这很容易验证,给 bar.txt 创建一个硬链接,然后删除 bar.txt ,fd 目录里的软链接解析出来的也是 deleted,但原进程继续写入内容的话,就能看到这个硬链接内容变化了,
zhoudaiyu
2021-05-06 18:06:31 +08:00
@sujin190 #3 感觉可以这样 先 tail 文件描述符重定向到 file1,然后把 fd 拷贝到 file2,重启业务,然后再合并一下 file1 与 file2 (可能需要人工,且假定文件只追加新的内容不修改之前写入的)
billlee
2021-05-06 22:01:21 +08:00
ln -L /proc/1000/fd/6 /foo/bar.txt
zhoudaiyu
2021-05-07 07:27:14 +08:00
@billlee 这个逻辑连接没有太看懂啥意思呀😿
iwishing
2021-05-07 11:12:56 +08:00
zhoudaiyu
2021-05-07 11:56:25 +08:00
@iwishing #8 这个看过了 我也是有多么操作的 但是新数据不会写入
billlee
2021-05-07 20:53:39 +08:00
@zhoudaiyu

1. /proc/1000/fd/6 是指向原文件的(伪)符号连接
2. -L 是符号连接解引用,获得原文件
3. ln 在 /foo/bar.txt 处创建原文件的硬连接

UNIX 任何 dentry 都是指向某个 inode 的硬连接
buf1024
2021-05-08 09:45:24 +08:00
换个思路,从源头上禁止删除,至少有两种做法:
1. 创建特定的用户,用特定的用户启动程序,读写文件
2. 用 chattr 更改文件属性,使其不能被删除。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/775191

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX