ESC را فشار دهید تا بسته شود

رفع خطای No space left on device در لینوکس وقتی دیسک خالی است

فهرست

اگر روی Linux یا VPS با خطای No space left on device روبه‌رو شده‌اید اما df -h هنوز فضای خالی نشان می‌دهد، یکی از محتمل‌ترین علت‌ها پر شدن inodeهاست. در این حالت ظرفیت بلوکی فایل‌سیستم تمام نشده، اما تعداد inode قابل‌استفاده به صفر رسیده و سیستم دیگر نمی‌تواند فایل یا دایرکتوری جدید بسازد. سریع‌ترین تشخیص، مقایسه df -h با df -i است.

خلاصه سریع: وقتی دیسک خالی است ولی No space left می‌گیرید

df -hT
df -i

اگر ستون IUse% برای فایل‌سیستم مشکل‌دار روی 100% باشد، مسئله inode exhaustion است، نه کمبود گیگابایت.

نمونه:

Filesystem     Inodes   IUsed IFree IUse% Mounted on
/dev/vda1      655360  655360     0  100% /

در این وضعیت باید مسیرهایی را پیدا کنید که تعداد بسیار زیادی فایل کوچک ساخته‌اند، علت تولید آن فایل‌ها را متوقف کنید، پاک‌سازی کنترل‌شده انجام دهید و در پایان دوباره df -i را Verify کنید.

inode چیست و چرا می‌تواند قبل از فضای دیسک تمام شود؟

در فایل‌سیستم‌های لینوکسی هر فایل و دایرکتوری یک inode دارد که متادیتاهایی مثل مالک، مجوزها، زمان‌ها و اشاره‌گرهای داده را نگه می‌دارد. بنابراین حتی یک فایل 1KB هم یک inode مصرف می‌کند. اگر یک سرویس میلیون‌ها فایل کوچک بسازد، ممکن است inodeها زودتر از بلوک‌های دیسک تمام شوند.

این سناریو معمولاً در این موارد دیده می‌شود:

  • Sessionهای PHP یا Cache که به‌صورت فایل ذخیره می‌شوند؛
  • Mail queue یا Spam queue بزرگ؛
  • Cacheهای WordPress، Composer، npm یا package manager؛
  • Thumbnailها و فایل‌های موقت؛
  • دایرکتوری‌هایی با تعداد بسیار زیاد لاگ چرخشی یا فایل خطا؛
  • Job یا اسکریپتی که فایل‌های کوچک را بدون Cleanup می‌سازد؛
  • کانتینر یا سرویس معیوب که فایل‌های موقت را پیوسته تولید می‌کند.

مرحله 1: اول فرق Disk Full و Inode Full را ثابت کنید

ابتدا مصرف بلوک‌ها را بررسی کنید:

df -hT

سپس inodeها را ببینید:

df -i

اگر df -h مثلاً 55% Usage نشان می‌دهد اما df -i روی 100% است، علت اصلی inode است.

اگر هر دو روی 100% هستند، باید هم فضای بلوکی و هم تعداد فایل‌ها را مدیریت کنید. اگر فقط df -h پر است، این مقاله مسیر اصلی شما نیست؛ برای نمونه اگر Docker logها رشد کرده‌اند، راهنمای جلوگیری از پر شدن دیسک VPS با لاگ Docker و تنظیم Log Rotation را ببینید.

اگر df -i هم طبیعی بود چه چیزهایی را بررسی کنیم؟

اگر df -h فضای خالی نشان می‌دهد و df -i هم پر نیست، هنوز چند علت رایج دیگر برای خطای No space left on device یا ENOSPC وجود دارد. قبل از پاک کردن فایل‌ها، این موارد را بررسی کنید:

  • پر شدن tmpfs: مسیرهایی مثل /run، /tmp یا /dev/shm ممکن است فایل‌سیستم جداگانه و محدود داشته باشند. با دستورهای زیر وضعیت آن‌ها را ببینید:
    df -h /run /tmp /dev/shm 2>/dev/null
    df -i /run /tmp /dev/shm 2>/dev/null
    
  • فایل حذف‌شده ولی هنوز باز: اگر برنامه‌ای فایل بزرگی را باز نگه داشته باشد، حذف نام فایل لزوماً فضا را فوراً آزاد نمی‌کند. بررسی کنید:
    sudo lsof +L1
    

    اگر خروجی دارید، سرویس مالک فایل را شناسایی و به‌صورت کنترل‌شده reload یا restart کنید.

  • Quota: ممکن است خود filesystem فضا داشته باشد اما سهمیه کاربر یا گروه تمام شده باشد. در سیستم‌هایی که quota فعال است:
    quota -s
    sudo repquota -a
    

