如何找到最大的打开文件?

Hak*_*aba 14 size sort files

在所有进程打开的文件中寻找最大的文件。 lsof已经有打开的文件及其大小。它可能将正确的参数传递给lsof并处理输出。

Gil*_*il' 11

您可以使用-F选项lsof来获得几乎明确的输出,该输出是机器可解析的,只有中度的痛苦。输出不明确,因为将lsof文件名中的换行符重写为\n.

lsof输出由每行一个字段的。每个名称的第一个字符表示字段类型,该行的其余部分是字段值。这些字段是:p=PID(仅针对给定进程中的第一个描述符)、f=descriptor、t=type(REG对于常规文件,唯一具有大小的类型)、s=size(仅当可用时)、n=name。下面的 awk 代码收集具有大小的条目并打印大小和文件名。其余的管道对输出进行排序并保留最大尺寸的条目。

lsof -Fnst | awk '
    { field = substr($0,1,1); sub(/^./,""); }
    field == "p" { pid = $0; }
    field == "t" { if ($0 == "REG") size = 0; else next; }
    field == "s" { size = $0; }
    field == "n" && size != 0 { print size, $0; }
' | sort -k1n -u | tail -n42 | sed 's/^[0-9]* //'
Run Code Online (Sandbox Code Playgroud)


Hak*_*aba 9

一种令人费解的方式如下所示:

lsof \
| grep REG \
| grep -v "stat: No such file or directory" \
| grep -v DEL \
| awk '{if ($NF=="(deleted)") {x=3;y=1} else {x=2;y=0}; {print $(NF-x) "  " $(NF-y) } }'  \
| sort -n -u  \
| numfmt  --field=1 --to=iec
Run Code Online (Sandbox Code Playgroud)

输出

...
....
129M  /var/log/maillog
166M  /var/log/nginx/access_log
172M  /var/log/metrics/kubernetes/kubelet.log
185M  /var/log/metrics/kubernetes/etcd.log
257M  /var/log/metrics/kubernetes/etcd.log.1
335M  /var/log/metrics/kubernetes/kubelet.log.1
Run Code Online (Sandbox Code Playgroud)

我知道这并不完美。例如,如果文件名包含“DEL”,这将从输出列表中清除该文件。 lsof也有一个-F其他程序输出部分中描述的选项。使用它可能更简单。

细节

lsof 打印这样的东西:

COMMAND      PID    TID           USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
systemd        1                  root  cwd       DIR              253,0      4096        128 /
tuned       2975                  root    7u      REG              253,0      4096  805307770 /tmp/ffiKkVeXD (deleted)
python2    49888  49890           root  DEL       REG               0,18            196039884 /dev/shm/sem.NXPFow
systemd        1                  root  mem       REG              253,0     90664      10063 /usr/lib64/libz.so.1.2.7
java      149435 175229            box   69r      REG              253,0 350872273  808108999 /box/var/log/metrics/kubernetes/kubelet.log.1
java      149435 149580            box  107w     FIFO                0,8       0t0  272526226 pipe
prometheu 147867 148211           root  mem       REG              253,6             31457463 /lib64/ld-2.12.so (stat: No such file or directory)
Run Code Online (Sandbox Code Playgroud)

grep REG 保留常规文件


grep -v "stat: No such file or directory"删除有统计错误的文件。(我不知道为什么会发生这种情况)


grep -v DEL 丢弃已删除的Linux地图文件;

从 lsof文档

''DEL'' 表示已删除的 Linux 地图文件;


在这个处理之后,我们得到了这样的东西:

tuned       2975                  root    7u      REG              253,0      4096  805307770 /tmp/ffiKkVeXD (deleted)
systemd        1                  root  mem       REG              253,0     90664      10063 /usr/lib64/libz.so.1.2.7
java      149435 175229            box   69r      REG              253,0 350872273  808108999 /box/var/log/metrics/kubernetes/kubelet.log.1
Run Code Online (Sandbox Code Playgroud)

大小是倒数第 3 或第 2 列,具体取决于最后一列的值。如果最后一列是(deleted)从最后一列中选择第 3列,否则为第 2 列。

awk '{if ($NF=="(deleted)") {x=3;y=1} else {x=2;y=0}; {print $(NF-x) " " $(NF-y) } }'


sort -n -u | numfmt --field=1 --to=iec

排序、统一化并使字节数成为人类可读的


Che*_* A. 5

您可以执行以下操作

lsof | grep REG | awk '{ print $1,$7,$9 }' | sort -t ' ' -k 2 -V
Run Code Online (Sandbox Code Playgroud)

使用 awk 过滤输出以包含命令、大小和文件名,并根据第二列(即大小)对其进行排序。 -t指定分隔符,-V排序“自然” - 所以 1, 2, 10 将按这种方式排序,而不是 1, 10, 2。-k是排序的键(要排序的列)