ความเป็นมา: ฟิสิคัลเซิร์ฟเวอร์อายุประมาณสองปีไดรฟ์ SATA 7200-RPM เชื่อมต่อกับการ์ด RAID 3Ware, ext3 FS ที่ติดตั้งในเวลากลางวันและข้อมูล = สั่งไม่อยู่ภายใต้การโหลดที่บ้าคลั่งเคอร์เนล 2.6.18-92.1.22.el5, uptime 545 วัน . ไดเรกทอรีไม่มีไดเรกทอรีย่อยใด ๆ มีเพียงไฟล์เล็ก ๆ (~ 100 byte) หลายล้านไฟล์และบางอันก็มีขนาดใหญ่กว่า (ไม่กี่ KB)
เรามีเซิร์ฟเวอร์ที่มีนกกาเหว่าอยู่เล็กน้อยในช่วงสองสามเดือนที่ผ่านมา แต่เราสังเกตเห็นเพียงวันเดียวเมื่อมันเริ่มไม่สามารถเขียนไปยังไดเรกทอรีได้เนื่องจากมันมีไฟล์มากเกินไป มันเริ่มโยนข้อผิดพลาดนี้ใน / var / log / messages:
ext3_dx_add_entry: Directory index full!
ดิสก์ที่สงสัยมีจำนวนไอโหนดเหลืออยู่:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
ดังนั้นฉันเดาว่านั่นหมายความว่าเรามีขีด จำกัด จำนวนรายการที่สามารถอยู่ในไฟล์ไดเรกทอรีได้ ไม่ทราบว่าจะมีไฟล์กี่ไฟล์ แต่จะไม่เป็นเช่นนั้นเท่าที่คุณจะเห็นมากกว่าสามล้านหรือมากกว่านั้น ไม่ว่าจะเป็นสิ่งที่ดีใจคุณ! แต่นั่นเป็นส่วนหนึ่งของคำถามของฉัน: ขีด จำกัด บนนั้นคืออะไร? ปรับได้ไหม ก่อนที่ผมจะได้รับการตะโกนใส่ฉันต้องการที่จะปรับมันลง ; ไดเรกทอรีมหาศาลนี้ทำให้เกิดปัญหาทุกประเภท
อย่างไรก็ตามเราติดตามปัญหาในรหัสที่สร้างไฟล์เหล่านั้นทั้งหมดและเราได้ทำการแก้ไขแล้ว ตอนนี้ฉันติดอยู่กับการลบไดเรกทอรี
ตัวเลือกที่นี่:
rm -rf (dir)
ฉันลองสิ่งนี้ก่อน ฉันยอมแพ้และฆ่ามันหลังจากมันวิ่งไปหนึ่งวันครึ่งโดยไม่มีผลกระทบใด ๆ
- ยกเลิกการเชื่อมโยง (2) ในไดเรกทอรี: การพิจารณาที่คุ้มค่าแน่นอน แต่คำถามคือการลบไฟล์ในไดเรกทอรีด้วย fsck เร็วกว่าการลบผ่านการยกเลิกการเชื่อมโยง (2) นั่นคือวิธีใดวิธีหนึ่งฉันต้องทำเครื่องหมาย inodes เหล่านั้นว่าไม่ได้ใช้ นี้ถือว่าแน่นอนว่าฉันสามารถบอก fsck ที่จะไม่ปล่อยรายการไปยังไฟล์ใน / หายไป + พบ; มิฉะนั้นฉันเพิ่งย้ายปัญหาของฉัน นอกเหนือจากความกังวลอื่น ๆ ทั้งหมดหลังจากอ่านเกี่ยวกับเรื่องนี้อีกเล็กน้อยปรากฏว่าฉันอาจต้องเรียกฟังก์ชั่น FS ภายในบางอย่างเนื่องจากไม่มีตัวแปร unlink (2) ที่ฉันสามารถหาได้ ไดเรกทอรีที่มีรายการอยู่ในนั้น ฮี้
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
อันที่จริงนี่เป็นเวอร์ชั่นย่อ ตัวจริงที่ฉันใช้อยู่ซึ่งเพิ่งเพิ่มการรายงานความคืบหน้าและการหยุดแบบคลีนเมื่อเราเรียกใช้ไฟล์ที่ไม่ได้ลบคือ:
ส่งออก i = 0; เวลา (ในขณะที่ [จริง]; ทำ ls -Uf | หัว -n 3 | grep -qF '.png' || หยุดพัก; ls -Uf | หัว -n 10000 | xargs rm -f 2> / dev / null; ส่งออก i = $ (($ i + 10,000)); echo "$ i ... "; เสร็จสิ้น)
ดูเหมือนว่าจะทำงานได้ดี เมื่อฉันเขียนสิ่งนี้มันได้ลบไฟล์ 260,000 ไฟล์ในสามสิบนาทีที่ผ่านมา
- ดังกล่าวข้างต้นขีด จำกัด รายการต่อไดเรกทอรีสามารถปรับได้หรือไม่
- เหตุใดจึงใช้ "ของจริง 7m9.561s / ผู้ใช้ 0m0.001s / sys 0m0.001s" เพื่อลบไฟล์เดียวซึ่งเป็นไฟล์แรกในรายการที่ส่งคืนโดย
ls -U
อาจใช้เวลาสิบนาทีในการลบ 10,000 รายการแรกที่มี คำสั่งใน # 3 แต่ตอนนี้มันลากอย่างมีความสุข? สำหรับเรื่องนั้นมันถูกลบ 260,000 ในเวลาประมาณสามสิบนาที แต่ตอนนี้ใช้เวลาอีกสิบห้านาทีเพื่อลบอีก 60,000 ทำไมการแกว่งตัวครั้งใหญ่ในความเร็ว? - มีวิธีที่ดีกว่าในการทำสิ่งนี้หรือไม่? ไม่เก็บไฟล์นับล้านไฟล์ในไดเรกทอรี ฉันรู้ว่ามันโง่และมันจะไม่เกิดขึ้นกับนาฬิกาของฉัน Googling ปัญหาและการค้นหาผ่าน SF และ SO มีการเปลี่ยนแปลงมากมาย
find
ที่ไม่ได้เร็วกว่าวิธีของฉันอย่างเห็นได้ชัดด้วยเหตุผลหลายประการ แต่แนวคิดการลบผ่าน fsck มีขาบ้างหรือไม่ หรืออย่างอื่นอย่างสิ้นเชิง? ฉันกระตือรือร้นที่จะได้ยินความคิดนอกกรอบ (หรือภายในกล่องที่ไม่เป็นที่รู้จัก)
เอาต์พุตสคริปต์สุดท้าย!:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
ดังนั้นไฟล์สามล้านไฟล์จึงถูกลบภายในเวลาไม่เกินสี่ชั่วโมง
rm -rfv | pv -l >/dev/null
. pv ควรพร้อมใช้งานในที่เก็บEPEL