اگر هیچ‌کدام از این موارد مشکل را توضیح ندادند، با findmnt -T /path مطمئن شوید همان Mount Pointای را بررسی می‌کنید که برنامه روی آن می‌نویسد.

مرحله 2: مشخص کنید کدام Mount Point مشکل دارد

خروجی را محدود کنید:

df -i /
df -i /var
df -i /home

اگر /var فایل‌سیستم جداگانه‌ای دارد، ممکن است فقط همان Mount پر شده باشد. این نکته مهم است چون باید جست‌وجو را روی همان filesystem نگه دارید.

برای دیدن mountها:

findmnt

مرحله 3: دایرکتوری‌های پر از فایل را پیدا کنید

یک روش سریع برای شروع:

sudo find /var -xdev -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -n | tail -n 30

این دستور تعداد entryها را بر اساس parent directory جمع می‌کند و به شما نشان می‌دهد کدام مسیرها حجم زیادی از تعداد فایل را ساخته‌اند.

اگر مشکل روی root filesystem است:

sudo find / -xdev -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -n | tail -n 30

نکته: روی سرور Production این دستور می‌تواند I/O ایجاد کند. آن را در زمان مناسب اجرا کنید و اگر میلیون‌ها فایل دارید، از scope کوچک‌تر مثل /var یا /home شروع کنید.

مرحله 4: تعداد فایل را در مسیرهای مشکوک دقیق‌تر بررسی کنید

مثلاً برای Sessionهای PHP:

sudo find /var/lib/php/sessions -xdev -type f | wc -l

برای یک Cache:

sudo find /var/cache -xdev -type f | wc -l

و برای دایرکتوری خاص سایت:

sudo find /var/www/example.com -xdev -type f | wc -l

اگر عددها غیرعادی‌اند، قبل از حذف، چند فایل نمونه و زمان آن‌ها را ببینید:

sudo find /path/to/suspect -xdev -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort | head
sudo find /path/to/suspect -xdev -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort | tail

مرحله 5: علت تولید فایل‌ها را قبل از Cleanup پیدا کنید

پاک کردن فایل‌ها بدون اصلاح علت، معمولاً فقط چند ساعت یا چند روز مشکل را عقب می‌اندازد.

بررسی کنید:

systemctl --failed
journalctl -p warning -n 200 --no-pager

اگر فایل‌ها توسط یک سرویس مشخص ساخته می‌شوند:

systemctl status SERVICE --no-pager
journalctl -u SERVICE -n 200 --no-pager

برای Cron:

systemctl status cron --no-pager 2>/dev/null || systemctl status crond --no-pager

اگر فایل‌های Docker یا runtime باعث رشد شده‌اند، منبع تولید را در خود سرویس یا کانتینر اصلاح کنید.

مرحله 6: Cleanup را امن و کنترل‌شده انجام دهید

