如何恢复在进程一直占用某个文件的时被删除的文件,并保持正常写入? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
zhoudaiyu
V2EX    Linux

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

  •  1
     
  •   zhoudaiyu
    PRO
    2021 年 5 月 6 日 1957 次点击
    这是一个创建于 1815 天前的主题,其中的信息可能已经有所发展或是发生改变。
    场景假设:
    进程 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 年 5 月 6 日
    感觉上没有办法,删除了就是删除了,从 fd 复制出来的也是新文件了,原进程读取的还是原文件,这了是原进程 fd 能复制出已删除文件原原因,
    至于 tail 能看到新文件,那只是因为 fd 里是软链接,新的 tail 进程解析软链接得到了新文件,
    原进程要读新文件应该只能关闭 fd 重新读了,
    tr>
    zhoudaiyu
        2
    zhoudaiyu  
    OP
    PRO
       2021 年 5 月 6 日
    @AoEiuV020 #1 谢谢您,我还有个疑问,就是源文件被删除了之后,fd 里面看到的软链文件内容是写到哪里了?
    sujin190
        3
    sujin190  
       2021 年 5 月 6 日
    这个应该是打开没有完全关闭的文件并不会真的从磁盘删除,只是文件系统不能检索了,也就是删除了名称,实在不行你可以用 tail 啥的再次打开这个文件描述符占着,然后关闭你写文件这个进程,然后用 tail 打开的文件描述符复制文件到新文件,然后再启动刚才那个进程就行吧
    AoEiuV020
        4
    AoEiuV020  
       2021 年 5 月 6 日   1
    @zhoudaiyu 原地址吧,毕竟文件删除只是删除文件头,不影响文件本身的数据,原进程拿着原 fd 继续操作的话,动的也还是原来数据所在位置,
    这很容易验证,给 bar.txt 创建一个硬链接,然后删除 bar.txt ,fd 目录里的软链接解析出来的也是 deleted,但原进程继续写入内容的话,就能看到这个硬链接内容变化了,
    zhoudaiyu
        5
    zhoudaiyu  
    OP
    PRO
       2021 年 5 月 6 日 via iPhone
    @sujin190 #3 感觉可以这样 先 tail 文件描述符重定向到 file1,然后把 fd 拷贝到 file2,重启业务,然后再合并一下 file1 与 file2 (可能需要人工,且假定文件只追加新的内容不修改之前写入的)
    billlee
        6
    billlee  
       2021 年 5 月 6 日
    ln -L /proc/1000/fd/6 /foo/bar.txt
    zhoudaiyu
        7
    zhoudaiyu  
    OP
    PRO
       2021 年 5 月 7 日 via iPhone
    @billlee 这个逻辑连接没有太看懂啥意思呀
    zhoudaiyu
        9
    zhoudaiyu  
    OP
    PRO
       2021 年 5 月 7 日 via iPhone
    @iwishing #8 这个看过了 我也是有多么操作的 但是新数据不会写入
    billlee
        10
    billlee  
       2021 年 5 月 7 日
    @zhoudaiyu

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

    UNIX 任何 dentry 都是指向某个 inode 的硬连接
    buf1024
        11
    buf1024  
       2021 年 5 月 8 日
    换个思路,从源头上禁止删除,至少有两种做法:
    1. 创建特定的用户,用特定的用户启动程序,读写文件
    2. 用 chattr 更改文件属性,使其不能被删除。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1563 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 16:34 PVG 00:34 LAX 09:34 JFK 12:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86