如何在不重新启动引用过程的情况下恢复已删除文件的可用空间?


12

在服务器上删除大文件时,进程可能仍会引用这些文件,因此文件系统没有更多的可用空间。

我尝试使用lsof,但似乎没有列出已删除的文件。fuser -c可以做得更好,但是进程列表太长而无法检查每个进程,特别是因为每个进程都是Oracle进程。

bash-3.2# fuser -c /var
/var:      105o   29999o   20444c    3528c   27258o    7715o    3864o    3862o    2494o   18205o   17450co   17445co   14912co   14824co   14818co   14816o   14814o    8532c    8530c    7633com    7118o    6958o    6790c    6784co    6734o    6693o    6689o    6684o    6675o    6635o    6594c    6548o    6547o    6546o    6545o    6544o    6543o    6542o    6541o    6540o    6537o    6535o    6456o    6128co    6113o     335o     245co     229o     161o       8o
bash-3.2# du -hs /proc
 139T   /proc

有时会发生文件被应用程序或用户删除的情况,例如日志文件,而该文件仍被无法重新启动的进程引用。

是否有商品方法可以回收已删除文件上的磁盘空间,而无需重新启动引用此已删除文件的进程?


供参考..删除打开的文件的更好方法是将/ dev / null复制到文件中cp /dev/null file
Mike

@Mike cp /dev/null是空命令,因为cp没有要复制的内容,简单的重定向严格等效:>file甚至是>file
jlliagre 2013年

Answers:


12
find /proc/*/fd -ls 2> /dev/null | grep '(deleted)'

查找所有打开的文件描述符。

Grep已删除。

StdError到/ dev / null

输出:

160448715    0 lrwx------   1 user      user            64 Nov 29 15:34 /proc/28680/fd/113 -> /tmp/vteT3FWPX\ (deleted)

或者你可以使用awk

查找/ proc / * / fd -ls 2> / dev / null | awk'/ deleted / {print $ 11}';

awk输出(在bash Ubuntu 12.04中测试):

/proc/28680/fd/113

查找并截断所有已删除的文件(在bash Ubuntu 12.04中测试):

(如果您不知道该怎么做,请不要这样做)

find /proc/*/fd -ls 2> /dev/null | awk '/deleted/ {print $11}' | xargs -p -n 1 truncate -s 0

-p在执行截断之前提示

更好的方法是手动截断

手动截断:

: > /proc/28680/fd/113

要么:

> /proc/28680/fd/113

要么:

truncate -s 0 /proc/28680/fd/113

请享用 ;)


+1,但我也需要sudo来运行这些命令
79E09796 '04

6

这是一个简单的示例less

假设我们有一个文件my10MBfile

$ dd if=/dev/zero of=/tmp/my10MBfile bs=1M count=10
10+0 enregistrements lus
10+0 enregistrements écrits
10485760 octets (10 MB) copiés, 0,0454491 s, 231 MB/s

$ ls -l /tmp/my10MBfile
-rw-r--r-- 1 max max 10485760 avril 23 22:49 /tmp/my10MBfile

$ df -m /tmp
/dev/disk/by-uuid/6835b2fd-971d-420c-ba18-3c729ec2e8a0     14637  9225       4662  67% /

现在我用打开该文件less(是的,它是一个二进制文件...没关系)

$ less /tmp/my10MBfile &

$ lsof -p $(pidof less) | grep 10MBfile
less    29351  max    4r   REG    8,3 10485760 521464 /tmp/my10MBfile

然后我删除该文件

$ rm /tmp/my10MBfile

$ lsof -p $(pidof less) | grep 10MBfile
less    29351  max    4r   REG    8,3 10485760 521464 /tmp/my10MBfile (deleted)

$ df -m /tmp
/dev/disk/by-uuid/6835b2fd-971d-420c-ba18-3c729ec2e8a0     14637  9225       4662  67% /

它仍然在那里,但是被删除了。查看lsof输出的第4列:4号文件描述符可供读取(4r)

让我们运行GDB!

$ gdb -p $(pidof less)

GNU gdb (GDB) 7.4.1-debian
....
Attaching to process 29351
....

(gdb) p close(4)
$1 = 0
(gdb) q

而已!

$ df -m /tmp
/dev/disk/by-uuid/6835b2fd-971d-420c-ba18-3c729ec2e8a0     14637  9215       4672  67% /

欢迎回来我们的10 MB :)

$ ls /proc/29351/fd
0  1  2  3

$ ps 29351
29351 pts/0    S+     0:00 less /tmp/my10MBfile

该过程仍在运行。


2
好的,但是要持续多久?如果许多进程无法写入日志文件,它们就会退出。
longneck

Logrotate不能为您这样做吗?
maxxvw

logrotate向进程发送信号以关闭日志文件并打开一个新文件。
longneck

2

此命令将显示在Solaris系统上仍打开的所有已删除文件:

find /proc/*/fd -type f -links 0

您可以使用以下命令截断您确定想要的那些:

:> /proc/p/fd/x

p是进程ID,x是第一个命令返回的文件描述符。

不用担心,如果某些程序报告ls的大小在一段时间后恢复为截断前的大小,则磁盘上使用的实际大小会小得多,因为文件现在是稀疏文件。


0

您可以尝试转到/proc/<pid>/fd目录并截断相应的文件描述符。假设fd = 3指向pid == 123的已删除文件:

# echo "" >! /proc/123/fd/3

您有这种方法可行的例子吗?找不到从那里更改FD的方法
maxxvw

是的,这可行,但是如何找到该进程的pid?
ujjain

-2

这些解决方案都不适合我。只有将Bleachbit用作根用户后,我才能正确释放与已删除文件关联的空间。

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.