هیچ‌وقت فقط به‌خاطر inode full دستورهای عمومی مثل rm -rf /tmp/* یا حذف کورکورانه Cache اجرا نکنید. ابتدا مشخص کنید چه فایل‌هایی هستند، چه سرویسی آن‌ها را می‌سازد و Retention مجاز چیست.

نمونه برای حذف فایل‌های موقت قدیمی‌تر از 7 روز، فقط پس از Verify مسیر:

sudo find /path/to/temp -xdev -type f -mtime +7 -print

ابتدا فقط لیست را ببینید. اگر صحیح بود:

sudo find /path/to/temp -xdev -type f -mtime +7 -delete

برای Cache اپلیکیشن بهتر است از ابزار رسمی همان برنامه استفاده کنید؛ چون حذف مستقیم فایل می‌تواند باعث lock، corruption یا cache stampede شود.

چرا حذف هزاران فایل با rm ممکن است کند باشد؟

وقتی یک دایرکتوری میلیون‌ها فایل دارد، عملیات shell ممکن است کند شود یا به سقف argument برسد. به‌جای:

rm -f /path/*

از find ... -delete استفاده کنید:

sudo find /path -xdev -type f -mtime +7 -delete

یا در batch:

sudo find /path -xdev -type f -mtime +7 -print0 | xargs -0 -r -n 1000 rm -f

مرحله 7: بعد از Cleanup حتماً Verify کنید

بعد از حذف کنترل‌شده:

df -i
df -hT

باید مقدار IFree از صفر خارج شده و IUse% کاهش پیدا کرده باشد.

سپس تست واقعی بسازید:

touch /tmp/inode-test
ls -l /tmp/inode-test
rm -f /tmp/inode-test

اگر فایل بدون خطای ENOSPC ساخته شد، مسیر Recovery موفق بوده است.

اگر فایل حذف شده ولی inode آزاد نمی‌شود چه؟

در بیشتر فایل‌سیستم‌ها inode پس از حذف آخرین link و بسته‌شدن آخرین file descriptor آزاد می‌شود. اگر فایل حذف شده ولی یک process هنوز آن را باز نگه داشته باشد، باید process مربوط را پیدا کنید. این سناریو با inode exhaustion کلاسیک فرق دارد. راهنمای رفع مشکل فایل حذف‌شده ولی آزاد نشدن فضای دیسک با lsof را اجرا کنید.

پیشگیری: چطور دوباره inode تمام نشود؟

  • برای IUse% مانیتورینگ و Alert بسازید؛ فقط Disk GB را مانیتور نکنید.
  • Retention فایل‌های موقت، Session و Cache را مشخص کنید.
  • Jobهای Cleanup را با گزارش و Exit Code واقعی اجرا کنید.
  • دایرکتوری‌های دارای صدها هزار فایل را شناسایی و Application Design را بازبینی کنید.
  • برای workloadهای تولید فایل بسیار زیاد، فایل‌سیستم و پارامترهای ساخت آن را متناسب انتخاب کنید.
  • از Snapshot/Backup قبل از Cleanupهای بزرگ استفاده کنید.

نمونه Monitoring ساده:

df -iP | awk 'NR>1 {gsub("%","",$5); if ($5 >= 85) print "WARN inode usage:", $0}'

آیا می‌توان تعداد inodeهای ext4 را بعداً زیاد کرد؟

در ext4 تعداد inodeها هنگام ساخت filesystem تعیین می‌شود و افزایش مستقیم تعداد inode روی همان filesystem معمولاً مانند افزایش ساده حجم پارتیشن نیست. اگر workload دائماً تعداد فایل بسیار بالایی دارد، راه استاندارد این است که Backup معتبر داشته باشید، filesystem جدید را با پارامتر مناسب بسازید و داده را Migration کنید.

قبل از هر تغییر ساختاری:

lsblk -f
findmnt
df -hT
df -i

و از Backup قابل بازیابی مطمئن شوید.

Rollback و Recovery Plan

اگر Cleanup باعث اختلال شد:

  1. Job یا سرویس تولیدکننده فایل را موقتاً متوقف کنید.
  2. اگر Snapshot یا Backup دارید، فقط داده لازم را Restore کنید.
  3. مجوزها و مالکیت مسیر را Verify کنید:
    namei -l /path/to/app
    stat /path/to/app
    
  4. سرویس را مرحله‌ای بالا بیاورید و Log را دنبال کنید:
    systemctl restart SERVICE
    journalctl -u SERVICE -f
    
  5. دوباره df -i و رفتار برنامه را بررسی کنید.

چک‌لیست نهایی عیب‌یابی inode

df -hT
df -i
findmnt
sudo find /var -xdev -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -n | tail -n 30
systemctl --failed
journalctl -p warning -n 200 --no-pager
df -i
touch /tmp/inode-test && rm -f /tmp/inode-test

اگر روی VPS Production کار می‌کنید و برای سرویس‌های چندسایتی، Cache، Queue یا workloadهای فایل‌محور به منابع و Storage قابل ارتقا نیاز دارید، مشخصات سرور مجازی وان‌سرور را می‌توانید متناسب با ظرفیت و نوع کاربرد بررسی کنید.

جمع‌بندی

خطای No space left on device همیشه به معنی پر شدن گیگابایت دیسک نیست. وقتی df -h فضای خالی دارد ولی df -i روی 100% است، فایل‌سیستم inode آزاد ندارد. مسیر درست این است که اول filesystem مشکل‌دار را مشخص کنید، مسیرهای دارای تعداد بسیار زیاد فایل را پیدا کنید، علت تولید فایل‌ها را متوقف کنید، Cleanup کنترل‌شده انجام دهید و در پایان با df -i و ساخت یک فایل تست نتیجه را Verify کنید.

منابع فنی

Rate this post
اشتراک گذاری نوشته در:

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *