df مکمل، du نہیں: چھپی ہوئی disk space کیسے تلاش کریں
VPS میں df مکمل مگر du کم دکھائے تو حذف شدہ مگر کھلی file تلاش کریں۔ lsof سے process معلوم کریں، reboot کے بغیر جگہ آزاد کریں، اور دیگر وجوہ دیکھیں۔
df مکمل کیوں دکھاتا ہے جبکہ du ایسا نہیں دکھاتا
df ڈسک کو مکمل رپورٹ کرتا ہے، جبکہ du اس جگہ کو تلاش نہیں کر پاتا کیونکہ کوئی process اب بھی حذف شدہ file کو کھولے ہوئے ہے۔ File حذف کرنے سے directory میں موجود اس کا نام ختم ہو جاتا ہے۔ Data blocks صرف اس وقت آزاد ہوتے ہیں جب اس inode کی طرف اشارہ کرنے والا آخری open file descriptor بند ہو جائے۔ du ناموں کو scan کرتا ہے، اس لیے وہ کچھ شمار نہیں کرتا۔ df filesystem سے معلوم کرتا ہے کہ کتنے blocks allocate ہیں، اس لیے وہ اس file کو اب بھی شمار کرتا ہے جس کا نام باقی نہیں رہا۔
یہ guide پہلے سے نصب tools کے ذریعے ایک سادہ Ubuntu VPS پر اس صورتِ حال کو دوبارہ بناتی ہے، /proc کے ذریعے اس file کو کھولے رکھنے والے process کو تلاش کرتی ہے، اور reboot کیے بغیر جگہ آزاد کرتی ہے۔ اسی علامت کی دوسری وجوہات بھی بعد میں بیان کی گئی ہیں: ایسا inode table جس میں کوئی free entry نہ ہو، mount point کے نیچے چھپی ہوئی files، اور root کے لیے reserved blocks۔
ہر command چلائیں اور اپنا output پڑھیں۔ Values آپ کی disk پر منحصر ہوتی ہیں، اس لیے guide میں چھپی ہوئی کسی figure سے موازنہ کرنے کے بجائے اپنی machine پر پہلے اور بعد کے نتائج کا موازنہ کریں۔
What df counts and what du counts
df (disk free) asks each mounted filesystem for its own accounting: how many blocks exist, how many are allocated, how many are free. It never opens a directory. The answer covers every allocated block, including blocks belonging to a file that no directory entry points at.
du (disk usage) does the opposite. It starts at a path you give it, reads directories, stats every entry it finds, and adds up the blocks. A file with no name is invisible to it. So is any directory it is not allowed to read, which is why an ordinary user gets a smaller total than root does. Run du under sudo before you conclude anything from the comparison.
Two options matter every time you compare the two.
-xkeepsduon one filesystem. Without it,du /walks into every filesystem mounted below/and produces a total thatdf /was never measuring.-sprints one summary line per argument instead of one line per directory.
That gives the pair to run side by side on the filesystem you care about.
df -h /
sudo du -xhs / 2>/dev/nulldf answers immediately. du takes minutes on a large filesystem, because it stats every file on the way. When the two totals are far apart, and du ran as root with -x, the missing space is allocated to something that has no name.
جان بوجھ کر عدم مطابقت پیدا کریں
یہ کام test VPS پر کریں۔ نیچے دی گئی تمام چیزیں bash اور coreutils پر مشتمل ہیں، اس لیے کچھ بھی install نہیں ہوگا۔
اس filesystem کی ابتدائی حالت ریکارڈ کریں جس میں /var/tmp موجود ہے۔
cd /var/tmp
df -h .
df --output=used -B1 .دوسرا command استعمال شدہ bytes کو بغیر rounding کے دکھاتا ہے، اس لیے آخر میں کیا جانے والا check بالکل درست رہتا ہے۔
اب ایک file بنائیں۔ اس کا size مشین کی بتائی ہوئی free space سے حاصل ہوتا ہے، اس لیے یہ demonstration آپ کی disk کے مطابق خود کو ڈھال لیتی ہے۔
free=$(df --output=avail -B1 . | tail -n 1)
fallocate -l $((free / 10)) ghost.bin
ls -l ghost.bin
df -h .$(...) command substitution ہے: shell اس کے اندر موجود command چلاتا ہے، اور اس کا output free کی value بن جاتا ہے۔ اگر یہ syntax آپ کے لیے نیا ہے تو bash میں command substitution میں اس کی مکمل وضاحت موجود ہے۔ fallocate data لکھے بغیر حقیقی blocks reserve کرتا ہے، اسی لیے یہ فوراً مکمل ہو جاتا ہے۔ ایسے filesystem پر جو اس feature کو support نہ کرے، command ناکام ہو جاتا ہے، اور head -c $((free / 10)) /dev/zero > ghost.bin bytes لکھ کر یہی کام کرتا ہے۔
اس df -h . کا اس output سے موازنہ کریں جو آپ نے ریکارڈ کیا تھا۔ used column بڑھ گیا ہے اور available column کم ہو گیا ہے۔
اب کسی دوسرے process سے file کو open رکھیں، پھر اسے delete کریں۔
sleep infinity < ghost.bin &
holder=$!
rm ghost.bin
ls -l ghost.bin
df -h .
sudo du -xhs . 2>/dev/nullاصل طریقہ redirection میں ہے۔ sleep infinity < ghost.bin & ایک background process شروع کرتا ہے جس کا standard input اسی file سے آتا ہے، اس لیے shell file کو open کر کے اس کا descriptor sleep کو دے دیتی ہے، جو اسے open رکھتا ہے۔ $! اس background job کا process ID محفوظ کرتا ہے۔ rm اس کے بعد نام کو remove کر دیتا ہے، جبکہ descriptor اب بھی open رہتا ہے۔
Output پڑھیں۔ ls کو file نہیں ملتی، کیونکہ نام ختم ہو چکا ہے۔ du تقریباً اپنی ابتدائی حالت پر واپس آ گیا ہے، کیونکہ یہ ناموں کے ذریعے تلاش کرتا ہے۔ df میں کوئی تبدیلی نہیں ہوئی، کیونکہ blocks اب بھی allocated ہیں۔ اب filesystem اور directory tree ایک دوسرے سے مطابقت نہیں رکھتے، اور ان دونوں کے درمیان موجود فرق وہ file ہے جسے آپ نے ابھی delete کیا ہے۔
حذف شدہ فائل کو کھلے رکھنے والا process تلاش کریں
ہر کھلا file descriptor /proc/<pid>/fd/ کے تحت ایک symbolic link کے طور پر ظاہر ہوتا ہے، جو اس فائل کی طرف اشارہ کرتا ہے جسے وہ refer کرتا ہے۔ فائل unlink ہونے کے بعد kernel اس link کے target کو deleted کے طور پر نشان زد کرتا ہے۔ اس لیے holder تلاش کرنے کا مطلب ایسی link تلاش کرنا ہے جس کے target پر یہ marker موجود ہو۔
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null-lname symbolic link کے نام کے بجائے اس کے target سے match کرتا ہے، %p descriptor کا path دکھاتا ہے، اور %l دکھاتا ہے کہ وہ کس طرف اشارہ کرتا ہے۔ process ID اس path کا دوسرا element ہے جسے یہ print کرتا ہے۔ اسے sudo کے ساتھ چلائیں، کیونکہ بصورت دیگر آپ صرف اپنے processes کے لیے /proc/<pid>/fd پڑھ سکتے ہیں۔ stderr redirect ان processes کے error messages کو خارج کر دیتا ہے جو find کے چلتے ہوئے exit ہو جائیں۔
مصروف server میں کسی بھی وقت کئی deleted files کھلی رہ سکتی ہیں، اور ان میں سے زیادہ تر چھوٹی اور بے ضرر ہوتی ہیں۔ انہیں size کے لحاظ سے sort کریں تاکہ صرف اہم files فہرست کے اوپر رہیں۔
sudo bash -c 'for fd in /proc/[0-9]*/fd/*; do
target=$(readlink "$fd" 2>/dev/null) || continue
case "$target" in
*"(deleted)") echo "$(stat -Lc %s "$fd" 2>/dev/null) $fd $target" ;;
esac
done' | sort -rn | headstat -L خود inode تک link follow کرتا ہے، اس لیے %s اس file کا size report کرتا ہے جس کا اب کوئی نام نہیں رہا۔ اس number پر sorting کرنے سے سب سے بڑی file پہلے آ جاتی ہے۔
اب اس descriptor کے پیچھے موجود process کی شناخت کریں۔ اس فہرست میں سب سے اوپر موجود path دونوں مطلوبہ numbers رکھتا ہے، اس لیے پہلے انہیں variables میں محفوظ کریں، اور PID اور N کی جگہ اپنی listing میں ظاہر ہونے والی values لکھیں۔
pid=PID
n=N
ps -o pid,user,etime,args -p "$pid"
sudo stat -L "/proc/$pid/fd/$n"ps program کا نام بتاتا ہے اور یہ دکھاتا ہے کہ وہ کتنے عرصے سے چل رہا ہے۔ stat -L deleted inode کا size اور allocated block count print کرتا ہے۔ دونوں معلومات مل کر اصل سوال کا جواب دیتی ہیں: کون سی service اس file کو alive رکھے ہوئے ہے۔
اگر machine پر پہلے سے lsof موجود ہو تو sudo lsof +L1 ایسی open files کی فہرست بناتا ہے جن کا link count صفر ہو چکا ہے، اور sizes کو ایک table میں دکھاتا ہے۔ minimal Ubuntu image میں یہ موجود نہیں ہوتا، اور خالی جگہ نہ رکھنے والے filesystem پر package install کرنا خود بھی fail ہو سکتا ہے، اس لیے /proc والا walk وہ طریقہ ہے جو ہمیشہ کام کرتا ہے۔
ری بوٹ کے بغیر جگہ خالی کریں
ری بوٹ کرنے سے واقعی مسئلہ حل ہو جاتا ہے، لیکن یہ پہلا قدم نہیں ہونا چاہیے: اس سے service بند ہو جاتی ہے اور شواہد ضائع ہو جاتے ہیں۔ اس کے لیے چار نسبتاً کم مداخلت والے طریقے ہیں۔ انہیں اسی ترتیب سے آزمائیں۔
اگر آپ data رکھنا چاہتے ہیں تو پہلے اسے copy کر لیں۔ descriptor path پڑھنے سے live inode پڑھا جاتا ہے۔
sudo cp /proc/<pid>/fd/<n> /root/recovered.logیہ واحد صورت ہے جس میں deleted file واپس حاصل کرنا آسان ہوتا ہے۔ اسی لیے rm -rf سے deleted files کو recover کرنا اس سوال سے شروع ہوتا ہے کہ آیا کوئی process اب بھی file کو open رکھے ہوئے ہے۔ آخری descriptor بند ہوتے ہی یہ راستہ ختم ہو جاتا ہے۔
دوسرا طریقہ یہ ہے کہ descriptor کے ذریعے file خالی کر دیں۔ /proc path اسی inode تک پہنچاتا ہے، اس لیے اسے truncate کرنے سے process چلتا رہتا ہے اور blocks release ہو جاتے ہیں۔
sudo truncate -s 0 "/proc/$pid/fd/$n"
df -h /یہ طریقہ اس وقت درست طور پر کام کرتا ہے جب writer نے file کو append mode میں کھولا ہو، کیونکہ ہر write اس وقت file کے موجودہ اختتام پر جاتی ہے۔ اگر ایسا نہ ہو تو process اپنا پرانا write offset برقرار رکھتا ہے۔ اس لیے اگلی write file میں بہت آگے جا کر ہوتی ہے اور شروع میں hole کے ساتھ file دوبارہ بن جاتی ہے۔ hole کے لیے blocks allocate نہیں ہوتے، اس لیے blocks خالی رہتے ہیں اور df وہ space برقرار رکھتا ہے جو ابھی واپس ملی ہے۔ صرف size دوبارہ نظر آتا ہے: process کے write کرنے کے بعد sudo stat -L "/proc/$pid/fd/$n" دوبارہ چلائیں۔ یہ پرانا size دکھائے گا، جبکہ block count اس سے مطابقت نہیں رکھے گا۔ جب size بھی صفر سے شروع کرنی ہو تو process کو restart کریں۔
تیسرا طریقہ یہ ہے کہ service سے logs دوبارہ open کرنے کو کہیں۔ کسی daemon کی log file اس کے نیچے سے delete ہو جانا اس مسئلے کی عام حقیقی صورت ہے۔ بہت سے daemons signal ملنے پر اپنی log files دوبارہ open کرتے ہیں: nginx کے لیے SIGUSR1 اور rsyslog کے لیے SIGHUP استعمال ہوتا ہے۔ سامنے موجود daemon کی documentation دیکھ کر signal کی تصدیق کریں، اندازہ نہ لگائیں، کیونکہ غلط daemon کو غلط signal بھیجنے سے وہ رک سکتا ہے۔
sudo systemctl kill -s USR1 nginxاس سے signal اس process کو بھیجا جاتا ہے جسے systemd unit کا main process record کرتا ہے۔ اس لیے اگر unit میں daemon کے اصل startup طریقے کے لیے غلط Type= درج ہو تو signal ایسے process کو پہنچ سکتا ہے جس نے deleted file کبھی open ہی نہ کی ہو، اور space وہیں برقرار رہتی ہے۔
چوتھا طریقہ unit کو restart کرنا ہے۔ sudo systemctl restart <unit> پرانے process کے تمام descriptors بند کرتا ہے، اس لیے blocks یقینی طور پر واپس آ جاتے ہیں۔ اوپر کی demonstration میں holder وہ sleep ہے جسے آپ نے خود شروع کیا تھا، اس لیے اسے ختم کرنا کافی ہے۔
kill $holder
df -h .
df --output=used -B1 .
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/nullاستعمال شدہ bytes کا اس value سے موازنہ کریں جسے file بنانے سے پہلے record کیا تھا۔ دونوں دوبارہ برابر ہیں، اور find اب آپ کے descriptor کو report نہیں کرتا۔ اسی command سے تصدیق کرنا جس نے مسئلہ تلاش کیا تھا، برقرار رکھنے کے قابل اچھی عادت ہے۔
اس value میں تبدیلی دیکھنا df کو بار بار ہاتھ سے چلانے کے مقابلے میں آسان ہے۔ watch مقررہ وقفے سے command دہراتا ہے اور output کو اسی جگہ دوبارہ دکھاتا ہے، اس لیے watch df -h / used column میں ہونے والی تبدیلی دکھاتا ہے جب space واپس آتی ہے۔
جب totals ایک دوسرے سے مطابقت رکھتے ہوں اور disk پھر بھی full ہو
اگر df اور root du -x ایک دوسرے سے مطابقت رکھتے ہوں تو اس میں کوئی deleted file شامل نہیں ہے۔ باقی وجوہات نوعیت میں مختلف ہیں، اور ہر وجہ کی اپنی جانچ ہے۔
Inodes ختم ہو گئے، blocks نہیں
inode ایک file کا metadata محفوظ کرتا ہے۔ ext4 filesystem بناتے وقت inodes کی ایک مقررہ تعداد بناتا ہے، اس لیے filesystem میں free blocks موجود ہونے کے باوجود inodes ختم ہو سکتے ہیں۔ اس کے بعد نئی files بنانے میں ناکامی ہوتی ہے، حالانکہ df -h میں جگہ باقی دکھائی دیتی ہے۔
df -h /
df -i /پہلی command blocks اور دوسری inodes شمار کرتی ہے۔ دونوں کے use column کا موازنہ کریں۔ اگر block use کم ہو اور inode use اپنی حد تک پہنچ چکا ہو تو مسئلہ بہت بڑی تعداد میں موجود انتہائی چھوٹی files ہیں۔
df ایک ہی invocation میں -i اور --output کو قبول نہیں کرتا۔ اس لیے جب raw counts پڑھنے یا کسی دوسری command کو دینے ہوں تو inode fields کو نام سے منتخب کریں اور -i شامل نہ کریں۔
df --output=itotal,iused,iavail,ipcent /ان columns میں وہی accounting موجود ہوتی ہے جو df -i دکھاتا ہے، لیکن ایسی شکل میں جسے الگ الگ پڑھا جا سکتا ہے۔
Files کو bytes کے بجائے entries شمار کرکے تلاش کریں۔
sudo du --inodes -x -d 1 / 2>/dev/null | sort -rn | headجو directory سب سے اوپر آئے، اس پر اسی command کو ایک level نیچے دوبارہ چلائیں، یہاں تک کہ وہ tree مل جائے جو files بنا رہا ہے۔ اگر آپ کا du، --inodes کو support نہیں کرتا تو sudo find /var -xdev -type f | wc -l subtree کو سست طریقے سے شمار کرتا ہے۔
حل ان files کو delete یا move کرنا ہے۔ موجودہ ext4 filesystem میں inodes شامل نہیں کیے جا سکتے، کیونکہ ان کی تعداد mkfs کے وقت مقرر ہو جاتی ہے۔ اس لیے تعداد بڑھانے کا مطلب filesystem دوبارہ بنانا اور backup سے restore کرنا ہے۔ XFS ضرورت کے مطابق inodes allocate کرتا ہے، اس لیے اسے اسی طرح کی مقررہ حد کا سامنا نہیں ہوتا۔ جو machine containers چلاتی ہے وہ دونوں limits تک زیادہ جلد پہنچتی ہے، کیونکہ image layers میں بہت سی چھوٹی files ہوتی ہیں۔ ایسی machine پر VPS پر Docker کا disk usage کم کرنا مخصوص حل ہے، اور یہ filesystem کی عمومی صفائی کے مقابلے میں کہیں زیادہ جگہ واپس حاصل کرتا ہے۔
Mount point کے نیچے چھپی ہوئی جگہ
کسی directory میں mount ہونے سے پہلے بھی files موجود ہو سکتی ہیں۔ اس directory پر filesystem mount کریں تو نیچے موجود files اپنی جگہ رہتی ہیں: space اب بھی allocated ہوتا ہے، df میں اب بھی شمار ہوتا ہے، لیکن نام کے ذریعے قابل رسائی نہیں رہتا۔ du انہیں نہیں دیکھ سکتا کیونکہ mount ان files کو ڈھانپ دیتا ہے۔
اسے tmpfs کے ذریعے دکھائیں، جس کے لیے اضافی disk درکار نہیں ہوتی۔ اس حصے کے لیے ایسی machine درکار ہے جہاں آپ کو mount کرنے کی اجازت ہو، اس لیے یہ KVM VPS پر کام کرے گا۔
sudo mkdir -p /srv/covered
sudo cp /etc/services /srv/covered/
ls /srv/covered
sudo mount -t tmpfs tmpfs /srv/covered
ls /srv/covered
sudo umount /srv/covered
ls /srv/coveredدرمیان میں موجود ls ایک خالی directory دکھاتا ہے۔ copy کہیں نہیں گئی: وہ اب بھی root filesystem پر موجود ہے، اور unmount کرنے کے فوراً بعد دوبارہ نظر آ جائے گی۔ اب ایسی service کا تصور کریں جو کسی volume کے اس path پر mount ہونے سے پہلے ایک ماہ تک اسی path میں logs لکھتی رہی ہو۔
چلتے ہوئے server پر اصل files تلاش کرنے کے لیے root filesystem کو دوسری بار کسی مختلف جگہ پر mount کریں۔ bind mount ایک filesystem کو اس کے اندر mounted filesystems کے بغیر دکھاتا ہے۔
sudo mkdir -p /mnt/rootcheck
sudo mount --bind / /mnt/rootcheck
sudo du -xhs /mnt/rootcheck/* 2>/dev/null | sort -h
sudo umount /mnt/rootcheckاس listing میں جو کچھ normal path کے تحت موجود نہ ہو، وہ mount point کے نیچے دبا ہوا ہے۔ کام مکمل ہونے پر bind mount کو unmount کر دیں، ورنہ بعد میں du کو -x کے بغیر چلانے سے وہی files دو مرتبہ شمار ہوں گی۔
root کے لیے مختص بلاکس
ext4 اپنے بلاکس کا ایک حصہ root صارف کے لیے مختص رکھتا ہے، تاکہ مکمل بھر جانے والی disk کے باعث root صارف machine میں login کرکے اس کی مرمت نہ کر سکے۔ عام صارف کے طور پر چلنے والا process پہلے اس حد تک پہنچتا ہے، جبکہ df میں اب بھی تھوڑی جگہ دکھائی دیتی ہے۔ default فرض کرنے کے بجائے اپنی filesystem کی setting دیکھیں۔
dev=$(df --output=source / | tail -n 1)
sudo tune2fs -l "$dev" | grep -i 'block count'یہ کمانڈ total block count اور reserved block count کو ایک ہی units میں دکھاتی ہے، اس لیے دونوں کا ratio براہِ راست معلوم ہو جاتا ہے۔ df available column کو اس جگہ کے طور پر رپورٹ کرتا ہے جسے عام صارف اب بھی استعمال کر سکتا ہے۔ اسی لیے used اور available کا مجموعہ size سے کم آتا ہے۔ یہی فرق reserve ہے۔
اسے sudo tune2fs -m <percent> "$dev" سے تبدیل کریں۔ تبدیلی فوراً لاگو ہوتی ہے اور remount کی ضرورت نہیں ہوتی۔ الگ data filesystem پر reserve کم کرنا مناسب ہے۔ root filesystem پر اتنی جگہ ضرور مختص رہنے دیں کہ root اب بھی لکھ سکے، کیونکہ بالکل خالی root filesystem کی مرمت کرنا زیادہ مشکل ہوتا ہے۔ یہی reserve آپ کو lock out ہونے سے بھی بچاتا ہے: اگر filesystem میں کوئی جگہ باقی نہ ہو تو authorized_keys میں شامل کی جانے والی key مختصر لکھی جا سکتی ہے یا بالکل نہیں لکھی جا سکتی، اور اگلا login Permission denied (publickey) کا جواب دے گا۔ اس کی وجہ key نہیں ہوگی۔ tune2fs ext2، ext3 اور ext4 پر کام کرتا ہے۔ XFS میں اس کے مساوی کوئی setting نہیں ہے۔
جہاں du اکیلا آپ کو گمراہ کر سکتا ہے
du کی چار عادتیں ایسے مجموعے دکھاتی ہیں جو غلط معلوم ہوتے ہیں۔
- ہارڈ لنکس:
duکسی inode کو صرف ایک بار شمار کرتا ہے، خواہ کئی نام اس کی طرف اشارہ کر رہے ہوں۔ اس لیے ہارڈ لنکس سے بھرا ہوا درخت اپنی فائلوں کے مجموعے سے کم جگہ دکھاتا ہے۔ - Sparse files:
duصرف مختص کیے گئے blocks دکھاتا ہے، جبکہls -lظاہری سائز دکھاتا ہے۔ دوسرا عدد دیکھنے کے لیے--apparent-sizeشامل کریں۔ - اجازتیں: عام صارف کے طور پر چلانے پر
duان چیزوں کو نظرانداز کر دیتا ہے جنہیں وہ پڑھ نہیں سکتا، اس لیے مجموعہ کم دکھاتا ہے۔ اس کی ظاہر کردہ errors وہی ہوتی ہیں جنہیں لوگ/dev/nullپر redirect کر کے پڑھنا چھوڑ دیتے ہیں۔ - Filesystem boundaries:
-xکے بغیرdu /،/کے نیچے mount کیے گئے ہر filesystem کو شمار کرتا ہے، اس لیے اس کا مجموعہdf /کے دکھائے گئے مجموعے سے زیادہ ہو سکتا ہے۔
df کی بھی ایک عادت جاننا مفید ہے۔ یہ ہر filesystem کو الگ رپورٹ کرتا ہے، اس لیے اسے عین اس path پر چلائیں جسے failing write استعمال کر رہی ہے۔ ایک الگ /boot اپنے شیڈول کے مطابق بھرتا ہے، کیونکہ kernel packages جمع ہوتے رہتے ہیں، اور Ubuntu پر پرانے kernels ہٹانا / پر جگہ خالی کرنے سے مختلف کام ہے۔
حقیقی واقعے کے لیے عملی طریقۂ کار
df -h <path>اورdf -i <path>اس filesystem پر چلائیں جس پر ناکام write کا ہدف تھا؛ عادتاً/پر نہ چلائیں۔sudo du -xh -d 1 <mountpoint> 2>/dev/null | sort -hچلائیں، پھر سب سے بڑی directory کے اندر جا کر مزید جائزہ لیں۔- اگر
duاس استعمال کی وضاحت نہ کر سکے جسےdfused کے طور پر رپورٹ کرتا ہے، تو/procمیں ایسی deleted files تلاش کریں جو اب بھی open ہیں۔ - اگر دونوں نتائج باہم مطابقت رکھتے ہوں تو filesystem کو کسی اور مقام پر bind mount کریں اور mount point کے نیچے موجود files تلاش کریں۔
- اگر limit تک پہنچنے کی وجہ inode use ہو تو bytes کے بجائے files شمار کریں۔
اس طریقۂ کار میں ہر قدم ایک ایسا command ہے جس کے output کو آپ پڑھ سکتے ہیں۔ مسئلے کو درست کرنے اور محض اندازہ لگانے میں یہی بنیادی فرق ہے۔
FAQ
df کے مطابق ڈسک مکمل کیوں ہے، جبکہ du اس سے کہیں کم جگہ دکھاتا ہے؟
عام وجہ ایسی file ہوتی ہے جسے کسی process کے open رکھنے کے دوران delete کر دیا گیا ہو۔ file حذف کرنے سے اس کا directory entry ختم ہو جاتا ہے، اس لیے du کے پاس اسے تلاش کرنے کے لیے کوئی نام نہیں رہتا اور وہ اس کی گنتی روک دیتا ہے۔ inode اور اس کے blocks آخری descriptor کے close ہونے تک allocated رہتے ہیں، جبکہ df allocated blocks گنتا ہے۔ /proc/<pid>/fd میں ایسی symbolic links تلاش کریں جن کا target deleted کے طور پر نشان زد ہو؛ اس طرح file اور اسے کھلا رکھنے والا process دونوں مل جائیں گے۔ موازنے پر اعتماد کرنے سے پہلے تصدیق کریں کہ آپ نے du کو root کے طور پر اور -x کے ساتھ چلایا ہے، کیونکہ عام user ان directories کو خاموشی سے چھوڑ دیتا ہے جنہیں وہ پڑھ نہیں سکتا۔
lsof کے بغیر ایسی deleted file کیسے تلاش کروں جو اب بھی open ہو؟
open descriptors کا kernel کا اپنا record استعمال کریں۔ sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null ہر ایسے descriptor کی فہرست دیتا ہے جو بے نام file کی طرف اشارہ کر رہا ہو، اور process ID اس path کے اندر موجود ہوتی ہے جسے یہ دکھاتا ہے۔ ان descriptor paths میں سے کسی ایک پر sudo stat -Lc %s چلانے سے اس کا size معلوم ہو جاتا ہے، لہٰذا آپ انہیں sort کر کے متعلقہ file منتخب کر سکتے ہیں۔ اس کے لیے کسی package کی ضرورت نہیں، جو اہم ہے کیونکہ خالی جگہ نہ رکھنے والے filesystem پر package install کرنا ناکام ہو سکتا ہے۔
کیا process کو ختم کیے بغیر جگہ خالی کی جا سکتی ہے؟
کبھی کبھی۔ sudo truncate -s 0 /proc/<pid>/fd/<n> descriptor کے ذریعے اسی inode تک پہنچتا ہے اور process کو چلتا رکھتے ہوئے اس کے blocks release کر دیتا ہے۔ یہ طریقہ اس وقت سب سے صاف ہوتا ہے جب process نے file کو append mode میں open کیا ہو، کیونکہ اس کی writes ہمیشہ موجودہ end پر جاتی ہیں۔ اگر ایسا نہ ہو تو write offset اپنی سابقہ جگہ پر رہتا ہے، اور اگلی write شروع میں hole کے ساتھ file دوبارہ بناتی ہے۔ نتیجتاً reported size دوبارہ بڑھ جاتی ہے، جبکہ hole کے نیچے والے blocks free رہتے ہیں۔ unit کو restart کرنا، یا documentation میں نامزد signal کے ذریعے اسے logs دوبارہ open کرنے کا اشارہ دینا، ایسا حل ہے جس کے بعد sparse file باقی نہیں رہتی۔
df خالی جگہ دکھاتا ہے لیکن writes پھر بھی ناکام ہوتی ہیں۔ اور کیا وجہ ہو سکتی ہے؟
اسی path پر df -i کے ذریعے inodes چیک کریں، کیونکہ free blocks رکھنے والا مگر free inodes سے محروم filesystem نئی files بنانے سے انکار کر دیتا ہے۔ یہ بھی چیک کریں کہ write کسی non-root user کے طور پر ایسے ext4 filesystem پر تو نہیں چل رہی جہاں صرف reserved blocks باقی ہوں؛ device پر sudo tune2fs -l یہ صورت دکھا دے گا۔ تصدیق کریں کہ آپ وہی filesystem پڑھ رہے ہیں جسے write حقیقتاً target کرتی ہے، کیونکہ الگ /boot یا /var، / سے آزادانہ طور پر بھر سکتا ہے۔
du کا total df سے زیادہ کیوں دکھائی دیتا ہے؟
du کو -x کے بغیر چلانے سے دیے گئے path کے اندر mount کیے گئے ہر filesystem میں داخل ہو جاتا ہے۔ اس طرح یہ متعدد filesystems کو جمع کرتا ہے، جبکہ df صرف ایک filesystem کی وضاحت کرتا ہے۔ Bind mounts مسئلہ مزید بڑھا دیتے ہیں، کیونکہ ایک ہی files ان تمام paths کے تحت دوبارہ گنی جاتی ہیں جہاں وہ ظاہر ہوتی ہیں۔ -x شامل کریں تاکہ du ایک ہی filesystem تک محدود رہے، اور df کو بھی وہی path دیں، تاکہ دونوں commands ایک ہی چیز کی وضاحت کریں۔