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

فایل حذف شده ولی فضای دیسک آزاد نشده؟ رفع مشکل با lsof در لینوکس

فهرست

اگر یک فایل بزرگ را با rm حذف کرده‌اید اما df -h هنوز فضای دیسک را پر نشان می‌دهد، معمولاً فایل واقعاً از دید فایل‌سیستم آزاد نشده است؛ یک پردازش هنوز File Descriptor آن را باز نگه داشته و بلوک‌های دیسک تا بسته‌شدن آخرین descriptor قابل استفاده مجدد نیستند. سریع‌ترین مسیر تشخیص روی Linux معمولاً sudo lsof +L1 است.

چرا با حذف فایل، فضای دیسک آزاد نمی‌شود؟

در Linux حذف یک نام فایل با unlink() الزاماً به معنی آزادشدن فوری داده‌های آن نیست. اگر آخرین لینک فایل حذف شده باشد ولی یک پردازش هنوز فایل را باز نگه داشته باشد، داده تا زمانی که آخرین File Descriptor بسته نشود روی دیسک باقی می‌ماند. این سناریو معمولاً برای فایل‌های لاگ بزرگ، Java، NGINX/Apache، دیتابیس‌ها و برنامه‌هایی رخ می‌دهد که فایل لاگ را برای مدت طولانی باز نگه می‌دارند.

به همین دلیل ممکن است du فایل حذف‌شده را نبیند، ولی df همچنان فضای مصرف‌شده را گزارش کند. اگر با lsof آشنایی ندارید، ابتدا راهنمای جامع نصب و استفاده از lsof در لینوکس را ببینید.

مرحله ۱: ابتدا واقعاً وضعیت فضای دیسک را بررسی کنید

df -h

پارتیشن پر را مشخص کنید. مثلاً اگر /var یا روت سرور نزدیک ۹۵ تا ۱۰۰ درصد است، سپس مصرف فایل‌های قابل‌مشاهده را با du بررسی کنید:

sudo du -xhd1 /var 2>/dev/null | sort -h

گزینه -x باعث می‌شود du از همان filesystem خارج نشود. اگر مجموع قابل‌مشاهده توسط du به‌وضوح کمتر از مصرف گزارش‌شده در df است، فایل حذف‌شده‌ای که هنوز باز است یکی از اولین مواردی است که باید بررسی شود.

مرحله ۲: فایل‌های حذف‌شده‌ای که هنوز باز هستند را با lsof پیدا کنید

sudo lsof +L1

گزینه +L1 فایل‌های باز با Link Count کمتر از ۱ را نشان می‌دهد؛ یعنی فایل‌هایی که نامشان حذف شده اما هنوز یک یا چند پردازش آن‌ها را باز نگه داشته‌اند. خروجی نمونه می‌تواند شبیه این باشد:

COMMAND   PID  USER   FD   TYPE DEVICE  SIZE/OFF NLINK NAME
nginx    1832  root  12w   REG  253,0   18.7G      0 /var/log/nginx/access.log (deleted)

ستون‌های مهم:

  • COMMAND: برنامه‌ای که فایل را باز نگه داشته است.
  • PID: شناسه پردازش.
  • FD: File Descriptor؛ مثلاً 12w یعنی descriptor شماره ۱۲ برای نوشتن باز است.
  • SIZE/OFF: اندازه یا offset مرتبط با فایل.
  • NLINK: در این سناریو معمولاً صفر است.
  • NAME: مسیر فایل که با (deleted) مشخص شده است.

مرحله ۳: قبل از هر کاری پردازش را دقیق شناسایی کنید

ps -fp 1832

اگر پردازش توسط systemd مدیریت می‌شود، وضعیت سرویس را هم بررسی کنید:

sudo systemctl status nginx

این مرحله مهم است چون بستن اشتباه یک PID می‌تواند سرویس وب، دیتابیس یا یک job مهم را قطع کند. در سرور تولیدی قبل از restart حتماً اثر downtime و وضعیت درخواست‌های فعال را در نظر بگیرید.

مرحله ۴: فضای دیسک را به روش امن آزاد کنید

راه ترجیحی این است که برنامه مالک File Descriptor را وادار کنید فایل را به‌صورت سالم ببندد. برای سرویس‌های systemd معمولاً restart کنترل‌شده امن‌تر از کشتن پردازش است:

sudo systemctl restart nginx

