กำหนดตำแหน่งของการใช้ Inode


15

ฉันเพิ่งติดตั้ง Munin บนเว็บเซิร์ฟเวอร์การพัฒนาเพื่อติดตามการใช้งานระบบ ฉันได้แจ้งว่าการใช้งาน inode ของระบบกำลังเพิ่มขึ้นประมาณ 7-8% ต่อวันแม้ว่าการใช้งานดิสก์จะเพิ่มขึ้นแทบทุกครั้ง ฉันคาดเดาว่ามีบางอย่างกำลังเขียนไฟล์ขนาดเล็กมากมาย แต่ฉันไม่สามารถหาได้ที่ไหน

ฉันรู้วิธีค้นหาการใช้พื้นที่ดิสก์ แต่ฉันไม่สามารถหาวิธีสรุปการใช้ inode ได้

มีวิธีที่ดีในการตรวจสอบการใช้งาน inode ตามไดเรกทอรีหรือไม่เพื่อให้ฉันสามารถหาที่มาของการใช้งานได้?

คำตอบ:


15

อย่าคาดหวังว่าสิ่งนี้จะทำงานได้อย่างรวดเร็ว ...

cd ไปยังไดเรกทอรีที่คุณสงสัยว่าอาจมีไดเรกทอรีย่อยที่มี inodes มากมาย หากสคริปต์นี้ใช้เวลานานคุณอาจพบว่าอยู่ในระบบไฟล์เพื่อค้นหา / var เป็นการเริ่มต้นที่ดี ...

มิฉะนั้นถ้าคุณเปลี่ยนไปที่ไดเรกทอรีบนสุดในระบบไฟล์นั้นแล้วเรียกใช้และรอจนกว่าจะเสร็จคุณจะพบไดเรกทอรีที่มี inodes ทั้งหมด

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

ฉันไม่กังวลเกี่ยวกับค่าใช้จ่ายในการจัดเรียง ฉันทำการทดสอบและเรียงลำดับผลลัพธ์ที่ไม่เรียงลำดับของไดเรกทอรี 350,000 ไดเรกทอรีใช้เวลา 8 วินาที การค้นหาเริ่มต้นใช้เวลา ราคาจริงกำลังเปิดไดเรกทอรีเหล่านี้ทั้งหมดในขณะที่วนรอบ (ลูปเองใช้เวลา 22 วินาที) (ข้อมูลทดสอบถูกเรียกใช้ในไดเรกทอรีย่อยที่มี 350,000 ไดเรกทอรีหนึ่งในนั้นมีหนึ่งล้านไฟล์ส่วนที่เหลือมีระหว่าง 1 ถึง 15 ไดเรกทอรี)

มีคนหลายคนชี้ให้เห็นว่า ls นั้นไม่ดีเพราะมันเรียงลำดับผลลัพธ์ ฉันลองใช้เสียงก้องแล้ว แต่นั่นก็ไม่ได้ยอดเยี่ยมเช่นกัน มีคนอื่นชี้ให้เห็นว่าสถิติให้ข้อมูลนี้ (จำนวนรายการไดเรกทอรี) แต่ไม่สามารถพกพาได้ ปรากฎว่าการหา - maxdepth นั้นรวดเร็วมากในการเปิดไดเร็กตอรี่และนับเป็น. ไฟล์ดังนั้น ... ที่นี่มันคือ .. จุดสำหรับทุกคน!


2
@ ไมค์ G: คุณถูกต้อง 100% เกี่ยวกับเรื่องนี้ไม่ใช่วิธีที่เร็วที่สุดที่จะทำสิ่งนี้ ในใจของฉันวิธีที่ถูกต้องเพื่อเพิ่มประสิทธิภาพนี้คือการเปลี่ยนเส้นทางไปยัง stderr เมื่อเริ่มต้นและจบส่วน "นับรายการไดเรกทอรี" ของสคริปต์ ด้วยวิธีนี้เมื่อคุณเข้าสู่ไดเรกทอรีที่มีล้านรายการมันจะพูดว่า "การประมวลผลไดเรกทอรีสปูล / postfix / maildrop" แล้วไม่พูดทันที "เสร็จสิ้น" และบูม - ดูในสปูล / postfix / maildrop และคุณจะเห็นจำนวนมาก ไฟล์
chris

ฉันยังไม่ได้กังวลเกี่ยวกับค่าใช้จ่ายในการจัดเรียงเนื่องจากเป็นงานที่เกิดขึ้นครั้งเดียวหรืออย่างน้อยก็ไม่บ่อยนัก
เดฟ 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บรรทัดคือขนาดของไดเรกทอรีเป็นสัดส่วนกับปริมาณของไฟล์ในไดเรกทอรีนั้นโดยตรง ดังนั้นที่นี่เราค้นหาไดเรกทอรีที่มีไฟล์มากมายอยู่ข้างใน

