查找在哪里使用inode


189

因此,我从监控系统中的一个盒子上收到了一个警告,指出文件系统上可用空闲节点的数量正在减少。

df -i 输出显示以下内容:

Filesystem       Inodes  IUsed    IFree IUse% Mounted on
/dev/xvda1       524288 422613   101675   81% /

如您所见,根分区已使用其索引节点的81%。
我怀疑它们都在单个目录中使用。但是我怎么能找到那呢?

Answers:


214

我在stackoverflow上看到了这个问题,但是我不喜欢任何答案,无论如何,这确实是应该在U&L上提出的问题。

基本上,索引节点用于文件系统上的每个文件。因此,用尽inode通常意味着您周围有很多小文件。因此问题就变成了“哪个目录中包含大量文件?”

在这种情况下,我们关心的文件系统是根文件系统/,因此我们可以使用以下命令:

find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n

这将转储文件系统上每个目录的列表,并以该目录中文件(和子目录)的数量为前缀。因此,文件数量最多的目录将位于底部。

以我为例,它显示以下内容:

   1202 /usr/share/man/man1
   2714 /usr/share/man/man3
   2826 /var/lib/dpkg/info
 306588 /var/spool/postfix/maildrop

因此,基本上/var/spool/postfix/maildrop是在消耗所有inode。

请注意,这个答案确实有三个需要注意的警告。它不能正确处理路径中带有换行符的任何内容。我知道我的文件系统没有带换行符的文件,并且由于该文件仅用于人类消费,因此潜在的问题不值得解决(并且始终可以\n\0和替换sort -z上面的)。如果文件分散在大量目录中,它也不会处理。但这不太可能,因此我认为风险可以接受。它还会多次计数到同一文件的硬链接(因此仅使用一个inode)。同样,不太可能产生误报


我不喜欢关于stackoverflow答案的任何答案的主要原因是它们都跨越了文件系统边界。由于我的问题是在根文件系统上,所以这意味着它将遍历每个已挂载的文件系统。投掷-xdev在查找命令甚至没有正常工作。
例如,最受好评的答案是这个:

for i in `find . -type d `; do echo `ls -a $i | wc -l` $i; done | sort -n

如果我们改为

for i in `find . -xdev -type d `; do echo `ls -a $i | wc -l` $i; done | sort -n

即使/mnt/foo是坐骑,它也是根文件系统上的目录,因此它将出现在中find . -mount -type d,然后将其传递到ls -a $i,然后将潜入坐骑。

find在我的答案,而不是列出了安装的每一个文件的目录。因此基本上具有以下文件结构:

/foo/bar
/foo/baz
/pop/tart

我们最终以

/foo
/foo
/pop

因此,我们只需要计算重复行的数量即可。


2
@MohsenPahlevanzadeh不是我的答案的一部分,我是在评论为什么我不喜欢该解决方案,因为它是该问题的常见答案。
Patrick

7
使用绑定挂载是避免搜索其他文件系统的更可靠的方法,因为它允许访问挂载点下的文件。例如,假设我在下创建了300,000个文件/tmp,然后将系统配置为在上安装tmpfs /tmp。这样一来,您将无法单独找到文件find。不太可能是senario,但值得注意。
Graeme

2
两项工作都只需要删除sort,因为当输出足够大时sort需要创建一个文件,这是不可能的,因为我使用了100%的inode。
qwertzguy

1
请注意,这-printf似乎是要查找的GNU扩展,因为OS X中可用的BSD版本不支持它。
熊恰亚诺夫,2016年

1
所有文件都在一个目录中这一假设很困难。许多程序都知道单个目录中的许多文件性能很差,因此会
散乱

26

这是按质询者的要求从此处转贴的:

du --inodes -S | sort -rh | sed -n \
        '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'

如果要保留在同一文件系统中,请执行以下操作:

du --inodes -xS

这是一些示例输出:

