V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
zhoudaiyu
V2EX  ›  Linux

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

  •  1
     
  •   zhoudaiyu · 2021-05-06 16:01:41 +08:00 · 1426 次点击
    这是一个创建于 1079 天前的主题,其中的信息可能已经有所发展或是发生改变。
    场景假设:
    进程 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 是正常有新数据写入的。

    我的问题就是怎么能在恢复被删除的文件的同时保证新数据正常写入?也就操作后不丢数据。
    11 条回复    2021-05-08 09:45:24 +08:00
    AoEiuV020
        1
    AoEiuV020  
       2021-05-06 16:34:29 +08:00
    感觉上没有办法,删除了就是删除了,从 fd 复制出来的也是新文件了,原进程读取的还是原文件,这了是原进程 fd 能复制出已删除文件原原因,
    至于 tail 能看到新文件,那只是因为 fd 里是软链接,新的 tail 进程解析软链接得到了新文件,
    原进程要读新文件应该只能关闭 fd 重新读了,
    zhoudaiyu
        2
    zhoudaiyu  
    OP
       2021-05-06 16:46:55 +08:00
    @AoEiuV020 #1 谢谢您,我还有个疑问,就是源文件被删除了之后,fd 里面看到的软链文件内容是写到哪里了?
    sujin190
        3
    sujin190  
       2021-05-06 17:09:27 +08:00
    这个应该是打开没有完全关闭的文件并不会真的从磁盘删除,只是文件系统不能检索了,也就是删除了名称,实在不行你可以用 tail 啥的再次打开这个文件描述符占着,然后关闭你写文件这个进程,然后用 tail 打开的文件描述符复制文件到新文件,然后再启动刚才那个进程就行吧
    AoEiuV020
        4
    AoEiuV020  
       2021-05-06 17:12:17 +08:00   ❤️ 1
    @zhoudaiyu 原地址吧,毕竟文件删除只是删除文件头,不影响文件本身的数据,原进程拿着原 fd 继续操作的话,动的也还是原来数据所在位置,
    这很容易验证,给 bar.txt 创建一个硬链接,然后删除 bar.txt ,fd 目录里的软链接解析出来的也是 deleted,但原进程继续写入内容的话,就能看到这个硬链接内容变化了,
    zhoudaiyu
        5
    zhoudaiyu  
    OP
       2021-05-06 18:06:31 +08:00 via iPhone
    @sujin190 #3 感觉可以这样 先 tail 文件描述符重定向到 file1,然后把 fd 拷贝到 file2,重启业务,然后再合并一下 file1 与 file2 (可能需要人工,且假定文件只追加新的内容不修改之前写入的)
    billlee
        6
    billlee  
       2021-05-06 22:01:21 +08:00
    ln -L /proc/1000/fd/6 /foo/bar.txt
    zhoudaiyu
        7
    zhoudaiyu  
    OP
       2021-05-07 07:27:14 +08:00 via iPhone
    @billlee 这个逻辑连接没有太看懂啥意思呀😿
    iwishing
        8
    iwishing  
       2021-05-07 11:12:56 +08:00
    zhoudaiyu
        9
    zhoudaiyu  
    OP
       2021-05-07 11:56:25 +08:00 via iPhone
    @iwishing #8 这个看过了 我也是有多么操作的 但是新数据不会写入
    billlee
        10
    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
        11
    buf1024  
       2021-05-08 09:45:24 +08:00
    换个思路,从源头上禁止删除,至少有两种做法:
    1. 创建特定的用户,用特定的用户启动程序,读写文件
    2. 用 chattr 更改文件属性,使其不能被删除。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1062 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:45 · PVG 02:45 · LAX 11:45 · JFK 14:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.