Inode 사용 위치 결정


15

최근에 시스템 사용을 추적하기 위해 개발 웹 서버에 Munin을 설치했습니다. 디스크 사용량이 거의 증가하지 않았지만 시스템의 inode 사용량이 하루 약 7-8 % 증가하고 있음을 알았습니다. 뭔가 작은 파일을 쓰고 있다고 생각하지만 무엇을 어디서 찾을 수 없습니다.

디스크 공간 사용량을 찾는 방법을 알고 있지만 inode 사용량을 요약하는 방법을 찾지 못하는 것 같습니다.

디렉토리를 기준으로 inode 사용을 결정하는 좋은 방법이 있습니까? 사용 소스를 찾을 수 있습니까?

답변:


15

이것이 빨리 실행될 것으로 기대하지 마십시오 ...

inode가 많은 서브 디렉토리가 있다고 생각되는 디렉토리로 cd하십시오. 이 스크립트에 많은 시간이 걸리면 파일 시스템의 위치를봤을 것입니다. / var는 좋은 시작입니다 ...

그렇지 않으면, 해당 파일 시스템에서 최상위 디렉토리로 변경하고이를 실행하고 완료 될 때까지 기다리면 모든 inode가있는 디렉토리를 찾을 수 있습니다.

find . -type d | 
while 
  read line  
do 
  echo "$( find "$line" -maxdepth 1 | wc -l) $line"  
done | 
sort -rn | less

정렬 비용이 걱정되지 않습니다. 테스트를 실행하고 350,000 개의 디렉토리에 대해 분류되지 않은 출력을 정렬하는 데 8 초가 걸렸습니다. 처음 발견했다. 실제 비용은 while 루프에서 이러한 모든 디렉토리를 여는 것입니다. 루프 자체는 22 초가 걸립니다. 테스트 데이터는 350,000 개의 디렉토리가있는 서브 디렉토리에서 실행되었으며 그 중 하나에는 백만 개의 파일이 있고 나머지는 1-15 개의 디렉토리가있었습니다.

다양한 사람들은 ls가 출력을 정렬하기 때문에 그 점이 좋지 않다고 지적했습니다. 나는 메아리를 시도했지만 그다지 좋지 않습니다. 다른 사람은 stat 이이 정보 (디렉토리 항목 수)를 제공하지만 이식 가능하지 않다고 지적했습니다. find -maxdepth는 디렉토리를 여는 데 실제로 빠르며 .files를 계산하므로 모든 사람을위한 포인트입니다.


2
@ mike G : 이런 종류의 작업을 수행하는 가장 빠른 방법이 아니라는 점에 대해 100 % 정확합니다. 내 생각에 이것을 최적화하는 올바른 방법은 스크립트의 "count directory items"부분을 시작하고 마칠 때 stderr로 리디렉션하는 것입니다. 이렇게하면 백만 개의 항목이있는 디렉토리에 도달하면 "처리 디렉토리 스풀 / postfix / maildrop"이라고 말한 다음 즉시 "완료"및 붐이라고 말하지 않습니다-스풀 / postfix / maildrop을 보면 많은 것을 볼 수 있습니다 파일.
chris

또한 정렬 비용에 대해 걱정하지 않았습니다.이 작업은 한 번 또는 최소한의 경우는 드물기 때문입니다.
Dave Forgac

7

문제가 파일이 너무 많은 하나의 디렉토리 인 경우 간단한 해결책은 다음과 같습니다.

# Let's find which partition is out of inodes:
$ df -hi
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda3               2.4M    2.4M       0  100% /
...

# Okay, now we know the mount point with no free inodes,
# let's find a directory with too many files:
$ find / -xdev -size +100k -type d

find줄 의 아이디어 는 디렉토리의 크기가 해당 디렉토리 내부의 파일 크기에 비례한다는 것입니다. 그래서 여기에 많은 파일이있는 디렉토리를 찾습니다.

숫자를 추측하고 싶지 않고 "size"로 정렬 된 모든 의심되는 디렉토리를 나열하는 것을 선호하는 경우에도 쉽습니다.

# Remove the "sort" command if you want incremental output
find / -xdev -size +10k -type d -printf '%s %p\n' | sort -n

6

Grrr, 댓글을 달려면 50 명의 답변이 필요합니다. 이 답변은 실제로 chris의 답변에 대한 주석입니다.

질문자는 아마도 모든 디렉토리에 신경 쓰지 않을 것이므로 최악의 디렉토리 만 정렬을 사용하면 sort를 사용하는 것이 너무 비싸다.