15K     /usr/share/man/man3
4.0K    /usr/lib
3.6K    /usr/bin
2.4K    /usr/share/man/man1
1.9K    /usr/share/fonts/75dpi
...
519     /usr/lib/python2.7/site-packages/bzrlib
516     /usr/include/KDE
498     /usr/include/qt/QtCore
487     /usr/lib/modules/3.13.6-2-MANJARO/build/include/config
484     /usr/src/linux-3.12.14-2-MANJARO/include/config

现在使用LS:

一些人提到他们没有最新的coreutils,并且--inodes选项对他们不可用。所以,这是ls:

ls ~/test -AiR1U | 
sed -rn '/^[./]/{h;n;};G;
    s|^ *([0-9][0-9]*)[^0-9][^/]*([~./].*):|\1:\2|p' | 
sort -t : -uk1.1,1n |
cut -d: -f2 | sort -V |
uniq -c |sort -rn | head -n10

如果您很好奇,那么麻烦的一点儿麻烦regex就是将filename每个ls's递归搜索结果中的替换为找到它的目录名称。从那里,只需压缩重复的索引节点编号,然后计算重复的目录名称并进行相应排序即可。

-U选项与在分拣特别有用的是它专门针对没有进行排序,而是提出在原来的顺序目录列表-或者,换句话说,通过inode数。

当然-1,这非常有用,因为它可以确保每行只有一个结果,而不管文件名中可能包含换行符,还是尝试解析列表时可能发生的其他不幸的问题。

当然,-A对于所有人,-iinode和-R递归来说,这都是长短。

这样做的基本方法是,我将ls的每个文件名替换为sed中包含目录名称的文件名。接下来……好吧,我自己有点模糊。我可以肯定,它可以准确计数文件,如您在此处看到的:

% _ls_i ~/test
> 100 /home/mikeserv/test/realdir
>   2 /home/mikeserv/test
>   1 /home/mikeserv/test/linkdir

这为我提供了与du命令几乎相同的结果:

杜:

15K     /usr/share/man/man3
4.0K    /usr/lib
3.6K    /usr/bin
2.4K    /usr/share/man/man1
1.9K    /usr/share/fonts/75dpi
1.9K    /usr/share/fonts/100dpi
1.9K    /usr/share/doc/arch-wiki-markdown
1.6K    /usr/share/fonts/TTF
1.6K    /usr/share/dolphin-emu/sys/GameSettings
1.6K    /usr/share/doc/efl/html

LS:

14686   /usr/share/man/man3:
4322    /usr/lib:
3653    /usr/bin:
2457    /usr/share/man/man1:
1897    /usr/share/fonts/100dpi:
1897    /usr/share/fonts/75dpi:
1890    /usr/share/doc/arch-wiki-markdown:
1613    /usr/include:
1575    /usr/share/doc/efl/html:
1556    /usr/share/dolphin-emu/sys/GameSettings:

我认为include事情只取决于程序首先查看哪个目录-因为它们是相同的文件,并且经过硬链接。有点喜欢上面的事情。我对此可能是错的-我欢迎改正...

杜德莫

% du --version
> du (GNU coreutils) 8.22

创建一个测试目录:

% mkdir ~/test ; cd ~/test
% du --inodes -S
> 1       .

一些子目录:

% mkdir ./realdir ./linkdir
% du --inodes -S
> 1       ./realdir
> 1       ./linkdir
> 1       .

制作一些文件:

% printf 'touch ./realdir/file%s\n' `seq 1 100` | . /dev/stdin
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

一些硬链接:

% printf 'n="%s" ; ln ./realdir/file$n ./linkdir/link$n\n' `seq 1 100` | 
    . /dev/stdin
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

查看硬链接:

% cd ./linkdir
% du --inodes -S
> 101

% cd ../realdir
% du --inodes -S
> 101

他们一个人算,但上一个目录...

% cd ..
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

然后从下面运行我的运行脚本,然后:

> 100     /home/mikeserv/test/realdir
> 100     /home/mikeserv/test/linkdir
> 2       /home/mikeserv/test

和格雷姆的:

> 101 ./realdir
> 101 ./linkdir
> 3 ./

因此,我认为这表明计数inode的唯一方法是使用inode。而且,由于对文件进行计数意味着对inode进行计数,因此您不能对inode进行双重计数-要对文件进行精确计数,就不能对inode进行多次计数。


2
添加了哪个版本--inodes?哪个“变体” /“风味” /“ posix-wannabes” /“实现” /什么?
n611x007

Ubuntu的14.04.5:杜:无法识别的选项'--inodes'
普特尼克

du(GNU coreutils)自2014年以来的版本8.23(在我过时的Debian Jessie中)。Debian> Ubuntu为那个双关语感到抱歉:P Ubuntu的包太旧了……
Daniel W.

6

我使用了SO Q&A中题为:我的所有inode都在哪里使用的答案当我们的NAS大约2年前用完时:

$ find . -type d -print0 \
    | while IFS= read -rd '' i; do echo $(ls -a "$i" | wc -l) "$i"; done \
    | sort -n

$ find . -type d -print0 \
    | while IFS= read -rd '' i; do echo $(ls -a "$i" | wc -l) "$i"; done \
    | sort -n
...
110 ./MISC/nodejs/node-v0.8.12/out/Release/obj.target/v8_base/deps/v8/src
120 ./MISC/nodejs/node-v0.8.12/doc/api
123 ./apps_archive/monitoring/nagios/nagios-check_sip-1.3/usr/lib64/nagios
208 ./MISC/nodejs/node-v0.8.12/deps/openssl/openssl/doc/crypto
328 ./MISC/nodejs/node-v0.8.12/deps/v8/src
453 ./MISC/nodejs/node-v0.8.12/test/simple

检查设备的Inode

根据您的NAS,它可能无法提供功能齐全的df命令。因此,在这些情况下,您可以改为使用tune2fs

$ sudo tune2fs -l /dev/sda1 |grep -i inode
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Inode count:              128016
Free inodes:              127696
Inodes per group:         2032
Inode blocks per group:   254
First inode:              11
Inode size:           128
Journal inode:            8
Journal backup:           inode blocks

跨越文件系统边界

您可以使用-xdev开关直接find将搜索范围缩小到您要启动搜索的设备。

假设我/home通过我的NAS(名称为mulder)通过NFS共享进行目录自动挂载。

$ df -h /home/sam 
Filesystem            Size  Used Avail Use% Mounted on
mulder:/export/raid1/home/sam
                      917G  572G  299G  66% /home/sam

注意,安装点仍被认为是系统本地的。

$ df -h /home/ .
Filesystem            Size  Used Avail Use% Mounted on
-                        0     0     0   -  /home
/dev/mapper/VolGroup00-LogVol00
                      222G  159G   52G  76% /

现在当我启动时find

$ find / -xdev  | grep '^/home'
/home

它发现/home但没有自动装入的内容,因为它们位于不同的设备上!

文件系统类型

您可以利用切换到find-fstype以控制find将查找哪种类型的文件系统。

   -fstype type
          File is on a filesystem of type type.  The valid filesystem types 
          vary among different versions of Unix; an incomplete list of 
          filesystem  types that are accepted on some version of Unix or 
          another is: ufs, 4.2, 4.3, nfs, tmp, mfs, S51K, S52K.  You can use 
          -printf with the %F directive to see the types of your
          filesystems.

我有什么文件系统?

$ find . -printf "%F\n" | sort -u
ext3

因此,您可以使用它来控制交叉路口:

仅ext3

$ find . -fstype ext3 | head -5
.
./gdcm
./gdcm/gdcm-2.0.16
./gdcm/gdcm-2.0.16/Wrapping
./gdcm/gdcm-2.0.16/Wrapping/CMakeLists.txt

