58

我如何找出哪些目录负责咀嚼我的所有 inode?

最终根目录将负责最大数量的 inode,所以我不确定我想要什么样的答案..

基本上,我用完了可用的 inode,需要找到一个不需要的目录来剔除。

谢谢,很抱歉这个模糊的问题。

4

16 回答 16

90

如果您不想创建新文件(或者因为 inode 用完而无法创建文件),您可以运行以下查询:

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

正如内部人员在另一个答案中提到的那样,使用 find 的解决方案会更快,因为递归 ls 非常慢,请在下面查看该解决方案!(信用到期的信用!)

于 2012-01-21T16:37:22.310 回答
45

提供递归ls的方法非常慢。只是为了快速找到消耗我使用的大多数 inode 的父目录:

cd /partition_that_is_out_of_inodes
for i in *; do echo -e "$(find $i | wc -l)\t$i"; done | sort -n
于 2013-01-18T03:03:01.163 回答
21

所以基本上你正在寻找哪些目录有很多文件?这是第一次尝试:

find . -type d -print0 | xargs -0 -n1 count_files | sort -n

其中“count_files”是一个shell脚本(感谢乔纳森)

echo $(ls -a "$1" | wc -l) $1
于 2008-12-07T14:29:49.433 回答
18

我使用以下方法来解决(在我的同事 James 的帮助下)我们有大量的 PHP 会话文件需要在一台机器上删除:

1. 我使用了多少个 inode?

 root@polo:/# df -i
 Filesystem     Inodes  IUsed  IFree IUse% Mounted on
 /dev/xvda1     524288 427294  96994   81% /
 none           256054      2 256052    1% /sys/fs/cgroup
 udev           254757    404 254353    1% /dev
 tmpfs          256054    332 255722    1% /run
 none           256054      3 256051    1% /run/lock
 none           256054      1 256053    1% /run/shm
 none           256054      3 256051    1% /run/user

2. 所有这些 inode 都在哪里?

 root@polo:/# find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
 [...]
    1088 /usr/src/linux-headers-3.13.0-39/include/linux
    1375 /usr/src/linux-headers-3.13.0-29-generic/include/config
    1377 /usr/src/linux-headers-3.13.0-39-generic/include/config
    2727 /var/lib/dpkg/info
    2834 /usr/share/man/man3
  416811 /var/lib/php5/session
 root@polo:/#

最后一行有很多 PHP 会话文件。

3.如何删除所有这些文件?

删除目录中所有超过 1440 分钟(24 小时)的文件:

root@polo:/var/lib/php5/session# find ./ -cmin +1440 | xargs rm
root@polo:/var/lib/php5/session#

4. 有效果吗?

 root@polo:~# find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
 [...]
    1088 /usr/src/linux-headers-3.13.0-39/include/linux
    1375 /usr/src/linux-headers-3.13.0-29-generic/include/config
    1377 /usr/src/linux-headers-3.13.0-39-generic/include/config
    2727 /var/lib/dpkg/info
    2834 /usr/share/man/man3
    2886 /var/lib/php5/session
 root@polo:~# df -i
 Filesystem     Inodes  IUsed  IFree IUse% Mounted on
 /dev/xvda1     524288 166420 357868   32% /
 none           256054      2 256052    1% /sys/fs/cgroup
 udev           254757    404 254353    1% /dev
 tmpfs          256054    332 255722    1% /run
 none           256054      3 256051    1% /run/lock
 none           256054      1 256053    1% /run/shm
 none           256054      3 256051    1% /run/user
 root@polo:~#

幸运的是,我们收到了一封邮件通知我们的 inode 几乎用完了。

于 2015-05-29T13:34:38.090 回答
11

这是我的看法。它与其他的并没有太大的不同,但输出很漂亮,我认为它比其他(目录和符号链接)计算更多的有效 inode。这会计算工作目录的每个子目录中的文件数;它将输出排序并格式化为两列;它打印一个总计(显示为“.”,工作目录)。这不会跟随符号链接,但会计算以点开头的文件和目录。这不包括设备节点和命名管道等特殊文件。如果您也想计算这些,只需删除“-type l -o -type d -o -type f”测试。因为这个命令被分成两个 find 命令,所以它不能正确区分安装在其他文件系统上的目录(-mount 选项不起作用)。例如,这应该真的忽略“/proc” 和“/sys”目录。您可以看到,在“/”中运行此命令时,包括“/proc”和“/sys”在内的总计数严重偏斜。

for ii in $(find . -maxdepth 1 -type d); do 
    echo -e "${ii}\t$(find "${ii}" -type l -o -type d -o -type f | wc -l)"
done | sort -n -k 2 | column -t

例子:

# cd /
# for ii in $(find -maxdepth 1 -type d); do echo -e "${ii}\t$(find "${ii}" -type l -o -type d -o -type f | wc -l)"; done | sort -n -k 2 | column -t
./boot        1
./lost+found  1
./media       1
./mnt         1
./opt         1
./srv         1
./lib64       2
./tmp         5
./bin         107
./sbin        109
./home        146
./root        169
./dev         188
./run         226
./etc         1545
./var         3611
./sys         12421
./lib         17219
./proc        20824
./usr         56628
.             113207
于 2014-01-08T00:24:07.773 回答
6

这是一个简单的 Perl 脚本,可以做到这一点:

#!/usr/bin/perl -w

