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

ujj*_*ain 13 solaris unix disk-space-utilization solaris-10

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

我尝试使用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
Run Code Online (Sandbox Code Playgroud)

有时,文件被应用程序或用户删除,例如日志文件,并且该文件仍被无法重新启动的进程引用。

是否有很好的方法来回收已删除文件的磁盘空间,而无需重新启动引用此已删除文件的进程?

use*_*968 20

find /proc/*/fd -ls 2> /dev/null | grep '(deleted)'
Run Code Online (Sandbox Code Playgroud)

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

Grep 已删除。

标准错误到 /dev/null

输出:

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

或者你可以使用awk

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

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

/proc/28680/fd/113
Run Code Online (Sandbox Code Playgroud)

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

(如果您不知道自己在做什么,请不要这样做)

find /proc/*/fd -ls 2> /dev/null | awk '/deleted/ {print $11}' | xargs -p -n 1 truncate -s 0
Run Code Online (Sandbox Code Playgroud)

-p执行truncate前的提示

更好的方法是手动截断

手动截断:

: > /proc/28680/fd/113
Run Code Online (Sandbox Code Playgroud)

或者:

> /proc/28680/fd/113
Run Code Online (Sandbox Code Playgroud)

或者:

truncate -s 0 /proc/28680/fd/113
Run Code Online (Sandbox Code Playgroud)

享受 ;)


小智 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% /
Run Code Online (Sandbox Code Playgroud)

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

$ less /tmp/my10MBfile &

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

然后我删除该文件

$ 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% /
Run Code Online (Sandbox Code Playgroud)

它仍然存在,但已被删除。查看lsof输出的第4列:File Descriptor number 4 open for Reading (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
Run Code Online (Sandbox Code Playgroud)

就是这样!

$ df -m /tmp
/dev/disk/by-uuid/6835b2fd-971d-420c-ba18-3c729ec2e8a0     14637  9215       4672  67% /
Run Code Online (Sandbox Code Playgroud)

我们的 10 MB 欢迎回来:)

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

$ ps 29351
29351 pts/0    S+     0:00 less /tmp/my10MBfile
Run Code Online (Sandbox Code Playgroud)

该进程仍在运行。

  • 好的,但要多久?如果无法写入日志文件,许多进程就会直接退出。 (2认同)

kof*_*ann 0

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

# echo "" >! /proc/123/fd/3
Run Code Online (Sandbox Code Playgroud)