只有nfs

$ find . -fstype nfs | head -5
$ 

ext3和ext4

$ find . -fstype ext3 -o -fstype ext4 | head -5
.
./gdcm
./gdcm/gdcm-2.0.16
./gdcm/gdcm-2.0.16/Wrapping
./gdcm/gdcm-2.0.16/Wrapping/CMakeLists.txt

您如何防止它跨越文件系统边界?就像if /是否已满,并且已经安装了网络文件系统一样,您不想深入研究网络文件系统。
帕特里克

@Patrick-查看更新,您可以使用-fstype来控制它find
slm

1
@Gilles-简单的答案...在找到的手册页中没有完全翻页8
slm

@Gilles-手册页似乎并不表示-xtype排除文件系统,而是查看文件的类型。我只找到这样的示例:find . \( -fstype nfs -prune \)
slm

@Gilles-我在关于如何find避免越过文件系统边界的评论中谈到了Patrick的问题。在他的前任。他提到“就像/如果已满,并且您已经安装了网络文件系统,就不想深入研究网络文件系统”。
slm


3

要列出的详细索引节点用法/,请使用以下命令:

echo "Detailed Inode usage for: $(pwd)" ; for d in `find -maxdepth 1 -type d |cut -d\/ -f2 |grep -xv . |sort`; do c=$(find $d |wc -l) ; printf "$c\t\t- $d\n" ; done ; printf "Total: \t\t$(find $(pwd) | wc -l)\n" 

欢迎到这里!我建议下一次格式化更好。
彼得2015年

1
这是一个单行,我没有发现任何错误。
sjas

2

绝对最多的回答可以帮助理解linux和unix中的inode的概念,但是当涉及到从磁盘删除或删除inode的实际问题时,它并没有真正的帮助。在基于ubuntu的系统上执行此操作的一种更简单的方法是删除不需要的linux内核标头和映像。

sudo apt-get autoremove

会为你做的。就我而言,由于收到警报,因此inode的使用率为78%。

$ df -i
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
/dev/xvda1     524288 407957 116331   78% /
none           957443      2 957441    1% /sys/fs/cgroup
udev           956205    388 955817    1% /dev
tmpfs          957443    320 957123    1% /run
none           957443      1 957442    1% /run/lock
none           957443      1 957442    1% /run/shm
none           957443      5 957438    1% /run/user

运行sudo apt-get autoremove命令后,它已下降到29%

$ df -i
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
/dev/xvda1     524288 150472 373816   29% /
none           957443      2 957441    1% /sys/fs/cgroup
udev           956205    388 955817    1% /dev
tmpfs          957443    320 957123    1% /run
none           957443      1 957442    1% /run/lock
none           957443      1 957442    1% /run/shm
none           957443      5 957438    1% /run/user

这只是我的观察,节省了我的时间。人们可能会找到比这更好的解决方案。


2

我发现使用以下命令可以更快速,更轻松地进行深入分析:

$ sudo du -s --inodes * | sort -rn

170202  var
157325  opt
103134  usr
53383   tmp
<snip>

然后,您可以进入var例如查看使用目录的大索引节点。


0

到目前为止,每个答案都假定问题出在单个目录中有许多文件,而不是所有导致问题的子目录中。幸运的是,解决方案是仅使用更少的标志。

# du --inodes --one-file-system /var | sort --numeric-sort
...
2265    /var/cache/salt/minion
3818    /var/lib/dpkg/info
3910    /var/lib/dpkg
4000    /var/cache/salt/master/gitfs/refs
4489    /var/lib
5709    /var/cache/salt/master/gitfs/hash
12954   /var/cache/salt/master/gitfs
225058  /var/cache/salt/master/jobs
241678  /var/cache/salt/master
243944  /var/cache/salt
244078  /var/cache
248949  /var

或更短的选项:du --inodes -x | sort -n。不幸的是,并非所有版本都du具有inodes选项。

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.