use strict;

sub count_inodes($);
sub count_inodes($)
{
  my $dir = shift;
  if (opendir(my $dh, $dir)) {
    my $count = 0;
    while (defined(my $file = readdir($dh))) {
      next if ($file eq '.' || $file eq '..');
      $count++;
      my $path = $dir . '/' . $file;
      count_inodes($path) if (-d $path);
    }
    closedir($dh);
    printf "%7d\t%s\n", $count, $dir;
  } else {
    warn "couldn't open $dir - $!\n";
  }
}

push(@ARGV, '.') unless (@ARGV);
while (@ARGV) {
  count_inodes(shift);
}

如果您希望它像这样工作du(每个目录计数还包括子目录的递归计数),那么将递归函数更改为return $count,然后在递归点说:

$count += count_inodes($path) if (-d $path);
于 2008-12-07T15:51:11.237 回答
3

一个实际功能的单线(GNU 查找,对于其他类型的查找,您需要自己的等价物-xdev才能保持在同一个 FS 上。)

find / -xdev -type d | while read -r i; do printf "%d %s\n" $(ls -a "$i" | wc -l) "$i"; done | sort -nr | head -10

显然,尾巴是可定制的。

与此处的许多其他建议一样,这只会以非递归方式向您显示每个目录中的条目数量。

附言

快速但不精确的单行(按目录节点大小检测):

find / -xdev -type d -size +100k

于 2016-03-16T20:16:06.917 回答
1
对于我在 dir.[01]
做
    find $i -printf "%i\n"|sort -u|wc -l|xargs echo $i --
完毕

目录 0 -- 27913
目录 1 -- 27913

于 2013-06-07T23:06:16.777 回答
1

只是想提一下,您也可以使用目录大小间接搜索,例如:

find /path -type d -size +500k

如果您有很多大目录,则可以增加 500k。

请注意,此方法不是递归的。如果您在一个目录中有很多文件,这只会对您有所帮助,但如果文件均匀分布在其后代中,则不会。

于 2014-01-06T14:23:36.797 回答
1

采用

ncdu -x <path>

然后按 Shitf+c 按项目计数排序

于 2017-09-27T13:13:35.770 回答
0

perl 脚本很好,但要注意符号链接 - 仅当 -l filetest 返回 false 时才会递归,否则您充其量会过度计算,最坏的情况是无限期地递归(这可能 - 次要问题 - 调用撒旦的 1000 年统治)。

当有多个链接指向超过一小部分文件时,计算文件系统树中的 inode 的整个想法就会崩溃。

于 2013-11-02T02:10:18.570 回答
0

请注意,当您最终找到某个邮件假脱机目录并想要删除其中的所有垃圾时,如果文件太多, rm * 将不起作用,您可以运行以下命令快速删除该目录中的所有内容:

* 警告 *这将在 rm 不起作用的情况下快速删除所有文件

find . -type f -delete
于 2015-02-03T22:59:24.860 回答
0

不幸的是,这不是 POSIX 解决方案,但是......这会计算当前目录下的文件。即使文件名包含换行符,这也应该有效。它使用 GNU awk。将 d 的值(从 2)更改为所需的最大分离路径深度。0 表示无限深度。在最深层的子目录中的文件被递归计算。

d=2; find . -mount -not -path . -print0 | gawk '
BEGIN{RS="\0";FS="/";SUBSEP="/";ORS="\0"}
{
    s="./"
    for(i=2;i!=d+1 && i<NF;i++){s=s $i "/"}
    ++n[s]
}
END{for(val in n){print n[val] "\t" val "\n"}}' d="$d" \
 | sort -gz -k 1,1

与 Bash 4 相同;给出深度作为脚本的参数。根据我的经验,这要慢得多:

#!/bin/bash
d=$1
declare -A n

while IFS=/ read -d $'\0' -r -a a; do
  s="./"
  for ((i=2; i!=$((d+1)) && i<${#a[*]}; i++)); do
    s+="${a[$((i-1))]}/"
  done
  ((++n[\$s]))
done < <(find . -mount -not -path . -print0)

for j in "${!n[@]}"; do
    printf '%i\t%s\n\0' "${n[$j]}" "$j"
done | sort -gz -k 1,1 
于 2016-09-07T22:18:40.607 回答
0

在搜索占用磁盘空间最多的文件夹时,我曾经du像这样从上到下工作:

du -hs /*

这是列出每个顶级文件夹的文件消耗。之后,您可以通过扩展给定模式进入任一文件夹:

du -hs /var/*

等等 ...

现在,当涉及到 inode 时,可以使用相同的工具,但参数略有不同:

du -s --inodes /*

在同一文件夹中有一个缓存改进了此工具的后续调用,这在正常情况下是有益的。但是,当您用完 inode 时,我认为这会变成相反的情况。

于 2020-06-06T08:09:23.400 回答
0

不需要复杂的 for/ls 结构。您可以通过以下方式获得 10 个最胖(就 inode 使用而言)目录:

du --inodes --separate-dirs --one-file-system | sort -rh | head

--one-file-system参数是可选的。

于 2022-02-03T09:38:37.260 回答
-2

此命令适用于极不可能的情况,即您的目录结构与我的相同:

find / -type f | grep -oP '^/([^/]+/){3}' | sort | uniq -c | sort -n

于 2014-10-11T00:09:10.267 回答