يتطلب مستوى: مبتدئ
القرص يقول No space left و df يقول فاضي؟ الحكاية في الـ inodes
لو السيرفر رفض يكتب ملف جديد وقالك No space left on device، وفتحت df -h لقيته فاضي، المشكلة مش في المساحة. أنت خلّصت الـ inodes. في السطور الجاية هتعرف تشخّص ده في أقل من دقيقة، وتحلّه، وتمنعه يرجع تاني.
المشكلة باختصار
القرص عندك فيه حاجتين منفصلتين، مش حاجة واحدة. فيه المساحة اللي بتخزّن محتوى الملفات، وفيه عدد خانات للملفات اسمها inodes. كل ملف بياخد خانة inode واحدة، مهما كان حجمه صغير. لو الخانات خلصت، أي ملف جديد بيفشل، حتى لو المساحة لسه نص فاضية. ده اللي بيخلّي df -h يطمّنك وdf -i يفضح المشكلة.
مثال يقرّب الصورة
تخيّل مكتبة كبيرة. فيه رفوف واسعة تكفي آلاف الكتب، دي المساحة. وفيه درج فهرسة فيه بطاقات، وكل كتاب لازم بطاقة فهرسة واحدة، دي الـ inodes. لو درج البطاقات خلص، مش هتقدر تضيف كتاب جديد، حتى لو الرفوف نص فاضية. الموظف هيقولك مفيش مكان، وهو يقصد مكان في الفهرس، مش على الرف. ده بالظبط اللي بيحصل مع السيرفر.
دلوقتي بالتعريف الدقيق: الـ inode تركيبة بيانات ثابتة الحجم على القرص، بتخزّن ميتاداتا الملف: الصلاحيات، المالك، الحجم، توقيتات التعديل، ومؤشرات لأماكن البيانات الفعلية على القرص. اسم الملف نفسه مش مخزّن جوّه الـ inode، هو مخزّن في الدليل (directory) اللي بيربط الاسم برقم الـ inode. وعدد الـ inodes بيتحدّد لحظة تهيئة نظام الملفات (mkfs) وبيفضل ثابت بعد كده.
ليه بيحصل أصلاً؟
في نظام ext4، القاعدة الافتراضية بتحجز inode واحد لكل 16 كيلوبايت تقريبًا من المساحة. يعني قرص 50 جيجا ممكن يكون عنده حوالي 3.2 مليون inode ثابتة. ده رقم كبير في الأحوال العادية، لكنه بيتبخّر بسرعة لو التطبيق بيولّد ملايين الملفات الصغيرة: جلسات PHP، ملفات كاش، لوجات مقطّعة، أو مجلد /tmp منسي بيتملّى كل يوم.
الافتراض هنا إن نظام ملفاتك ext4 أو ext3. لو XFS أو Btrfs، القصة مختلفة شوية، وهنرجعلها في آخر المقال.
إزاي تكتشفها في دقيقة
الأمر الأساسي: df -i. بيوريك عدد الـ inodes المستخدم والمتبقّي لكل نظام ملفات. دوّر على العمود IUse%، لو وصل 100% دي مشكلتك.
df -i /
# Filesystem Inodes IUsed IFree IUse% Mounted on
# /dev/sda1 3.2M 3.2M 0 100% /
بعد ما تتأكد، محتاج تعرف مين بياكل الـ inodes. الأمر ده بيجمّع الملفات حسب المجلد الأب ويرتّبهم تنازليًا، فبيوصّلك للمجلد المذنب على طول:
sudo find / -xdev -printf '%h\n' | sort | uniq -c | sort -rn | head -20
الحل خطوة بخطوة
- حدّد المجلد المذنب من الأمر اللي فوق، غالبًا كاش أو جلسات أو لوجات.
- احذف الملفات الزيادة بأمان. لو ملايين الملفات، الحذف على مستوى المجلد أسرع بكتير من الحذف ملف ملف.
- لو الملفات لسه محتاجينها، اضغطهم في أرشيف واحد بـ
tarبدل ما يفضلوا ملايين ملفات منفصلة. - امنع التكرار: فعّل تدوير اللوجات (
logrotate) وحطّ مهمةcronتنضّف الكاش دوريًا.
sudo find /var/www/app/cache -type f -mtime +7 -delete
# لو محتاج تزوّد عدد الـ inodes (تدميري، على قرص جديد فقط):
sudo mkfs.ext4 -N 10000000 /dev/sdb1
ركّز: mkfs بيمسح كل حاجة على القرص. متشغّلهوش غير على قرص جديد، أو بعد باكب كامل وانت متأكد 100%.
الـ trade-offs
حذف الملفات بيحل المشكلة فورًا وببلاش، لكنه علاج مؤقت لو السبب مستمر. تزويد عدد الـ inodes وقت التهيئة بيحل المشكلة جذريًا، لكن بتكلفة: كل inode بياخد مساحة (256 بايت في ext4). يعني لو حجزت 10 مليون inode زيادة، بتخسر تقريبًا 2.5 جيجا من القرص قبل ما تكتب أي ملف. المكسب: أمان من نفاد الخانات. الخسارة: مساحة مهدورة وإعادة تهيئة كاملة.
متى لا تشغّل بالك بده
لو السيرفر بيخزّن ملفات كبيرة وقليلة (فيديوهات، باكب، صور ديسك)، نسبة الـ inodes عندك هتفضل تحت 5% للأبد، ومش محتاج تعمل حاجة. المشكلة دي بتضرب أساسًا الأنظمة اللي بتولّد ملايين الملفات الصغيرة. كمان لو نظام ملفاتك XFS أو Btrfs، الاتنين بيخصّصوا inodes عند الحاجة، فسقف الـ inodes الثابت مش موجود عندهم من الأساس، بس بتكلفة تعقيد إداري أعلى شوية.
الخطوة التالية
افتح السيرفر دلوقتي وشغّل df -i. لو أي نظام ملفات عدّى 80% في العمود IUse%، حطّ عليه تنبيه من النهاردة قبل ما يوصل 100% ويوقّف الخدمة. السطر ده في مراقبتك أرخص بكتير من حادثة إنتاج الساعة 3 الفجر.