برای سرویس‌هایی که reload واقعی باعث reopen شدن log file می‌شود، reload می‌تواند downtime کمتری داشته باشد؛ اما این رفتار برای همه برنامه‌ها یکسان نیست و باید مستندات همان سرویس را بررسی کنید.

هشدار: به‌صورت پیش‌فرض سراغ kill -9 نروید. SIGKILL به پردازش فرصت shutdown تمیز، flush داده یا cleanup نمی‌دهد. مخصوصاً برای دیتابیس‌ها و برنامه‌های stateful ابتدا از stop/restart استاندارد سرویس استفاده کنید.

مرحله ۵: بعد از اصلاح، نتیجه را Verify کنید

sudo lsof +L1

df -h

فایل موردنظر باید دیگر در خروجی lsof +L1 دیده نشود و فضای آزاد در df -h افزایش پیدا کند. اگر همچنان دیسک پر است، مشکل دیگری وجود دارد.

اگر lsof +L1 چیزی نشان نداد، چه چیزهایی را بررسی کنیم؟

۱. تمام شدن inodeها

df -i

گاهی فضای بایتی آزاد است اما inodeها تمام شده‌اند؛ در این حالت ایجاد فایل جدید با خطای No space left on device شکست می‌خورد.

۲. تفاوت mount pointها

ممکن است du را روی مسیری اجرا کرده باشید که زیر آن mount جداگانه، bind mount یا filesystem دیگری وجود دارد. خروجی‌های findmnt و df -hT را کنار هم بررسی کنید.

۳. فایل‌های بزرگ واقعی

sudo find / -xdev -type f -size +1G -printf '%s %pn' 2>/dev/null | sort -n

این دستور فایل‌های بزرگ قابل‌مشاهده را روی همان filesystem پیدا می‌کند. برای آشنایی بیشتر با ابزارهای عملی سرور، مقاله دستورات مانیتورینگ سرورهای لینوکس هم مکمل خوبی است.

چطور از تکرار این مشکل جلوگیری کنیم؟

  • برای لاگ‌ها logrotate را درست تنظیم کنید و روش reopen/reload مناسب همان سرویس را استفاده کنید.
  • برای پارتیشن‌های مهم هشدار ۷۵، ۸۵ و ۹۵ درصد بگذارید.
  • قبل از حذف دستی فایل لاگ بزرگ بررسی کنید برنامه چگونه log rotation را مدیریت می‌کند.
  • روی VPSهای پرترافیک، رشد /var/log، لاگ کانتینرها و دیتابیس را جداگانه مانیتور کنید.

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

جمع‌بندی سریع

  1. df -h را برای تأیید پر بودن filesystem اجرا کنید.
  2. با du مصرف فایل‌های قابل‌مشاهده را مقایسه کنید.
  3. sudo lsof +L1 را برای فایل‌های حذف‌شده اما باز اجرا کنید.
  4. PID و سرویس مالک فایل را شناسایی کنید.
  5. سرویس را ترجیحاً به‌صورت graceful reload/restart کنید.
  6. با lsof +L1 و df -h نتیجه را دوباره Verify کنید.

سوالات متداول

چرا بعد از rm فضای دیسک در Linux آزاد نمی‌شود؟

اگر پردازشی فایل حذف‌شده را هنوز باز نگه داشته باشد، بلوک‌های آن تا زمان بسته‌شدن آخرین File Descriptor آزاد نمی‌شوند. در این حالت df مصرف را می‌بیند ولی du ممکن است فایل را نبیند.

دستور lsof +L1 چه چیزی نشان می‌دهد؟

فایل‌های باز با link count کمتر از یک را فهرست می‌کند و برای پیدا کردن فایل‌های حذف‌شده‌ای که هنوز توسط یک پردازش باز هستند بسیار کاربردی است.

برای آزاد کردن فضا باید پردازش را kill -9 کنیم؟

معمولاً نه. ابتدا پردازش و سرویس را شناسایی و از reload، restart یا shutdown استاندارد همان سرویس استفاده کنید. kill -9 باید آخرین گزینه و با آگاهی از خطر از دست رفتن داده یا قطع سرویس باشد.

اختلاف df و du همیشه به فایل حذف‌شده باز مربوط است؟

خیر. mount pointها، inodeها، reserved blocks، snapshotها و بعضی لایه‌های ذخیره‌سازی هم می‌توانند باعث اختلاف شوند. lsof +L1 یکی از اولین تست‌های سریع برای این سناریو است.

منابع

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

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

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