หากคุณไม่ต้องการคาดเดาจำนวนและต้องการแสดงรายการไดเรกทอรีที่น่าสงสัยทั้งหมดที่เรียงลำดับโดย "ขนาด" นั่นก็เป็นเรื่องง่ายเช่นกัน:

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

6

Grrr, การแสดงความคิดเห็นต้องใช้ 50 ตัวแทน ดังนั้นคำตอบนี้เป็นความเห็นต่อคำตอบของคริส

เนื่องจากผู้ถามอาจไม่สนใจไดเรกทอรีทั้งหมดมีเพียงไดเรกทอรีที่แย่ที่สุดเท่านั้นดังนั้นการใช้การเรียงลำดับจึงมีราคาแพงเกินไป

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 ไดเรกทอรีที่มีขนาดใหญ่มากและสิ่งแรกที่เกิดขึ้นคือมี inode มากกว่า 1 มากกว่า 2 คุณจะไม่เห็นที่ 2

โซลูชันที่สมบูรณ์มากขึ้นคือการเขียนสคริปต์ perl ที่ฉลาดขึ้นซึ่งคอยติดตามค่า 10 อันดับแรกที่เห็นและพิมพ์ค่าเหล่านั้นในตอนท้าย แต่มันยาวเกินไปสำหรับคำตอบที่รวดเร็วสำหรับเซิร์ฟเวอร์ผิดพลาด

นอกจากนี้การเขียนสคริปต์ Perl อย่างชาญฉลาดกลางคันบางอย่างจะช่วยให้คุณข้ามวนลูปในแพลตฟอร์มส่วนใหญ่เรียงลำดับผลลัพธ์และอาจมีราคาแพงมากสำหรับไดเรกทอรีขนาดใหญ่ การเรียงลำดับ ls ไม่จำเป็นที่นี่เนื่องจากสิ่งที่เราใส่ใจคือการนับ


1
จริงเกี่ยวกับ ls - ในสถานการณ์เช่นนี้ฉันกังวลมากขึ้นเกี่ยวกับความชัดเจนในสิ่งที่ฉันทำและไม่มากเกี่ยวกับการแสดง ฉันค่อนข้างแน่ใจว่าคุณสามารถใช้ echo $ line / * | wc -w แทน ls $ line | wc -l และคุณหลีกเลี่ยงปัญหาการเรียงลำดับของ ls
chris

ฉันเพิ่งทดสอบในไดเรกทอรีที่มีไฟล์นับล้านไฟล์และใช้เวลา 22 วินาทีและ echo * ใช้เวลา 12 วินาที (สำหรับบันทึกเสียงก้อง * ในเปลือกจะไม่ตี จำกัด หาเรื่องเพราะเสียงสะท้อนใน 99% ของเปลือกหอยในการใช้งานที่ใช้งานอยู่ในตัว)
คริส

ls -f จะไม่เรียงลำดับผลลัพธ์ การเรียงลำดับผลลัพธ์ไดเรกทอรีจะนำไปสู่ปัญหาทั่วไปของ NFS และไดเร็กทอรีขนาดใหญ่ หากเวลาในการอ่านและเรียงลำดับไดเรกทอรี (บนเซิร์ฟเวอร์) เกินกว่าการหมดเวลาของ NFS ไดเรกทอรีและไดเรกทอรีย่อยจะใช้ไม่ได้
mpez0

5

คุณสามารถใช้ตัวอย่างเล็ก ๆ น้อย ๆ นี้:

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

มันจะพิมพ์จำนวนไฟล์และไดเรกทอรีในแต่ละไดเรกทอรีในโฟลเดอร์ปัจจุบันที่มีผู้กระทำผิดที่ใหญ่ที่สุดที่ด้านล่าง มันจะช่วยคุณค้นหาไดเรกทอรีที่มีไฟล์จำนวนมาก ( ข้อมูลเพิ่มเติม )


สิ่งนี้ทำงานได้ดี
ptman

3

นี่ไม่ใช่คำตอบที่ตรงกับคำถามของคุณ แต่การค้นหาไฟล์ที่เพิ่งแก้ไขซึ่งมีขนาดเล็กโดยใช้การค้นหาอาจทำให้การค้นหาของคุณแคบลง:

find / -mmin -10 -size -20k

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

