Nov 20

奇技淫巧(?) 之 解决被删掉又占用磁盘空间的文件 不指定

felix021 @ 2013-11-20 18:00 [IT » 操作系统] 评论(0) , 引用(0) , 阅读(5813) | Via 本站原创 | |
UPDATE@2014-01-09:注意,在gdb attach成功以后,这个进程会被暂停,可能会导致一些问题。

UPDATE@2017-11-11:用 lsof | grep deleted ,可以看到被删除的问题文件,记住占用该文件的PID, 到 /proc//fd (该进程打开的所有文件,按fd的值命名)下面可以看到这个文件的另一个链接,把这个链接的内容清空,也可以解决。

场景:Linux下,进程 p 打开了文件 f 并在后台持续地往 f 中写入日志。某日发现磁盘空间不够,把 f 删掉了,这时 ls 已经看不到 f 的存在,但是 df 发现磁盘空间占用并未减小,而 lsof 仍然可以看到该文件被占用(并显示一个 "(deleted)" 后缀)。更不幸的是,进程 p 是需要长期驻留在后台运行的,不能直接干掉它。

解决:简单地说就是替进程解决这个文件。

1) 根据链接文件名,可以查到该文件在进程中的 fd :

    $ ls -l /proc/[PID]/fd

2) 通过 gdb 连上该进程(一般需要root权限)

    $ sudo gdb
    (gdb) attach [PID]

3) 清除该文件所占空间

    (gdb) call ftruncate(3, 0)    #这里假定fd = 3
    $1 = 0

这种方式治标,但不治本 —— 随着进程的继续运行,被删掉的 f 仍然会占用越来越多的空间;但是又不能残暴地直接 close(3) ,否则 p 的后续写入操作会出错,可能导致进程报错结束。

但是还是有办法的:

4) 移花接木

    (gdb) call dup(3)
    $2 = 4
    (gdb) call open("/dev/null", 2)    #注:2 = O_RDWR,x86/x86_64/arm上都是这个值。
    $3 = 5
    (gdb) call dup2(5, 3)
    $4 = 3
    (gdb) call close(4)
    $5 = 0

注:未测试该招式是否可能因多线程竞争导致错误。

OVER.

转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: http://www.felix021.com/blog/feed.php
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]