ค้นหาไดเรกทอรีที่มีไฟล์จำนวนมาก


33

ดังนั้นลูกค้าของฉันได้รับอีเมลจาก Linode ในวันนี้ว่าเซิร์ฟเวอร์ของพวกเขาทำให้บริการการสำรองข้อมูลของ Linode ระเบิด ทำไม? มีไฟล์มากเกินไป ฉันหัวเราะแล้ววิ่ง:

# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/xvda        2.5M  2.4M   91K   97% /

อึ. 2.4 ล้าน inodes ที่ใช้งานอยู่ มันเกิดอะไรขึ้นเนี่ย!

ฉันค้นหาผู้ต้องสงสัยที่เห็นได้ชัด ( /var/{log,cache}และไดเรกทอรีที่โฮสต์เว็บไซต์ทั้งหมดจาก) แต่ฉันไม่พบสิ่งที่น่าสงสัยจริงๆ อยู่ที่ไหนสักแห่งในสัตว์ร้ายตัวนี้ฉันแน่ใจว่ามีไดเรกทอรีที่มีไฟล์สองล้าน

สำหรับบริบทหนึ่งเซิร์ฟเวอร์ไม่ว่างของฉันใช้ไอดี 200k และเดสก์ท็อปของฉัน (การติดตั้งเก่าที่มีพื้นที่เก็บข้อมูลที่ใช้มากกว่า 4TB) เป็นเพียงล้านเท่านั้น มีปัญหา

ดังนั้นคำถามของฉันคือฉันจะหาปัญหาได้อย่างไร มีduinodes หรือไม่?



1
รัน vmstat -1 100 และแสดงให้เราเห็น ระวังจำนวนมากใน CS (การสลับบริบท) บางครั้งระบบไฟล์ที่ล้มเหลวสามารถทำให้ไอโหนดจำนวนมากผิดพลาดได้ หรืออาจถูกต้องตามกฎหมายมีไฟล์จำนวนมาก ลิงก์นี้ควรแจ้งให้คุณทราบเกี่ยวกับไฟล์และ inodes stackoverflow.com/questions/653096/howto-free-inode-usageคุณอาจต้องดูว่าอะไรคือสิ่งที่ทำงาน / เปิดด้วยคำสั่ง lsof
j0h

คำตอบ:


23

ตรวจสอบ/lost+foundในกรณีที่เกิดปัญหาดิสก์และตรวจพบขยะจำนวนมากในรูปแบบไฟล์แยกอาจผิดไป

ตรวจสอบiostatดูว่าบางแอปพลิเคชันยังคงสร้างไฟล์อย่างบ้าคลั่ง

find / -xdev -type d -size +100kจะบอกคุณว่ามีไดเรกทอรีที่ใช้พื้นที่ดิสก์มากกว่า 100kB หรือไม่ นั่นจะเป็นไดเรกทอรีที่มีไฟล์จำนวนมากหรือมีไฟล์จำนวนมากในอดีต คุณอาจต้องการปรับขนาดรูปร่าง

ฉันไม่คิดว่าจะมีการรวมตัวเลือกต่าง ๆ กับ GNU duเพื่อให้นับ 1 ต่อรายการไดเรกทอรี คุณสามารถทำได้โดยสร้างรายการไฟล์ด้วยfindและนับจำนวนเล็กน้อยใน awk นี่คือduสำหรับ inodes ทดสอบน้อยที่สุดไม่พยายามจัดการกับชื่อไฟล์ที่มีบรรทัดใหม่

#!/bin/sh
find "$@" -xdev -depth | awk '{
    depth = $0; gsub(/[^\/]/, "", depth); depth = length(depth);
    if (depth < previous_depth) {
       # A non-empty directory: its predecessor was one of its files
       total[depth] += total[previous_depth];
       print total[previous_depth] + 1, $0;
       total[previous_depth] = 0;
    }
    ++total[depth];
    previous_depth = depth;
}
END { print total[0], "total"; }'

การใช้งาน: du-inodes /. พิมพ์รายการของไดเรกทอรีที่ไม่ว่างโดยมีจำนวนทั้งหมดของรายการในไดเรกทอรีเหล่านั้นและไดเรกทอรีย่อยซ้ำ เปลี่ยนทิศทางเอาต์พุตไปยังไฟล์และตรวจสอบในเวลาว่างของคุณ sort -k1nr <root.du-inodes | headจะบอกคุณถึงผู้กระทำผิดที่ใหญ่ที่สุด