lsจะไม่ค้นหาไฟล์ที่ชื่อขึ้นต้นด้วยจุด การใช้findหลีกเลี่ยงสิ่งนี้ สิ่งนี้จะค้นหาทุกไฟล์ในแผนผังไดเรกทอรีหยุดการ basename จากจุดสิ้นสุดของแต่ละเส้นทางและนับจำนวนครั้งที่แต่ละเส้นทางไดเรกทอรีปรากฏในผลลัพธ์ผลลัพธ์ คุณอาจต้องใส่ "!" ในเครื่องหมายคำพูดหากเชลล์ของคุณบ่นเกี่ยวกับมัน

Inodes ยังสามารถใช้งานได้โดยไฟล์ที่ถูกลบ แต่ถูกระงับไว้โดยกระบวนการที่กำลังทำงานอยู่ หากแพคเกจ Munin นี้รวมถึงโปรแกรมที่ทำงานอยู่ตลอดเวลาสิ่งอื่นที่ควรตรวจสอบคือการเปิดไฟล์ไว้เป็นจำนวนปกติหรือไม่


inodes อาจถูกนำไปใช้โดยไดเรกทอรีที่ลึกมากซึ่งไม่สามารถหาได้ มีกรณีแปลก ๆ จำนวนหนึ่งอยู่ในนี้ แต่สถานการณ์ที่พบบ่อยที่สุดคือไดเรกทอรีที่เต็มไปด้วยไฟล์ที่มีชื่อปกติ
chris

3

ฉันจะเดรัจฉานบังคับนี้: เรียกใช้ tripwire บนอุปกรณ์ทั้งหมดสำหรับพื้นฐานแล้วเรียกใช้การตรวจสอบในภายหลังและไดเรกทอรีที่กระทำผิดจะโผล่ออกมาเหมือนนิ้วหัวแม่มือเจ็บ


ซึ่งอาจใช้เวลาเป็นพันล้านปี สิ่งที่รวดเร็วกว่าคือการใช้คำสั่ง lsof | grep DIR และค้นหาในแต่ละไดเรกทอรีเหล่านั้นเพื่อหาไฟล์ใหม่มากมาย
chris

2
ตกลงวิธีนี้: ค้นหา / | จัดเรียง> /tmp/find1.txt; ค้นหา / | จัดเรียง> /tmp/find2.txt; diff /tmp/find1.txt /tmp/find2.txt
Geoff Fritz

2

(ไม่สามารถแสดงความคิดเห็นได้รับเก่าจริง ๆ - นี่คือเพื่อ egorgry)

egorgry - ls -i พิมพ์หมายเลขไอโหนดสำหรับรายการไม่ใช่ inode COUNT

ลองใช้ไฟล์ในไดเรกทอรีของคุณคุณอาจจะเห็นจำนวนที่สูงพอ ๆ กัน แต่ไม่นับจำนวน inodes มันเป็นเพียง inode # ที่รายการไดเรกทอรีของคุณชี้ไป


ฮ่า ๆ. ฉันโหวตให้คุณหนึ่ง ขอบคุณสำหรับคำอธิบาย การใช้ inode ทำให้เกิดความสับสนอยู่เสมอ
egorgry

ขอบคุณตอนนี้ฉันกลัวที่จะแปลงนี้ในการแสดงความคิดเห็นบนโหนดของคุณในกรณีที่ฉันสูญเสียกรรมเมื่อฉันลบคำตอบนี้ :)
ไมค์กรัม

2

ปรับปรุง

ซับเดียวที่ส่งคืนจำนวนไอโหนดของชายด์แต่ละไดเร็กทอรีที่กำหนดด้วยรายการที่ใหญ่ที่สุดที่ด้านล่าง

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

เพื่อนับว่ามีการใช้งานกี่ inodes ภายใต้ [path]


1

ฉันพยายามเขียนเชลล์ไปป์ไลน์ที่มีประสิทธิภาพ แต่มันก็ไม่สะดวกและช้าหรือไม่ถูกต้องเช่น

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

จะแสดงรายการไดเรกทอรีใบไม้ (และบางรายการ) ที่มีไฟล์มากกว่า 1,000 ไฟล์ ดังนั้นนี่คือสคริปต์ Perl เพื่อให้มีประสิทธิภาพทั้งในเวลาและ RAM ผลผลิตก็เหมือนกัน

« files-in-subtree »« files-direct-in-directory »« directory-name »

เพื่อให้คุณสามารถนวดและกรองได้อย่างง่ายดายโดยใช้เครื่องมือปกติเช่น 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 inodes


3
ls -i พิมพ์หมายเลข inode สำหรับรายการไม่ใช่ inode COUNT ลองใช้ไฟล์ในไดเรกทอรีของคุณคุณอาจจะเห็นจำนวนที่สูงพอ ๆ กัน แต่ไม่นับจำนวน inodes มันเป็นเพียง inode # ที่รายการไดเรกทอรีของคุณชี้ไป
egorgry
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.