توی این درس یاد میگیری هر سرور سه منبع اصلی دارد: دیسک (جای دائمی)، حافظه (RAM و swap) و CPU (توان پردازش). با df -h فضای خالی هر دیسک را، با du -sh * حجم پوشهها را، با free -h وضعیت حافظه را، با uptime بار سیستم (load average) را، و با lsblk و mount دیسکها و محل وصلشدنشان را میبینی. و مهمتر: وقتی «سرور پر شده» میدانی چطور پیدا کنی چه چیزی منبع را خورده. تمرین: بزرگترین پوشههای سیستم را پیدا میکنی.
مسئله: سرور کند یا از کار افتاده، چرا؟
Section titled “مسئله: سرور کند یا از کار افتاده، چرا؟”بیشتر «سرور خراب شد» ها یکی از سه علت دارند: دیسک پر شد، حافظه تمام شد یا CPU اشباع شد. قبل از هر عیبیابی پیچیده، باید بتوانی در یک دقیقه این سه را بخوانی.
تشبیه: انبار، میز کار و کارگرها
Section titled “تشبیه: انبار، میز کار و کارگرها”دیسک مثل انبار است: بزرگ و دائمی، اما رفتن تا آن کند است. RAM میز کار است: کوچکتر و بسیار سریع، و با خاموششدن همهچیزش پاک میشود. swap قفسهای در انبار است که وقتی میز پر شد، چیزهای کممصرف را موقتاً آنجا میگذاری (جا باز میشود ولی هر بار رفتن سراغش کند است). CPU کارگرهاست، و load average یعنی «بهطور متوسط چند کار منتظر نوبت یک کارگرند».
مثالهای عملی
Section titled “مثالهای عملی”مثال ۱: فضای دیسک، df -h
Section titled “مثال ۱: فضای دیسک، df -h”df (disk free) برای هر فایلسیستم (هر دیسک یا پارتیشنِ وصلشده) میگوید چقدر جا دارد. -h یعنی خوانا (human-readable: G و M بهجای بایت):
df -hFilesystem Size Used Avail Use% Mounted onoverlay 453G 22G 408G 6% /tmpfs 64M 0 64M 0% /devshm 64M 0 64M 0% /dev/shmoverlay 392M 356K 392M 1% /usr/sbin/docker-init/dev/vda1 453G 22G 408G 6% /etc/hoststmpfs 4.0K 0 4.0K 0% /proc/scsiستونها: Filesystem (دستگاه)، Size (اندازهی کل)، Used (استفادهشده)، Avail (قابلاستفاده)، Use% (درصد پر بودن) و Mounted on (محل وصلشدن در درخت پوشهها). چون این آزمایشگاه یک کانتینر است، فایلسیستم ریشه (/) از نوع overlay است و چند خط مخصوص کانتینر هم هست؛ روی سرور واقعی معمولاً یک /dev/sda1 یا /dev/vda1 روی / میبینی. دو گزینهی مفید:
echo "--- نوع فایلسیستم (-T) فقط برای /:"df -hT /echo "--- inode ها (-i):"df -i /--- نوع فایلسیستم (-T) فقط برای /:Filesystem Type Size Used Avail Use% Mounted onoverlay overlay 453G 22G 408G 6% /--- inode ها (-i):Filesystem Inodes IUsed IFree IUse% Mounted onoverlay 30179328 344223 29835105 2% /هر فایل یک inode (درس لینکها) مصرف میکند. اگر تعداد inode ها تمام شود، حتی با فضای خالی زیاد هم نمیتوانی فایل جدید بسازی (مثال ۷). پس هشدار Use% را هم برای فضا و هم برای inode نگاه کن.
مثال ۲: حجم پوشهها، du -sh *
Section titled “مثال ۲: حجم پوشهها، du -sh *”df میگوید دیسک چقدر پر است؛ du (disk usage) میگوید هر پوشه چقدر برداشته. -s یعنی فقط جمع هر مورد (summary)، -h خوانا. یک درخت نمونه با حجمهای مشخص میسازم (از head -c فقط برای ساختن فایلهای بیمحتوای ۵ مگابایتی استفاده میکنم):
mkdir -p demo/logs demo/cache demo/src demo/.hiddenhead -c 5M /dev/zero > demo/logs/app.loghead -c 2M /dev/zero > demo/logs/old.loghead -c 1M /dev/zero > demo/cache/c.binecho 'print(1)' > demo/src/main.pyhead -c 8M /dev/zero > demo/.hidden/big.bincd demoecho "--- du -sh * (حجم هر مورد):"du -sh *echo "--- از بزرگ به کوچک (sort -rh):"du -sh * | sort -rhecho "--- فایلهای یک پوشه، بزرگترین بالا (ls -S):"ls -lhS logs--- du -sh * (حجم هر مورد):1.1M cache7.1M logs8.0K src--- از بزرگ به کوچک (sort -rh):7.1M logs1.1M cache8.0K src--- فایلهای یک پوشه، بزرگترین بالا (ls -S):total 7.0M-rw-r--r-- 1 ali ali 5.0M Oct 3 21:20 app.log-rw-r--r-- 1 ali ali 2.0M Oct 3 21:20 old.logsort -rh مرتبسازی را برای اعداد خوانا (5.0M در برابر 1.1M) انجام میدهد (-h) و از بزرگ به کوچک (-r). یک نکتهی تله: du -sh * فقط چیزهایی را میبیند که * جایگزین میکند، و * فایلهای مخفی (با نقطه) را نمیگیرد؛ پوشهی .hidden هشت مگابایتی در خروجی نیامد! (اشتباهات رایج.)
مثال ۳: پیدا کردن اینکه چه چیزی دیسک را پر کرده
Section titled “مثال ۳: پیدا کردن اینکه چه چیزی دیسک را پر کرده”روش استاندارد: از ریشه شروع کن، فقط یک سطح پایین برو (--max-depth=1)، بزرگترین را انتخاب کن و همان را دوباره باز کن. -x از رفتن به فایلسیستمهای دیگر (مثل /proc) جلوگیری میکند و 2>/dev/null خطاهای «دسترسی نداری» را دور میریزد:
echo "--- بزرگترین پوشههای ریشه:"sudo du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -6echo "--- بزرگترین زیرپوشههای /usr:"sudo du -xh --max-depth=1 /usr 2>/dev/null | sort -rh | head -5--- بزرگترین پوشههای ریشه:732M /642M /usr71M /var17M /home2.8M /etc236K /tmp--- بزرگترین زیرپوشههای /usr:642M /usr268M /usr/lib143M /usr/share121M /usr/bin96M /usr/libexec(خط اول هر فهرست، جمع خود آن پوشه است.) هر بار بزرگترین را انتخاب میکنی و یک سطح پایینتر میروی تا به مقصر برسی (معمولاً /var/log، /var/lib/docker، یا /home). برای فایلهای منفرد بزرگ هم find (درس پیدا کردن فایلها):
echo "--- فایلهای بزرگتر از ۴ مگابایت در demo:"find demo -type f -size +4M -exec ls -lh {} +--- فایلهای بزرگتر از ۴ مگابایت در demo:-rw-r--r-- 1 ali ali 8.0M Oct 3 21:20 demo/.hidden/big.bin-rw-r--r-- 1 ali ali 5.0M Oct 3 21:20 demo/logs/app.logمثال ۴: حافظه و swap، free -h
Section titled “مثال ۴: حافظه و swap، free -h”free -h total used free shared buff/cache availableMem: 3.8Gi 2.2Gi 1.0Gi 5.6Mi 795Mi 1.6GiSwap: 1.0Gi 306Mi 717Miسطر Mem حافظهی RAM و سطر Swap فضای swap است. معنی ستونها:
| ستون | معنی |
|---|---|
total |
کل RAM |
used |
مصرفشده توسط برنامهها |
free |
کاملاً بیاستفاده |
shared |
حافظهی اشتراکی (مثل tmpfs) |
buff/cache |
کش دیسک: هسته از RAM آزاد برای تندتر کردن خواندن فایلها استفاده میکند |
available |
چقدر برای برنامهی جدید در دسترس است (free + کش قابلآزادسازی) |
مهمترین ستون available است، نه free. لینوکس عمداً RAM بیاستفاده را به کش میدهد (free کوچک و عادی است)؛ هر وقت برنامهای حافظه بخواهد، کش را رها میکند. هشدار وقتی است که available کم شود و swap used رشد کند. (عددها اینجا مال ماشین مجازی داکر است که میزبان این کانتینر است.) ببین یک برنامهی ۳۰۰ مگابایتی چه اثری دارد:
echo "--- قبل:"free -m | head -2python3 -c 'import time; b = bytearray(300 * 1024 * 1024); b[::4096] = b"x" * len(b[::4096]); time.sleep(6)' &sleep 2echo "--- وقتی پروسهای ۳۰۰ مگابایت نگه داشته:"free -m | head -2waitecho "--- swap:"swapon --show--- قبل: total used free shared buff/cache availableMem: 3916 2279 1030 5 795 1637--- وقتی پروسهای ۳۰۰ مگابایت نگه داشته: total used free shared buff/cache availableMem: 3916 2587 721 5 795 1328--- swap:NAME TYPE SIZE USED PRIO/var/lib/swap file 1024M 306.5M -1ستون used حدود ۳۰۰ مگابایت بالا رفت و available همانقدر پایین آمد. swapon --show فایل یا پارتیشن swap را نشان میدهد: یک فایل (/var/lib/swap) که ۱ گیگابایت از دیسک را برای swap گذاشته. اگر RAM و swap هر دو تمام شوند، هسته «OOM killer» را اجرا میکند و برای نجات سیستم یک پروسه را میکشد (درس لاگها).
مثال ۵: uptime و load average
Section titled “مثال ۵: uptime و load average”uptimeecho "--- همان عددها از /proc، و تعداد هستههای CPU:"cat /proc/loadavgnproc 21:20:15 up 1 day, 2:19, 0 user, load average: 0.45, 0.54, 1.59--- همان عددها از /proc، و تعداد هستههای CPU:0.45 0.54 1.59 1/480 8298uptime سه چیز میگوید: ساعت، مدتی که سیستم بالاست، و load average سه عدد: میانگین بار در ۱، ۵ و ۱۵ دقیقهی اخیر. load یعنی میانگین تعداد پروسههایی که آمادهی اجرا (R) یا منتظر دیسک (D) هستند. قاعدهی سرانگشتی: load را با تعداد هستهها (nproc) مقایسه کن: load برابر با تعداد هستهها یعنی CPU کاملاً مشغول؛ بیشتر از آن یعنی صف. الگوی سه عدد هم مهم است: اگر عدد ۱ دقیقه از عدد ۱۵ دقیقه کوچکتر باشد، بار در حال کمشدن است، و اگر بزرگتر باشد، در حال زیادشدن. (چون این کانتینر کل ماشین مجازی را میبیند، load شامل بقیهی کانتینرهای آن هم هست.) برای دیدن اثر یک بار شدید، چهار پروسهی شلوغ راه میاندازم و با vmstat (آماری که هر ثانیه تکرار میشود) نگاه میکنم:
for i in 1 2 3 4; do yes > /dev/null & donesleep 1vmstat 1 4pkill yesprocs -----------memory---------- ---swap-- -----io---- -system-- -------cpu------- r b swpd free buff cache si so bi bo in cs us sy id wa st gu 5 0 313904 1046920 37816 776576 3 12 153 358 3385 3 29 1 70 0 0 0 4 0 313904 1046920 37816 776576 0 0 0 224 5408 2071 14 38 49 0 0 012 0 313904 1052672 37816 776576 0 0 0 0 5758 2667 14 38 48 0 0 0 4 0 313904 1052420 37816 776576 0 0 0 0 5604 2559 13 39 48 0 0 0(سطر اول vmstat میانگین از زمان بوت است؛ از سطر دوم به بعد را بخوان.) ستون r (run queue) تعداد پروسههای آمادهی اجراست و برابر ۴ شد (همان ۴ پروسهی yes)؛ ستونهای us (user) و sy (system) سهم CPU شلوغ را نشان میدهند و id (idle) سهم بیکار: چون ماشین ۸ هسته دارد و ۴ تایشان مشغولاند، حدود نصف CPU بیکار ماند. ستون wa (wait) اگر بالا باشد یعنی CPU منتظر دیسک است، نشانهی دیسک کند، نه CPU ضعیف.
load average برابر ۴ روی سیستمی با ۴ هسته CPU یعنی…
load برابر تعداد هستهها یعنی هر هسته یک کار دارد: کاملاً مشغول ولی بدون صف. بیشتر از آن یعنی صف.
مثال ۶: دیسکها و mount، lsblk و mount
Section titled “مثال ۶: دیسکها و mount، lsblk و mount”دیسکها (block device) تا جایی که به درخت پوشهها وصل (mount) نشوند قابلاستفاده نیستند. برای دیدن کل چرخه، یک دیسک واقعی نمیخواهم: یک فایل ۱۰۰ مگابایتی را مثل دیسک فرمت میکنم (ext4) و با mount -o loop به /mnt/data وصل میکنم. این کار root میخواهد و در ماشین systemdدار آزمایشی (که در آن root هستم) انجام میدهم:
truncate -s 100M /tmp/lx-disk.imgmkfs.ext4 -q /tmp/lx-disk.imgmkdir -p /mnt/datamount -o loop /tmp/lx-disk.img /mnt/dataecho "--- lsblk: دیسکهای بلوکی (ram و nbd های خیالیِ ماشین آزمایشی را حذف کردم: -e 1,43)"lsblk -e 1,43echo "--- df با نوع فایلسیستم:"df -hT /mnt/dataecho "--- findmnt: این مسیر از کجا وصل شده؟"findmnt /mnt/dataecho "--- mount (فهرست همه؛ فقط خط مربوط به ما):"mount | grep lx-disk--- lsblk: دیسکهای بلوکی (ram و nbd های خیالیِ ماشین آزمایشی را حذف کردم: -e 1,43)NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTSloop0 7:0 0 100M 0 loop /mnt/datavda 254:0 0 460.4G 0 disk└─vda1 254:1 0 460.4G 0 part /etc/resolv.conf /etc/hosts /etc/hostnamevdb 254:16 0 646.1M 1 disk--- df با نوع فایلسیستم:Filesystem Type Size Used Avail Use% Mounted on/dev/loop0 ext4 90M 24K 83M 1% /mnt/data--- findmnt: این مسیر از کجا وصل شده؟TARGET SOURCE FSTYPE OPTIONS/mnt/data /dev/loop0 ext4 rw,relatime--- mount (فهرست همه؛ فقط خط مربوط به ما):/tmp/lx-disk.img on /mnt/data type ext4 (rw,relatime)lsblk(list block devices) دیسکها و پارتیشنها را در یک درخت مینشاند:vdaدیسک اصلی ماشین مجازی من است وloop0همان فایل ۱۰۰ مگابایتی باMOUNTPOINTSبرابر/mnt/data. (زیرvda1چند مسیر/etc/...هم هست چون این ماشین یک کانتینر است.)mountبدون آرگومان همهی mount ها را با شکل «دستگاه on مسیر type نوع (گزینهها)» چاپ میکند؛findmntهمین را مرتبتر.Sizeفایلسیستم (۹۰ مگابایت) از فایل ۱۰۰ مگابایتی کمتر است: بخشی صرف ساختار خود ext4 (journal، جدول inode ها) میشود، و ext4 بهطور پیشفرض ۵٪ را هم برای root رزرو میکند (Availکمتر ازSize - Used).
حالا از دیسک استفاده کن و بردارش (umount، بدون «n» اول، یک غلط املایی تاریخی است):
echo "دادهی من" > /mnt/data/note.txtls -l /mnt/datadf -h /mnt/data | tail -1umount /mnt/dataecho "--- بعد از umount:"ls -A /mnt/data | wc -lfindmnt /mnt/data || echo "(دیگر mount نیست)"total 20drwx------ 2 root root 16384 Oct 3 21:19 lost+found-rw-r--r-- 1 root root 19 Oct 3 21:19 note.txt/dev/loop0 90M 28K 83M 1% /mnt/data--- بعد از umount:0(دیگر mount نیست)بعد از umount، /mnt/data دوباره یک پوشهی خالی معمولی روی دیسک اصلی است؛ دادهها داخل فایل lx-disk.img ماندند و هر وقت دوباره mount کنی برمیگردند.
مثال ۷: «No space left on device»
Section titled “مثال ۷: «No space left on device»”برای دیدن این خطا بدون پر کردن دیسک واقعی، یک فایلسیستم ۱۰ مگابایتی در RAM (tmpfs) درست میکنم و پرش میکنم:
mkdir -p /mnt/smallmount -t tmpfs -o size=10M tmpfs /mnt/smalldd if=/dev/zero of=/mnt/small/big bs=1M count=20df -h /mnt/smallecho "--- مقصر را با du/ls پیدا و پاک میکنیم:"ls -lh /mnt/smallrm /mnt/small/bigdf -h /mnt/small | tail -1dd: error writing '/mnt/small/big': No space left on device11+0 records in10+0 records out10485760 bytes (10 MB, 10 MiB) copied, 0.008131 s, 1.3 GB/sFilesystem Size Used Avail Use% Mounted ontmpfs 10M 10M 0 100% /mnt/small--- مقصر را با du/ls پیدا و پاک میکنیم:total 10M-rw-r--r-- 1 root root 10M Oct 3 21:19 bigtmpfs 10M 0 10M 0% /mnt/smalldd در ۱۰ مگابایت اول موفق بود و بعد No space left on device؛ و df همان لحظه 100% را نشان داد. بعد از پاککردن فایل، فضا برگشت. نوع دوم همین خطا، با فضای خالیِ فراوان است: وقتی inode ها تمام شوند (مثلاً میلیونها فایل کوچک). با یک فایلسیستم که فقط ۵۰ inode دارد شبیهسازی میکنم:
umount /mnt/smallmount -t tmpfs -o size=10M,nr_inodes=50 tmpfs /mnt/smallfor i in $(seq 1 80); do touch /mnt/small/f$i 2>/tmp/lx-err || { echo "فایل شمارهی $i: $(cat /tmp/lx-err)"; break; }; doneecho "--- فضا:"df -h /mnt/small | tail -1echo "--- inode:"df -i /mnt/smallumount /mnt/smallفایل شمارهی 50: touch: cannot touch '/mnt/small/f50': No space left on device--- فضا:tmpfs 10M 0 10M 0% /mnt/small--- inode:Filesystem Inodes IUsed IFree IUse% Mounted ontmpfs 50 50 0 100% /mnt/smalldf -h میگوید ۰٪ پر (۱۰ مگابایت خالی!) ولی df -i میگوید ۱۰۰٪ inode ها مصرف شده. پس وقتی «No space left» دیدی و df -h خالی نشان داد، df -i را بزن.
مثال ۸: /etc/fstab، mount دائمی
Section titled “مثال ۸: /etc/fstab، mount دائمی”mount ای که با دست زدی بعد از ریبوت میرود. برای دائمیشدن، آن را در /etc/fstab مینویسند که سیستم هنگام بوت میخواند. هر خط شش ستون دارد: دستگاه، محل mount، نوع فایلسیستم، گزینهها، dump، fsck. برای همین دیسک نمونه (loop یعنی از یک فایل mount کن):
echo "--- fstab قبلی (بدون توضیح):"grep -v '^#' /etc/fstabecho "/tmp/lx-disk.img /mnt/data ext4 loop 0 0" >> /etc/fstabecho "--- بعد از افزودن یک خط:"grep -v '^#' /etc/fstabecho "--- mount -a (همهی خطهای fstab را که mount نیستند mount کن، مثل هنگام بوت):"mount -afindmnt /mnt/dataecho "--- پاکسازی:"umount /mnt/datased -i '/lx-disk/d' /etc/fstabrm -rf /mnt/data /mnt/small /tmp/lx-disk.imglosetup -aecho "(هیچ loop باقی نمانده)"--- fstab قبلی (بدون توضیح):--- بعد از افزودن یک خط:/tmp/lx-disk.img /mnt/data ext4 loop 0 0--- mount -a (همهی خطهای fstab را که mount نیستند mount کن، مثل هنگام بوت):TARGET SOURCE FSTYPE OPTIONS/mnt/data /dev/loop0 ext4 rw,relatime--- پاکسازی:(هیچ loop باقی نمانده)(fstab این ماشین فقط توضیح داشت، برای همین سطر اول چیزی چاپ نکرد.) mount -a بعد از ویرایش fstab بهترین آزمایش است: اگر خطی غلط باشد همانجا خطا میدهد، نه موقع بوت بعدی که سرور بالا نمیآید.
پشت پرده: df و du چرا گاهی با هم نمیخوانند؟
Section titled “پشت پرده: df و du چرا گاهی با هم نمیخوانند؟”df از خود فایلسیستم میپرسد «چند بلوک استفاده شده؟»، و du فایلها را یکییکی پیمایش میکند و اندازهشان را جمع میزند. بیشتر وقتها برابرند؛ ولی اگر فایلی پاک شده ولی هنوز باز باشد، du آن را نمیبیند (اسمی در پوشه نیست) ولی df هنوز جایش را میشمارد، چون فضا تا بستهشدن آخرین پروسهی بازکننده آزاد نمیشود. این یکی از شاخصترین معماهای واقعی است:
mkdir -p /mnt/smallmount -t tmpfs -o size=20M tmpfs /mnt/smalldd if=/dev/zero of=/mnt/small/log bs=1M count=15 2>/dev/nullsleep 300 < /mnt/small/log &holder=$!rm /mnt/small/logecho "--- پوشه خالی است:"ls -l /mnt/smalldu -sh /mnt/smallecho "--- ولی df ۱۵ مگابایت میگوید:"df -h /mnt/small | tail -1echo "--- چه کسی آن را باز نگه داشته؟ lsof +L1 (فایلهایی با 0 لینک):"lsof +L1 /mnt/smallkill $holder; wait $holder 2>/dev/nullecho "--- بعد از بستن آن پروسه:"df -h /mnt/small | tail -1umount /mnt/small--- پوشه خالی است:total 00 /mnt/small--- ولی df ۱۵ مگابایت میگوید:tmpfs 20M 15M 5.0M 75% /mnt/small--- چه کسی آن را باز نگه داشته؟ lsof +L1 (فایلهایی با 0 لینک):COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAMEsleep 474 root 0r REG 0,67 15728640 0 2 /mnt/small/log (deleted)--- بعد از بستن آن پروسه:tmpfs 20M 0 20M 0% /mnt/smallفایل با rm از پوشه حذف شد (لینکش صفر شد) ولی sleep هنوز آن را باز داشت، پس هسته فضایش را نگه داشت: lsof +L1 فهرست «پاکشده ولی باز» را نشان میدهد. وقتی آن پروسه تمام شد فضا برگشت. در سرور واقعی معمولاً مقصر یک سرویس است که لاگ را باز دارد و کسی لاگ را با rm پاک کرده؛ راهحل درست: فایل را خالی کن (: > فایل یا truncate -s 0 فایل) بهجای پاک کردن، یا سرویس را restart کن.
جدولهای مرجع
Section titled “جدولهای مرجع”| دستور | کار |
|---|---|
df -h |
فضای هر فایلسیستم |
df -hT /مسیر |
با نوع فایلسیستم، فقط برای یک مسیر |
df -i |
مصرف inode ها |
du -sh * |
حجم هر مورد (بدون فایلهای مخفی) |
du -sh .[!.]* * |
حجم همهی موارد از جمله مخفی |
du -xh --max-depth=1 / | sort -rh | head |
بزرگترین پوشهها |
ls -lhS |
فایلها از بزرگ به کوچک |
free -h |
حافظه و swap |
swapon --show |
فایلها یا پارتیشنهای swap |
uptime / cat /proc/loadavg |
مدت بالا بودن و load average |
nproc |
تعداد هستههای CPU |
vmstat 1 5 |
آمار حافظه و CPU (هر ثانیه، ۵ بار) |
lsblk |
دیسکها و پارتیشنها |
mount / findmnt |
فهرست mount ها |
mount دستگاه مسیر / umount مسیر |
وصل کردن / جدا کردن |
lsof +L1 |
فایلهای پاکشده ولی هنوز باز |
ستون free |
معنی |
|---|---|
used |
حافظهی مصرفشدهی برنامهها |
buff/cache |
کش دیسک؛ قابلآزادسازی |
available |
آنچه برای برنامهی جدید واقعاً هست (این را نگاه کن) |
اشتباهات رایج
Section titled “اشتباهات رایج”۱) du -sh * فایلهای مخفی را نمیبیند
Section titled “۱) du -sh * فایلهای مخفی را نمیبیند”cd demoecho "--- با * (بدون مخفیها):"du -sh *echo "--- با .[!.]* هم:"du -sh .[!.]* *echo "--- راه مطمئنتر: خودِ du پیمایش کند و sort:"du -h --max-depth=1 . | sort -rh--- با * (بدون مخفیها):1.1M cache7.1M logs8.0K src--- با .[!.]* هم:8.1M .hidden1.1M cache7.1M logs8.0K src--- راه مطمئنتر: خودِ du پیمایش کند و sort:17M .8.1M ./.hidden7.1M ./logs1.1M ./cache8.0K ./srcشل * را به نامهای بدون نقطهی اول باز میکند؛ پوشهی .hidden هشت مگابایتی (بزرگترین!) نیامد. راهحل: du -h --max-depth=1 . | sort -rh که خود du همهچیز (از جمله مخفیها) را میشمارد و . جمع کل است.
۲) پاککردن فایل و تغییر نکردن df
Section titled “۲) پاککردن فایل و تغییر نکردن df”مثال «پشت پرده»: فایل لاگ را با rm پاک کردی ولی df همان ۹۵٪ است. راهحل: lsof +L1 برای پیدا کردن نگهدارنده، و restart آن سرویس؛ در آینده با truncate -s 0 خالی کن، نه rm.
۳) ترسیدن از free کوچک
Section titled “۳) ترسیدن از free کوچک”ستون free ممکن است نسبت به total کوچک باشد در حالی که available (همان مثال ۴) خیلی بزرگتر است؛ سیستم سالم است. راهحل: همیشه ستون available و رشد swap used را نگاه کن، نه free.
۴) mount روی یک پوشهی پر، فایلهای قبلی را «پنهان» میکند
Section titled “۴) mount روی یک پوشهی پر، فایلهای قبلی را «پنهان» میکند”mkdir -p /mnt/shadowecho "فایل اصلی" > /mnt/shadow/data.txtecho "--- قبل از mount:"; ls /mnt/shadowmount -t tmpfs tmpfs /mnt/shadowecho "--- بعد از mount (روی همان پوشه):"; ls -A /mnt/shadow | wc -lumount /mnt/shadowecho "--- بعد از umount:"; ls /mnt/shadowrm -rf /mnt/shadow--- قبل از mount:data.txt--- بعد از mount (روی همان پوشه):0--- بعد از umount:data.txtفایلها پاک نشدند: mount جدید روی پوشه مینشیند و فایلهای زیرش تا umount دیده نمیشوند. اگر دیدی «فایلهایم ناپدید شدند»، با findmnt ببین روی آن پوشه چیزی mount شده یا نه. راهحل: نقطهی mount را یک پوشهی خالی انتخاب کن.
۵) rm -rf روی پوشهی mount
Section titled “۵) rm -rf روی پوشهی mount”اگر در یک مسیر دیسک دیگری mount شده باشد و rm -rf بزنی، محتوای آن دیسک پاک میشود، نه فقط پوشهی خالی. راهحل: پیش از حذف مسیرهای تحت /mnt و /media، با findmnt مطمئن شو چیزی mount نیست (یا اول umount).
درصد پر بودن فایلسیستم ریشه (/) و درصد مصرف inode آن را پیدا کن.
دیدن جواب
df -h /df -i /echo "--- فقط درصدها:"df --output=pcent,ipcent /Filesystem Size Used Avail Use% Mounted onoverlay 453G 22G 408G 6% /Filesystem Inodes IUsed IFree IUse% Mounted onoverlay 30179328 344233 29835095 2% /--- فقط درصدها:Use% IUse% 6% 2%--output ستونهای دلخواه df را انتخاب میکند (pcent درصد فضا و ipcent درصد inode).
تمرین اصلی: بزرگترین پوشههای سیستم را پیدا کن. با du بزرگترین پوشهی داخل /var را پیدا کن و بعد بزرگترین زیرپوشهی آن را؛ دو سطح پایین برو.
دیدن جواب
echo "--- سطح اول: بزرگترین پوشههای /var"sudo du -xh --max-depth=1 /var 2>/dev/null | sort -rh | sed -n '2,4p'echo "--- سطح دوم: داخل /var/lib (بزرگترینها)"sudo du -xh --max-depth=1 /var/lib 2>/dev/null | sort -rh | sed -n '2,4p'--- سطح اول: بزرگترین پوشههای /var67M /var/lib3.2M /var/cache600K /var/log--- سطح دوم: داخل /var/lib (بزرگترینها)55M /var/lib/apt11M /var/lib/dpkg760K /var/lib/plocatesed -n '2,4p' خط ۲ تا ۴ را میدهد (خط اول جمع خود پوشه است).
یک دیسک ۵۰ مگابایتی شبیهسازی کن: فایل، mkfs.ext4، mount در /mnt/vault، یک فایل بنویس، و در df -h و lsblk و findmnt نشانش بده؛ دائمیاش کن با یک خط fstab، با umount و mount -a آزمایش کن که برمیگردد، و همهچیز را پاک کن. (root لازم است؛ این بخش را روی ماشین آزمایشی انجام میدهم.)
دیدن جواب
truncate -s 50M /tmp/lx-vault.imgmkfs.ext4 -q /tmp/lx-vault.imgmkdir -p /mnt/vaultmount -o loop /tmp/lx-vault.img /mnt/vaultecho "رمز خزانه" > /mnt/vault/secret.txtdf -h /mnt/vault | tail -1lsblk -e 1,43 | grep vaultfindmnt /mnt/vaultecho "/tmp/lx-vault.img /mnt/vault ext4 loop 0 0" >> /etc/fstabumount /mnt/vaultecho "--- بعد از umount: $(ls -A /mnt/vault | wc -l) فایل (خالی)"mount -aecho "--- بعد از mount -a:"cat /mnt/vault/secret.txtumount /mnt/vaultsed -i '/lx-vault/d' /etc/fstabrm -rf /mnt/vault /tmp/lx-vault.img/dev/loop0 43M 28K 40M 1% /mnt/vaultloop0 7:0 0 50M 0 loop /mnt/vaultTARGET SOURCE FSTYPE OPTIONS/mnt/vault /dev/loop0 ext4 rw,relatime--- بعد از umount: 0 فایل (خالی)--- بعد از mount -a:رمز خزانهآزمونک
Section titled “آزمونک”تفاوت df و du چیست؟
df «چقدر پر است»؛ du «چه چیزی پر کرده». ممکن است با هم نخوانند (مثلاً فایل پاکشدهی باز).
در خروجی free کدام ستون نشان میدهد برای برنامهی جدید چقدر حافظه در دسترس است؟
available شامل free و کش قابلآزادسازی است؛ free کم بودن در لینوکس عادی است.
load average ۸ روی سیستمی با ۴ هسته یعنی…
load را با nproc مقایسه کن: برابر یعنی کاملاً مشغول، بیشتر یعنی صف.
df -h میگوید ۴۰٪ خالی است ولی نمیتوانی فایل بسازی و خطا No space left on device است. اول چه میزنی؟
هر فایل یک inode میخواهد؛ با میلیونها فایل کوچک inode ها تمام میشود، با فضای خالی فراوان.
فایل لاگ بزرگی را rm کردی ولی df همانقدر پر مانده است. چرا؟
راهحل: restart سرویس نگهدارنده؛ بعداً بهجای rm فایل را با truncate -s 0 خالی کن.
اگر یک دیسک را روی پوشهای mount کنی که از قبل فایل داشته، چه میشود؟
mount روی پوشه مینشیند؛ با umount همهچیز برمیگردد.
جمعبندی
Section titled “جمعبندی”- دیسک:
df -h(فضا؛-Tنوع،-iinode)،du -sh *وdu -h --max-depth=1 . | sort -rhبرای پیدا کردن مقصر.*فایلهای مخفی را نمیبیند. - حافظه:
free -h؛ ستونavailableمهم است، نهfree.swapon --showفضای swap را نشان میدهد؛ رشد swap و کمشدن available علامت خطر است. - CPU:
uptimeو load average (۱، ۵، ۱۵ دقیقه)؛ باnprocمقایسه کن.vmstat 1برای دیدنr،us،sy،idوwa. - دیسکها و mount:
lsblkدستگاهها،mount/findmntوصلشدهها،mount دستگاه مسیروumount؛ دائمیکردن با/etc/fstabو آزمایش باmount -a. - «No space left on device» دو علت دارد: فضا یا inode؛ و اگر
rmفضا را آزاد نکرد،lsof +L1.
| دستور | کاری که میکند |
|---|---|
df -h / df -hT / / df -i | فضا، نوع فایلسیستم، inode |
du -sh * | حجم هر مورد (بدون مخفیها) |
du -h --max-depth=1 . | sort -rh | head | بزرگترینها، با مخفیها |
sudo du -xh --max-depth=1 / 2>/dev/null | sort -rh | head | بزرگترین پوشههای سیستم |
ls -lhS | فایلها از بزرگ به کوچک |
free -h | حافظه و swap (ستون available) |
swapon --show | فضای swap |
uptime / nproc | load average و تعداد هستهها |
vmstat 1 5 | آمار CPU و حافظه |
lsblk | دیسکها و پارتیشنها |
mount | grep نام / findmnt مسیر | بررسی mount ها |
sudo mount دستگاه مسیر / sudo umount مسیر | وصل / جدا کردن |
lsof +L1 | فایلهای پاکشده ولی باز |