【问题标题】:Where are all my inodes being used?我的所有 inode 都在哪里使用?
【发布时间】:2010-09-25 17:54:30
【问题描述】:

我如何找出哪些目录负责清理我的所有 inode?​​p>

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

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

谢谢,对于这个含糊的问题,我们深表歉意。

【问题讨论】:

  • 哇,人们的 inode 快用完了?自从 Usenet 早期以来,我还没有看到过这种情况,当时您必须为 mkfs 提供一个参数以使其生成更多 inode - 因为 Usenet 新闻假脱机有大量的小文件。
  • 是的 - 肯定是对过去时代的提醒。
  • 我认为这就像在说,“哇,你溢出了堆栈,而且这些天有这么多可用的内存”。发生这种情况通常有充分的理由(特定的脚本或目录),而这正是 OP 正在寻找的。​​span>
  • @PaulTomblin:共享主机。

标签: linux unix posix inode


【解决方案1】:

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

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

其中“count_files”是一个 shell 脚本(感谢 Jonathan)

echo $(ls -a "$1" | wc -l) $1

【讨论】:

  • ls 不需要 '-l' 参数 - 如果 stdout 不是 tty,它将默认为每文件一行输出。
  • 如果隐藏文件以 '.' 开头,这将找不到它们。我可能会使用 - echo $1 $(ls -a "$1" | wc -l) - 生成目录名称并在一行上计数(我很可能会颠倒顺序以首先列出计数)。请注意在重要的文件名周围小心使用引号。
  • 当您的 inode 已经用尽时,您打算如何保存“count_files”shell 脚本?
  • @AnrDaemon 服务器设置通常使用不同的分区/磁盘用于不同的用途是有原因的。例如,Usenet 新闻 spools 过去常常为空间量消耗大量 inode,因此它通常是不同的分区。并且 /home 应该始终是一个不同的分区,这样它就不会在升级过程中被意外擦除。
  • 那只是一厢情愿。 OP 中最常遇到的情况是在 VPS 上,有限的磁盘空间和大的块大小会导致文件系统快速退化,以防在一个分区上保存许多小文件。 IE。已安装多个内核头文件,但到期时未清除。
【解决方案2】:

这里有一个简单的 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);

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 这应该是正确的答案,就好像你没有更多的 inode,你不能在 Paul 的回答中创建 shell 脚本......
    • sort 可能会创建用于排序的临时文件。所以这毕竟可能不是一个防弹的解决方案。
    • +1,但请注意,此 will 命令将使用大量内存来运行 - 它实际上列出了每个文件夹中的每个文件 - 所以除非您的系统健康,否则不要这样做。
    • 这应该消耗更少的内存。您可以将“20”(最小 inode 计数)更改为您需要的任何内容:find . -type d | while read i ; do echo `ls -a "$i" | wc -l` "$i" ; done | awk '{ if($1 >= 20) print $0 }' | sort -nr
    【解决方案4】:

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

    cd /partition_that_is_out_of_inodes
    for i in *; do echo -e "$(find $i | wc -l)\t$i"; done | sort -n
    

    【讨论】:

    • 我发现这个解决方案在处理奇怪的文件名时效果更好,并且比 Hannes 解决方案的响应速度更快。
    • 没有` | sort -n` 部分并仅使用for i in *; do echo -e "$(find $i | wc -l)\t$i"; done 我发现它更好,因为每个文件夹的结果都会在已知后立即输出,而不是等到最后才对结果进行排序。这提供了更具交互性的体验和命令进度反馈
    • 你应该引用find 的参数以防它包含空格。如果有一些目录属于另一个文件系统,则计算失败。
    • 当文件名中有换行符时,解决方案也失败了,但谁在文件名中使用了换行符?
    • $i 周围加上引号以处理带有空格的目录名称。例如for i in *; do echo -e "$(find "$i" | wc -l)\t$i"; done | sort -n
    【解决方案5】:
    对于我在 dir.[01] 做 find $i -printf "%i\n"|sort -u|wc -l|xargs echo $i -- 完毕

    dir.0 -- 27913
    目录 1 -- 27913

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

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

        find /path -type d -size +500k
        

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

        请注意,此方法不是递归的。仅当您在一个目录中有大量文件时,这才会对您有所帮助,但如果文件均匀分布在其后代中,则无济于事。

        【讨论】:

          【解决方案8】:

          这是我的看法。它与其他的并没有太大的不同,但输出很漂亮,我认为它比其他(目录和符号链接)计算更多有效的 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
          

          【讨论】:

            【解决方案9】:

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

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

            【讨论】:

            • 没有解释的代码转储很少有用。请考虑在您的答案中添加一些上下文。
            【解决方案10】:

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

            find . -type f -delete
            

            【讨论】:

            • for 也很敏捷,但写起来可能更复杂。
            【解决方案11】:

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

            1.我使用了多少个 inode?​​strong>

             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 几乎用完了。

            【讨论】:

            • 这是一个比公认的更好的答案。 find 命令更快,也更彻底。谢谢!
            • 如果你遇到我同样的问题,因为没有可用空间而无法执行'sort'命令,你可以使用 -T 选项为 temp 指定一个新的路径让排序命令运行。所以命令是:find / -xdev -printf '%h\n' |排序-T /path_with_free_space/temp_test |唯一的-c |排序 -k 1 -n -T /path_with_free_space/temp_test
            【解决方案12】:

            实际功能单行(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

            【讨论】:

            • 非常感谢!您的脚本结果很简洁,适用于 100% 使用的 inode 的情况。
            • 至少是“P.S.”解决方案没有回答“我的所有 inode 都在哪里使用”的问题。例如,在我的 Ubuntu Linux 系统中,即使 /usr 下有大约 270000 个文件,它也只能在 /usr 下找到 /usr/share/man/man3(大约有 2000 个文件)。
            • 在使用任何函数进行分析之前,您应该了解文件系统结构。目录的“大小”是直接位于其中的条目数量的乘积。因此,直接检查“目录大小”只会显示直接在其中包含太多条目的目录。这在许多情况下(泛滥的会话存储、陈旧的缓存目录等)非常有效。
            【解决方案13】:

            很遗憾,它不是 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 
            

            【讨论】:

              【解决方案14】:

              使用

              ncdu -x <path>
              

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

              【讨论】:

                【解决方案15】:

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

                du -hs /*
                

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

                du -hs /var/*
                

                等等……

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

                du -s --inodes /*
                

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

                【讨论】:

                • AFAIU 目录本身使用一个 inode,例如en.wikipedia.org/wiki/Inode 声明:“inode(索引节点)是 Unix 风格文件系统中的一种数据结构,用于描述文件系统对象,例如文件或目录。”
                【解决方案16】:

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

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

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

                【讨论】:

                  猜你喜欢
                  • 2016-10-22
                  • 1970-01-01
                  • 2011-10-13
                  • 2016-05-17
                  • 1970-01-01
                  • 2016-05-27
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-10-22
                  相关资源
                  最近更新 更多