find . -type d | 
while 
  read line  
do 
  echo "$(ls "$line" | wc -l) $line"  
done | 
perl -a -ne'next unless $F[0]>=$max; print; $max=$F[0]'  | less

이것은 버전만큼 완전하지는 않지만 인쇄 라인이 이전 최대 값보다 크면 인쇄되는 노이즈의 양을 크게 줄이고 정렬 비용을 절약하는 것입니다.

이것의 단점은 매우 큰 디렉토리가 2 개이고 첫 번째 디렉토리가 2 번째 디렉토리보다 1 개의 inode를 갖는 경우 2 번째는 보이지 않습니다.

보다 완벽한 솔루션은 가장 많이 본 10 가지 값을 추적하고 마지막에 출력하는 똑똑한 펄 스크립트를 작성하는 것입니다. 그러나 빠른 서버 오류에 대한 답변이 너무 깁니다.

또한 좀 더 똑똑한 perl 스크립팅을 사용하면 while 루프를 건너 뛸 수 있습니다. 대부분의 플랫폼에서 ls는 결과를 정렬하므로 큰 디렉토리의 경우 매우 비쌉니다. 우리가 관심있는 모든 것이 카운트이기 때문에 ls 정렬은 필요하지 않습니다.


1
ls에 대한 진실-이와 같은 상황에서 나는 내가하고있는 일이 분명하고 성능에 대해서는별로 신경 쓰지 않을 것에 대해 더 걱정합니다. echo $ line / *를 사용할 수 있다고 확신합니다. | ls $ line 대신 wc -w | wc -l 및 ls 정렬 문제를 피하십시오.
chris

방금 백만 개의 파일이있는 디렉토리에서 테스트를 실행했으며 ls는 22 초가 걸리고 echo *는 12 초가 걸렸습니다. (기록을 위해, 쉘에서 echo *는 활성화 된 쉘의 99 %에있는 에코가 내장되어 있기 때문에 arg 한계에 도달하지 않습니다)
chris

ls -f는 결과를 정렬하지 않습니다. 디렉토리 결과를 정렬하면 NFS 및 대형 디렉토리에서 공통적 인 문제가 발생합니다. 서버에서 디렉토리를 읽고 정렬하는 데 시간이 NFS 시간 종료를 초과하면 디렉토리 및 서브 디렉토리를 사용할 수 없습니다.
mpez0

5

이 작은 스 니펫을 사용할 수 있습니다.

find | cut -d/ -f2 | uniq -c | sort -n

현재 폴더의 각 디렉토리에있는 파일 및 디렉토리 수와 가장 큰 문제가 맨 아래에 인쇄됩니다. 파일이 많은 디렉토리를 찾는 데 도움이됩니다. ( 더 많은 정보 )


이것은 훌륭하게 작동했습니다.
ptman

3

이것은 귀하의 질문에 대한 직접적인 대답은 아니지만 find를 사용하여 작은 크기의 최근 수정 된 파일을 검색하면 검색 범위가 좁힐 수 있습니다.

find / -mmin -10 -size -20k

3
find /path ! -type d | sed 's,/[^/]*$,,' | uniq -c | sort -rn

ls 는 이름이 마침표로 시작하는 파일을 찾지 않습니다. find를 사용 하면 이것을 피할 있습니다. 디렉토리 트리에서 모든 파일을 찾고 각 경로 끝에서 기본 이름을 지정하고 각 디렉토리 경로가 결과 출력에 나타나는 횟수를 계산합니다. "!"를 넣어야 할 수도 있습니다. 쉘이 그것에 대해 불평하면 따옴표로 묶습니다.

Inode는 삭제되었지만 실행중인 프로세스에 의해 열려있는 파일에서도 사용할 수 있습니다. 이 Munin 패키지에 지속적으로 실행되는 프로그램이 포함되어 있으면 확인해야 할 또 다른 사항은 비정상적인 수의 파일이 열려 있는지 여부입니다.


inode는 또한 실제로는 찾을 수없는 깊은 디렉토리에 의해 취해질 수 있습니다. 여기에는 여러 가지 이상한 경우가 있지만 가장 일반적인 상황은 일반 이름을 가진 파일로 가득 찬 디렉토리입니다.
chris

3

나는 이것을 무력하게 만들 것입니다 : 기준선에 대해 전체 장치에서 tripwire를 실행 한 다음 잠시 후 확인을 실행하면 문제가되는 디렉토리가 아픈 엄지처럼 튀어 나옵니다.


