رفع مشکل

دیسک سرور پر شده (No space left on device)؛ پیدا کردن عامل و آزادسازی فضا

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۷ دقیقه

100%Nospaceleftرفع مشکلدیسک سرور پر شده (Nospace left on device)؛ پیداکردن عامل و آزادسازی فضامجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

وقتی دیسک سرور پر می‌شود، دیتابیس، وب‌سرور و حتی ورود SSH دچار خطا می‌شوند. ابتدا با df -h ببینید کدام پارتیشن پر است و با df -i پر شدن inode را رد کنید. سپس با du یا ncdu پوشه‌های حجیم را پیدا کنید. مقصران رایج لاگ‌ها، journald، ایمیج‌ها و لاگ‌های داکر، کش apt و بکاپ‌های قدیمی هستند. فایل لاگ در حال استفاده را truncate کنید نه حذف، و در پایان با logrotate و محدودیت journald جلوی تکرار را بگیرید.

علائم پر شدن دیسک

پر شدن دیسک معمولاً بی‌سروصدا اتفاق می‌افتد و ناگهان چند سرویس با هم خطا می‌دهند. نشانه‌های رایج:

  • پیام No space left on device هنگام ذخیرهٔ فایل، نصب بسته یا اجرای apt؛
  • توقف دیتابیس MySQL یا PostgreSQL و خطای نوشتن؛
  • خطای ۵۰۰ یا ۵۰۲ در سایت، چون PHP یا برنامه نمی‌تواند فایل موقت یا نشست بسازد؛
  • کند شدن یا شکست ورود SSH و کار نکردن تکمیل خودکار در bash؛
  • توقف کانتینرهای داکر یا شکست ساخت ایمیج.

اولین قدم این است که مطمئن شوید واقعاً فضا تمام شده و بفهمید کدام پارتیشن پر است. آرام باشید و پیش از پاک کردن هر چیز، ابتدا عامل را پیدا کنید؛ حذف عجولانه می‌تواند خسارتی بزرگ‌تر از خود مشکل بزند.

روند عیب‌یابی دیسک پر
  1. df -h و df -i

    پارتیشن پر را پیدا کنید و پر شدن inode را رد کنید.

  2. du یا ncdu

    از ریشه پایین بروید تا پوشهٔ حجیم را پیدا کنید.

  3. پاک‌سازی امن

    لاگ‌ها را truncate کنید، journald و کش apt و داکر را مرتب کنید.

  4. lsof +L1

    اگر فضا آزاد نشد، فایل‌های حذف‌شدهٔ باز را پیدا و سرویس را ری‌استارت کنید.

  5. پیشگیری

    logrotate، محدودیت لاگ داکر و هشدار دیسک را تنظیم کنید.

شکل ۱ اول پیدا کنید، بعد پاک کنید؛ و در پایان جلوی تکرار را بگیرید.

اقدام فوری وقتی سرویس‌ها از کار افتاده‌اند

اگر سایت یا ربات همین حالا از دسترس خارج شده و فرصت بررسی دقیق ندارید، ابتدا با کم‌خطرترین کارها کمی فضا آزاد کنید تا سرویس‌ها دوباره بالا بیایند و سپس با آرامش عیب‌یابی را ادامه دهید. سه اقدام سریع و تقریباً بی‌خطر این‌هاست: پاک کردن کش apt با sudo apt clean، محدود کردن ژورنال با sudo journalctl --vacuum-size=100M و خالی کردن بزرگ‌ترین فایل لاگی که می‌شناسید با truncate. معمولاً همین چند قدم چند صد مگابایت فضا آزاد می‌کند.

اگر SSH هم به‌سختی وصل می‌شود، از کنسول وب ارائه‌دهندهٔ سرور وارد شوید. بعد از آزاد شدن فضا، سرویس‌هایی را که متوقف شده‌اند (مثلاً دیتابیس) با systemctl restart دوباره اجرا کنید و لاگ‌شان را بررسی کنید تا مطمئن شوید هنگام پر بودن دیسک آسیبی به داده‌ها نرسیده است.

گام ۱: کدام پارتیشن پر است؟

df -h

در خروجی، ستون Use% و Mounted on را نگاه کنید. معمولاً پارتیشن ریشه (/) مشکل دارد، اما اگر پارتیشن جداگانه‌ای برای /var یا /home دارید، همان را بررسی کنید.

حالت دوم که کمتر شناخته شده، تمام شدن inode است. هر فایل، هر قدر هم کوچک باشد، یک inode مصرف می‌کند. اگر میلیون‌ها فایل کوچک (مثلاً فایل‌های نشست PHP یا کش) ساخته شده باشد، ممکن است فضای خالی دیسک زیاد باشد ولی همچنان خطای No space بگیرید:

df -i