สคริปต์ให้ข้อผิดพลาด:awk: line 2: find: regular expression compile failed (bad class -- [], [^] or [) [^ awk: line 2: syntax error at or near ] `/tmp/tmpw99dhs': Permission denied
Radu Rădeanu

@ RaduRădeanuอ่าฉันเข้าใจแล้วฉันใช้ความผิดปกติที่ไม่ได้ผลกับรุ่นอื่น ฉันได้เพิ่มแบ็กสแลชซึ่งฉันคิดว่าจำเป็นสำหรับ POSIX
Gilles 'หยุดความชั่วร้าย'

14

คุณสามารถตรวจสอบกับสคริปต์นี้:

#!/bin/bash

if [ $# -ne 1 ];then
  echo "Usage: `basename $0` DIRECTORY"
  exit 1
fi

echo "Wait a moment if you want a good top of the bushy folders..."

find "$@" -type d -print0 2>/dev/null | while IFS= read -r -d '' file; do 
    echo -e `ls -A "$file" 2>/dev/null | wc -l` "files in:\t $file"
done | sort -nr | head | awk '{print NR".", "\t", $0}'

exit 0

สิ่งนี้จะพิมพ์ไดเรกทอรีย่อย 10 อันดับแรกตามจำนวนไฟล์ หากคุณต้องการ x สูงสุดเปลี่ยนheadด้วย head -n xที่ไหนxจำนวนธรรมชาติมีค่ามากกว่า 0

เพื่อผลลัพธ์ที่แน่ใจ 100% รันสคริปต์นี้ด้วยสิทธิ์พิเศษ:

บนพวงโฟลเดอร์


2019: ฟื้นคืนชีพขึ้นมา10: read: Illegal option -d... ขัด-dธงชาติโดยreadหวังว่าจะไม่มีอะไรเลวร้ายเกิดขึ้น จะแจ้งให้คุณทราบเมื่อวิ่งเสร็จ ...
วิลเลียมส์

3

บ่อยครั้งที่เร็วกว่าการค้นหาหากฐานข้อมูลการค้นหาของคุณเป็นรุ่นล่าสุด:

# locate '' | sed 's|/[^/]*$|/|g' | sort | uniq -c | sort -n | tee filesperdirectory.txt | tail

สิ่งนี้จะลบฐานข้อมูลการค้นหาทั้งหมดดึงทุกสิ่งที่ผ่าน '/' สุดท้ายในเส้นทางจากนั้นเรียงลำดับและ "uniq -c" ทำให้คุณได้รับจำนวนไฟล์ / ไดเรกทอรีต่อไดเรกทอรี "sort -n" ไปยังหางเพื่อให้คุณได้รับสิบไดเรกทอรีที่มีสิ่งต่าง ๆ มากที่สุดในพวกเขา


+1: การใช้ฐานข้อมูลค้นหาเป็นแนวคิดที่ดีมาก!
Max Beikirch

เมื่อคุณไม่สามารถใช้การค้นหาไม่ว่าด้วยเหตุผลใดก็ตามให้เรียกใช้find /path/to/parent -xdev > filelistก่อนแล้วจึงสั่งให้อ่านข้อมูลจากรายการนั้น
gerrit

1

แนะนำอีกอย่าง:

http://www.iasptk.com/20314-ubuntu-find-large-files-fast-from-command-line

ใช้การค้นหาเหล่านี้เพื่อค้นหาไฟล์ที่ใหญ่ที่สุดบนเซิร์ฟเวอร์ของคุณ

ค้นหาไฟล์มากกว่า 1GB

sudo find / -type f -size + 1000000k -exec ls -lh {} \;

ค้นหาไฟล์มากกว่า 100MB

sudo find / -type f -size + 100000k -exec ls -lh {} \;

ค้นหาไฟล์ที่มีขนาดเกิน 10MB

sudo find / -type f -size + 10,000k -exec ls -lh {} \;

ส่วนแรกคือคำสั่ง find โดยใช้แฟล็ก "-size" เพื่อค้นหาไฟล์ที่มีขนาดแตกต่างกันวัดเป็นกิโลไบต์

บิตสุดท้ายของการเริ่มต้นด้วย "-exec" อนุญาตให้ระบุคำสั่งที่เราต้องการเรียกใช้งานในแต่ละไฟล์ที่เราค้นหา นี่คือคำสั่ง "ls -lh" เพื่อรวมข้อมูลทั้งหมดที่เห็นเมื่อแสดงรายการเนื้อหาของไดเรกทอรี h ไปยังจุดสิ้นสุดมีประโยชน์อย่างยิ่งเนื่องจากมันพิมพ์ขนาดของแต่ละไฟล์ในรูปแบบที่มนุษย์อ่านได้


2
ปัญหาของเขาคือการใช้งาน inode สูงซึ่งชี้ไปที่ไฟล์ขนาดเล็กจำนวนมากไม่ใช่ไฟล์ขนาดใหญ่
UpTheCreek

0

สิ่งนี้ใช้ได้ผลสำหรับฉันเมื่อสิ่งอื่นล้มเหลวบน Android ผ่านเชลล์:

find / -type d -exec sh -c "fc=\$(find '{}' -type f | wc -l); echo -e \"\$fc\t{}\"" \; | sort -nr | head -n25

0

ฉันชอบใช้สิ่งที่ต้องการdu --inodes -d 1ค้นหาไดเรกทอรีที่วนซ้ำหรือมีไฟล์จำนวนมากโดยตรง

ฉันชอบคำตอบนี้: https://unix.stackexchange.com/a/123052

สำหรับคนขี้เกียจของเรานี่คือส่วนสำคัญของมัน:

du --inodes -S | sort -rh | sed -n \
    '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.