아마도 10 억년이 걸릴 것입니다. 더 빠른 방법은 lsof를 실행하는 것입니다 | grep DIR을 실행하고 각 디렉토리에서 많은 새 파일을 찾으십시오.
chris

2
좋아, 이것에 대해서는 : find / | sort> /tmp/find1.txt; 찾기 / | sort> /tmp/find2.txt; diff /tmp/find1.txt /tmp/find2.txt
Geoff Fritz

2

(댓글을 작성할 수없는 것은 실제로 나이가 들었습니다-이것은 예를 들어 종교입니다)

egorgry-ls -i는 inode COUNT가 아니라 항목에 대해 inode NUMBER를 인쇄합니다.

디렉토리에있는 파일로 시도하십시오. 아마도 같은 숫자가 표시되지만 inode 수는 아니며 디렉토리 엔트리가 가리키는 inode # 일뿐입니다.


lol. 나는 당신에게 하나를 투표했다. 설명 주셔서 감사합니다. inode 사용법은 항상 혼란 스러웠습니다.
egorgry

고마워 이제이 답변을 삭제할 때 카르마를 잃을 경우를 대비하여 노드에 대한 주석으로 변환하는 것이 두렵습니다. :)
Mike G.

2

최신 정보

맨 아래에 가장 큰 항목이있는 지정된 디렉토리의 각 자식의 inode 수를 반환하는 하나의 라이너.

find . -mindepth 1 -printf "%p/%i\n" \
  | awk -F/ '{print $2"/"$NF}' | sort -u \
  | cut -d/ -f1 | uniq -c | sort -n

원래 답변

#!/bin/bash
# Show inode distribution for given directory

dirs=$(find $1 -mindepth 1 -maxdepth 1 -type d)

for dir in $dirs
do
    inode_count=$(find $dir -printf "%i\n" 2> /dev/null | sort -u | wc -l)
    echo "$inode_count $dir"
done

위와 같이 실행하십시오 (위의 스크립트가 작업 디렉토리의 실행 파일에 있음)

./indist / | sort -n

1

inode 사용법은 파일이나 디렉토리 당 대략 하나입니다. 그러니

find [path] -print | wc -l

[path]에서 사용 된 inode 수를 대략적으로 계산합니다.


1

효율적인 쉘 파이프 라인을 작성하려고했지만 다루기가 어려워지고 느리거나 부정확했습니다.

find . -depth -printf '%h\n' | uniq -c | awk '$1>1000'

1000 개 이상의 파일이있는 리프 디렉토리 (및 기타 디렉토리)가 나열됩니다. 따라서 시간과 RAM 모두에서 효율적으로 수행하는 Perl 스크립트가 있습니다. 출력은 같다

«하위 트리에있는 파일»«디렉토리에 직접있는 파일»«디렉토리 이름»

위와 같이 일반적인 도구 (예 : sort (1) 또는 awk (1))를 사용하여 쉽게 마사지하고 필터링 할 수 있습니다.

#! /usr/bin/perl -w
# Written by Kjetil Torgrim Homme <kjetil.homme@redpill-linpro.com>

use strict;
use File::Find;

my %counted;
my %total;

sub count {
    ++$counted{$File::Find::dir};
}

sub exeunt {
    my $dir = $File::Find::dir;

    # Don't report leaf directories with no files
    return unless $counted{$dir}; 

    my $parent = $dir;
    $parent =~ s!/[^/]*$!!;

    $total{$dir} += $counted{$dir};
    $total{$parent} += $total{$dir} if $parent ne $dir;
    printf("%8d %8d %s\n", $total{$dir}, $counted{$dir}, $dir);
    delete $counted{$dir};
    delete $total{$dir};
}

die "Usage: $0 [DIRECTORY...]\n" if (@ARGV && $ARGV[0] =~ /^-/);
push(@ARGV, ".") unless @ARGV;

finddepth({ wanted => \&count, postprocess => \&exeunt}, @ARGV);

-1
[gregm@zorak2 /]$ ls -i /home
131191 gregm

내 랩톱의 집에서 131191 inode를 사용하고 있습니다.


3
ls -i는 inode COUNT가 아니라 항목에 대해 inode NUMBER를 인쇄합니다. 디렉토리에있는 파일로 시도하십시오. 아마도 같은 숫자가 표시되지만 inode 수는 아니며 디렉토리 엔트리가 가리키는 inode # 일뿐입니다.
egorgry
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.