اگر IUse% نزدیک به پر بود، باید پوشه‌ای را پیدا کنید که تعداد فایل زیادی دارد (در گام ۴ توضیح می‌دهیم).

گام ۲: پیدا کردن پوشه‌های حجیم

ابزار du حجم پوشه‌ها را می‌شمارد. از ریشه شروع کنید و قدم‌به‌قدم پایین بروید:

sudo du -xh --max-depth=1 / 2>/dev/null | sort -h | tail -n 15
sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail -n 15

گزینهٔ -x باعث می‌شود du وارد پارتیشن‌های دیگر نشود و فقط همان دیسک را بشمارد. ابزار تعاملی ncdu این کار را بسیار راحت‌تر می‌کند؛ با کلیدهای جهت در پوشه‌ها حرکت می‌کنید و می‌بینید هرکدام چقدر فضا گرفته است:

sudo apt install -y ncdu
sudo ncdu -x /

برای پیدا کردن فایل‌های بزرگ به‌طور مستقیم:

sudo find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null

گام ۳: مقصران همیشگی و پاک‌سازی امن

لاگ‌های سیستم و برنامه‌ها

پوشهٔ /var/log بزرگ‌ترین مشکوک است؛ به‌خصوص وقتی برنامه‌ای پشت سر هم خطا می‌دهد و لاگ را پر می‌کند. فایل لاگی را که برنامه در حال نوشتن روی آن است با rm حذف نکنید؛ چون فضای آن تا ری‌استارت برنامه آزاد نمی‌شود (گام ۵). به‌جای حذف، محتوایش را خالی کنید:

sudo truncate -s 0 /var/log/nginx/error.log

و حتماً علت پر شدن لاگ را هم پیدا کنید؛ لاگی که در چند ساعت چند گیگابایت می‌شود، نشانهٔ خطای تکرارشونده‌ای است که باید رفع شود.

ژورنال systemd

journald می‌تواند به‌مرور فضای زیادی بگیرد. حجم فعلی را ببینید و محدودش کنید:

journalctl --disk-usage
sudo journalctl --vacuum-size=200M

برای دائمی کردن محدودیت، در فایل /etc/systemd/journald.conf مقدار SystemMaxUse=200M را تنظیم و سرویس systemd-journald را ری‌استارت کنید.

کش بسته‌ها و کرنل‌های قدیمی

sudo apt clean
sudo apt autoremove --purge

داکر

داکر یکی از بزرگ‌ترین مصرف‌کنندگان فضا روی سرورهای امروزی است: ایمیج‌های قدیمی، کانتینرهای متوقف، کش ساخت و لاگ کانتینرها.

docker system df
docker image prune -a      # ایمیج‌هایی که هیچ کانتینری از آن‌ها استفاده نمی‌کند
docker builder prune

پیش از اجرای docker volume prune بسیار دقت کنید؛ Volumeها داده‌های دیتابیس شما را نگه می‌دارند و Volumeی که کانتینرش موقتاً حذف شده، «بلااستفاده» حساب می‌شود. لاگ کانتینرها هم در /var/lib/docker/containers جمع می‌شود و باید محدود شود (گام ۶).

root@server: ~
$ df -h /Filesystem  Size  Used Avail Use% Mounted on/dev/vda1    ...   ...     0 100% /$ du -xh --max-depth=1 /var | sort -h | tail -n 3...   /var/cache...   /var/log...   /var/lib/docker$ docker system dfTYPE        TOTAL  ACTIVE  SIZE  RECLAIMABLE$ 
شکل ۲ در بیشتر سرورها، پوشه‌های لاگ و داکر بزرگ‌ترین مصرف‌کنندگان فضای دیسک هستند.

بکاپ‌ها و فایل‌های موقت

بکاپ‌های قدیمی که روی همان سرور مانده‌اند، فایل‌های dump دیتابیس، آرشیوهای دانلودشده و پوشهٔ /tmp را بررسی کنید. بکاپی که روی همان دیسک سرور است، هم فضا می‌گیرد و هم در صورت خرابی دیسک کمکی نمی‌کند؛ آن را به جای دیگری منتقل کنید.

گام ۴: وقتی inode تمام شده است

اگر df -i پر بودن inode را نشان داد، پوشه‌ای که بیشترین تعداد فایل را دارد پیدا کنید:

sudo find / -xdev -type f 2>/dev/null | cut -d/ -f2-3 | sort | uniq -c | sort -n | tail

مقصران معمول: پوشهٔ نشست‌های PHP، کش برنامه‌ها، صف ایمیل محلی یا فایل‌های موقتی که یک اسکریپت هرگز پاک نکرده است. پس از اطمینان از بی‌خطر بودن، با find و گزینهٔ -delete حذفشان کنید و علت ساخت بی‌رویه را رفع کنید.

گام ۵: فضا آزاد نشد؟ فایل‌های حذف‌شدهٔ باز

گاهی فایل بزرگی را حذف می‌کنید اما df تغییری نشان نمی‌دهد. علت این است که یک برنامه هنوز آن فایل را باز نگه داشته و تا وقتی فایل باز است، فضایش آزاد نمی‌شود. فهرست این فایل‌ها:

sudo lsof -nP +L1 | head -n 20

ستون اول نام برنامه را نشان می‌دهد. ری‌استارت همان سرویس (مثلاً sudo systemctl restart nginx) فضا را آزاد می‌کند.

گام ۶: جلوگیری از تکرار

  • logrotate: مطمئن شوید لاگ برنامه‌های خودتان هم چرخش دارد. فایلی در /etc/logrotate.d/ بسازید که لاگ‌ها را روزانه بچرخاند، فشرده کند و فقط چند نسخهٔ آخر را نگه دارد.
  • لاگ داکر: در فایل /etc/docker/daemon.json حجم لاگ کانتینرها را محدود کنید و سرویس داکر را ری‌استارت کنید:
{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "3" } }
  • پایش: یک کار cron ساده بنویسید که اگر استفادهٔ دیسک از حد مشخصی بالاتر رفت، به شما پیام بدهد. روش زمان‌بندی کارها را در آموزش‌های دستورهای لینوکس و دستورات پرکاربرد لینوکس برای سرور دنبال کنید.
rm یا truncate برای لاگ فعال؟
rm فایل لاگ
  • نام فایل حذف می‌شود
  • برنامه همچنان در فایل باز می‌نویسد
  • فضا تا ری‌استارت آزاد نمی‌شود
  • لاگ‌های بعدی ناپدید می‌شوند
در برابر
truncate -s 0
  • محتوا خالی می‌شود
  • برنامه بدون مشکل ادامه می‌دهد
  • فضا فوراً آزاد می‌شود
  • فایل و مجوزها حفظ می‌شود
شکل ۳ برای فایل لاگی که برنامه در حال نوشتن روی آن است، همیشه truncate را انتخاب کنید.

کی باید دیسک را بزرگ‌تر کرد؟

اگر پس از پاک‌سازی، داده‌های واقعی (دیتابیس، فایل‌های کاربران) بیشتر فضا را گرفته‌اند و مصرف به‌طور طبیعی رو به رشد است، مشکل «پاک‌سازی» نیست و سرور به دیسک بیشتری نیاز دارد. در این حالت پلن بزرگ‌تری انتخاب کنید یا فایل‌های حجیم و ثابت (مثل تصاویر و ویدیوها) را از سرور جدا کنید و از طریق CDN تحویل دهید تا هم فضای دیسک و هم ترافیک سرور اصلی کم شود. راهنمای انتخاب منابع در چه مقدار رم و CPU لازم دارم آمده است و پلن‌های با دیسک بزرگ‌تر را می‌توانید در صفحهٔ سرور مجازی ایران ببینید.

یادتان باشد که پر شدن دیسک و کمبود رم دو مشکل متفاوت‌اند؛ اگر سرویس‌ها به‌طور ناگهانی kill می‌شوند، مقالهٔ کمبود رم و خطای Out of Memory را بخوانید.

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

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

احتمالاً برنامه‌ای هنوز آن فایل را باز نگه داشته است. با sudo lsof +L1 فایل‌های حذف‌شدهٔ باز را پیدا کنید و سرویس مربوط را ری‌استارت کنید تا فضا آزاد شود.

پاک کردن /var/log خطرناک است؟

پاک کردن کورکورانهٔ کل پوشه توصیه نمی‌شود، چون برخی سرویس‌ها انتظار دارند پوشه‌ها و فایل‌هایشان وجود داشته باشد. فایل‌های چرخیده و فشرده‌شدهٔ قدیمی را می‌توانید حذف کنید و فایل‌های فعال را با truncate خالی کنید.

docker system prune چه چیزهایی را پاک می‌کند؟

کانتینرهای متوقف، شبکه‌های بلااستفاده، ایمیج‌های بدون برچسب و کش ساخت را پاک می‌کند. با گزینهٔ -a همهٔ ایمیج‌های بی‌کانتینر حذف می‌شوند و با --volumes Volumeهای بلااستفاده هم پاک می‌شوند که ممکن است دادهٔ مهم داشته باشند.

inode چیست و چرا تمام می‌شود؟

inode ساختاری است که اطلاعات هر فایل را نگه می‌دارد و تعدادش هنگام ساخت سیستم‌فایل ثابت می‌شود. اگر برنامه‌ای میلیون‌ها فایل کوچک بسازد، inodeها پیش از فضای دیسک تمام می‌شوند.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.