df पूर्ण, पण du कमी: डिस्कची जागा कुठे आहे?
df पूर्ण दाखवते पण du जागा शोधत नाही? प्रक्रिया हटवलेली फाइल उघडी ठेवते तेव्हा lsof ने ती शोधा; inode, mount point आणि root साठी राखीव blocksही तपासा.
df डिस्क पूर्ण असल्याचे का दाखवते आणि du वेगळे का सांगते
df डिस्क पूर्ण असल्याचे दाखवते, तर du जागा शोधू शकत नाही, कारण एखादी प्रक्रिया हटवलेली फाइल अजूनही उघडी ठेवून आहे. फाइल हटवल्यावर तिचे नाव directory मधून काढले जाते. त्या inode कडे निर्देश करणारा शेवटचा उघडा file descriptor बंद झाल्यावरच data blocks मुक्त केले जातात. du फाइलची नावे तपासते, त्यामुळे ते काहीही मोजत नाही. df filesystem कडे किती blocks allocate केले आहेत हे विचारते, त्यामुळे नाव नसलेली फाइल अजूनही त्यात मोजली जाते.
या मार्गदर्शकात आधीपासून install असलेल्या साधनांसह साध्या Ubuntu VPS वर ही स्थिती पुन्हा निर्माण केली आहे. /proc द्वारे फाइल धरून ठेवणारी प्रक्रिया शोधली आहे आणि reboot न करता जागा मुक्त केली आहे. याच लक्षणामागील इतर कारणेही पुढे दिली आहेत: उपलब्ध नसलेले inode table entries, mount point अंतर्गत लपलेल्या फाइल्स आणि root साठी राखीव blocks.
प्रत्येक command चालवा आणि स्वतःचा output वाचा. मूल्ये तुमच्या disk वर अवलंबून असतात. त्यामुळे मार्गदर्शकात दिलेल्या आकड्याशी तुलना करण्याऐवजी, तुमच्या मशीनवरील आधीची आणि नंतरची स्थिती तुलना करा.
df काय मोजते आणि du काय मोजते
df (disk free) प्रत्येक mounted filesystem कडून त्याचा स्वतंत्र हिशोब मागते: एकूण किती blocks आहेत, किती allocated आहेत आणि किती free आहेत. ते कधीही directory उघडत नाही. या उत्तरात प्रत्येक allocated block समाविष्ट असतो, त्यात कोणतीही directory entry निर्देश करत नसलेल्या file शी संबंधित blocks देखील येतात.
du (disk usage) याच्या उलट कार्य करते. तुम्ही दिलेल्या path पासून ते सुरू होते, directories वाचते, सापडलेल्या प्रत्येक entry वर stat करते आणि blocks ची बेरीज करते. नाव नसलेली file त्याला दिसत नाही. तसेच, ज्या directory वाचण्याची परवानगी त्याला नाही तीही दिसत नाही. म्हणून सामान्य user ला root पेक्षा कमी total मिळतो. या तुलनेवरून कोणताही निष्कर्ष काढण्यापूर्वी du ला sudo अंतर्गत चालवा.
दोन्हींची तुलना करताना प्रत्येक वेळी दोन options महत्त्वाचे असतात.
-xduला एकाच filesystem पुरते मर्यादित ठेवते. हे न वापरल्यासdu //खाली mounted असलेल्या प्रत्येक filesystem मध्ये प्रवेश करते आणिdf /कधीच मोजत नसलेला total तयार करते.-sप्रत्येक directory साठी एक ओळ देण्याऐवजी प्रत्येक argument साठी एक summary line छापते.
यामुळे तुम्हाला महत्त्वाच्या filesystem वर ही जोडी एकाच वेळी चालवता येते.
df -h /
sudo du -xhs / 2>/dev/nulldf त्वरित उत्तर देते. मोठ्या filesystem वर du ला काही मिनिटे लागतात, कारण मार्गातील प्रत्येक file वर ते stat करते. दोन्ही totals मध्ये मोठा फरक असेल आणि du हे root म्हणून -x सह चालवले असेल, तर गहाळ जागा नाव नसलेल्या एखाद्या allocated वस्तूकडे आहे.
जाणूनबुजून विसंगती पुन्हा निर्माण करा
हे काम चाचणी VPS वर करा. खालील सर्व आदेश bash आणि coreutils वापरतात, त्यामुळे काहीही install केले जात नाही.
/var/tmp असलेल्या filesystem ची प्रारंभिक स्थिती नोंदवा.
cd /var/tmp
df -h .
df --output=used -B1 .दुसरा आदेश rounding न करता वापरलेले bytes दाखवतो. त्यामुळे शेवटची पडताळणी अचूक होते.
आता एक file तयार करा. त्याचा size मशीनने स्वतः दाखवलेल्या free space वरून घेतला जातो. त्यामुळे तुमच्याकडे असलेल्या कोणत्याही 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 bytes न लिहिता प्रत्यक्ष blocks राखून ठेवते. त्यामुळे ती लगेच पूर्ण होते. ज्या filesystem मध्ये हे समर्थित नसते, तिथे command fail होते. अशा वेळी head -c $((free / 10)) /dev/zero > ghost.bin bytes प्रत्यक्ष लिहून तेच काम करते.
या df -h . ची तुम्ही नोंदवलेल्या स्थितीशी तुलना करा. 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 उघडते आणि descriptor sleep कडे देते; sleep तो open ठेवते. $! मध्ये त्या background job चा process ID असतो. त्यानंतर rm descriptor अजून open असतानाच file चे नाव काढून टाकते.
Output वाचा. नाव काढून टाकलेले असल्यामुळे ls ला file सापडत नाही. du पुन्हा सुरुवातीच्या स्थितीजवळ आलेले असते, कारण ते names वरून माहिती मोजते. Blocks अजूनही allocated असल्यामुळे df मध्ये बदल झालेला नसतो. आता filesystem आणि directory tree यांच्यात विसंगती निर्माण झाली आहे. त्यांच्यातील फरक म्हणजे तुम्ही नुकतीच delete केलेली file आहे.
हटविलेली फाइल कोणती प्रक्रिया उघडी ठेवत आहे ते शोधा
प्रत्येक उघडा file descriptor /proc/<pid>/fd/ अंतर्गत तो ज्या फाइलचा संदर्भ देतो तिच्याकडे निर्देश करणाऱ्या symbolic link म्हणून दिसतो. फाइल unlink केल्यावर kernel त्या link च्या target ला deleted म्हणून चिन्हांकित करतो. त्यामुळे holder शोधण्यासाठी, ज्याच्या target मध्ये हे marker आहे अशी link शोधावी लागते.
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null-lname symbolic link चे नाव नव्हे, तर तिच्या target शी जुळवते; %p descriptor चा path दाखवते आणि %l तो कशाकडे निर्देश करतो ते दाखवते. छापलेल्या path मधील दुसरा घटक process ID असतो. sudo वापरून ते चालवा; अन्यथा /proc/<pid>/fd मधून फक्त आपल्या स्वतःच्या processes ची माहिती वाचता येते. find चालू processes मधून फिरत असताना काही process बंद झाल्यास निर्माण होणारा stderr मधील अनावश्यक output redirect मुळे वगळला जातो.
व्यस्त सर्व्हरवर कोणत्याही वेळी अनेक हटविलेल्या 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 link चा मागोवा घेत inode पर्यंत पोहोचते. त्यामुळे %s आता नाव नसलेल्या file चा size दाखवते. त्या संख्येवर sorting केल्यास सर्वात मोठी file प्रथम येते.
यानंतर सर्वात वर असलेल्या descriptor मागील process ओळखा. त्या यादीतील पहिल्या path मध्ये आवश्यक दोन्ही numbers असतात. त्यामुळे आधी ते variables मध्ये ठेवा. PID आणि N यांच्या जागी तुमच्या listing मध्ये दिसलेली मूल्ये द्या.
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 दाखवते. या दोन्ही माहितीमधून महत्त्वाच्या प्रश्नाचे उत्तर मिळते: कोणती service ही file जिवंत ठेवत आहे.
मशीनवर आधीपासून lsof असल्यास, sudo lsof +L1 ज्या open files चा link count शून्यावर आला आहे त्या files ची यादी करते आणि त्यांच्या sizes एका table मध्ये दाखवते. Minimal Ubuntu image मध्ये ते उपलब्ध नसते. तसेच free space नसलेल्या filesystem वर package install करणे स्वतःच अयशस्वी होऊ शकते. त्यामुळे /proc ने केलेला walk ही नेहमी कार्य करणारी पद्धत आहे.
रीबूट न करता जागा मोकळी करा
रीबूट केल्याने समस्या सुटते, पण तो पहिला उपाय नसावा: त्यामुळे सेवा बंद होते आणि पुरावे नष्ट होतात. यासाठी चार सौम्य पर्याय आहेत. ते पुढील क्रमाने वापरा.
डेटा अद्याप हवा असल्यास, प्रथम तो बाहेर कॉपी करा. descriptor path वाचल्याने live inode वाचला जातो.
sudo cp /proc/<pid>/fd/<n> /root/recovered.logही एकमेव परिस्थिती आहे ज्यात deleted file परत मिळवणे सोपे असते. म्हणूनच rm -rf ने हटवलेल्या फाइल्स पुनर्प्राप्त करणे याची सुरुवात एखाद्या process कडे ती file अजूनही open आहे का, हे विचारून होते. शेवटचा descriptor बंद झाल्यावर हा मार्ग उपलब्ध राहत नाही.
दुसरे म्हणजे, descriptor द्वारे file रिकामी करा. /proc path त्याच inode कडे निर्देश करतो. त्यामुळे file truncate केल्यावर process चालू ठेवून blocks मोकळे करता येतात.
sudo truncate -s 0 "/proc/$pid/fd/$n"
df -h /writer ने file append mode मध्ये उघडली असल्यास हे व्यवस्थित कार्य करते, कारण त्यानंतर प्रत्येक write file च्या सध्याच्या शेवटी जाते. तसे नसल्यास process जुना write offset ठेवतो. त्यामुळे त्याचा पुढील write file मध्ये बराच पुढे जाऊन होतो आणि सुरुवातीला hole असलेली file पुन्हा तयार करतो. Hole साठी allocation होत नाही. त्यामुळे blocks मोकळे राहतात आणि df ने नुकतीच परत केलेली जागा तशीच मोकळी राहते. बदलणारी गोष्ट फक्त size असते: process ने write केल्यानंतर sudo stat -L "/proc/$pid/fd/$n" पुन्हा चालवा. ते जुना size आणि त्याच्याशी जुळत नसलेली block count दाखवते. Size देखील शून्यापासून सुरू करायचा असल्यास process restart करा.
तिसरे म्हणजे, सेवेने logs पुन्हा उघडावेत अशी विनंती करा. एखादी log file त्याच्या खालीच delete झाल्यानंतर ती धरून ठेवणारा daemon ही या समस्येची सामान्य वास्तविक परिस्थिती आहे. अनेक daemons signal मिळाल्यावर त्यांच्या log files पुन्हा उघडतात: nginx साठी SIGUSR1 आणि rsyslog साठी SIGHUP वापरले जाते. अंदाज लावण्याऐवजी संबंधित daemon चे documentation तपासा, कारण चुकीच्या daemon ला चुकीचा signal पाठवल्यास तो बंद होऊ शकतो.
sudo systemctl kill -s USR1 nginxयामुळे systemd ने unit चा main process म्हणून नोंदवलेल्या process कडे signal पाठवला जातो. त्यामुळे daemon प्रत्यक्षात ज्या प्रकारे सुरू होतो त्यासाठी unit मध्ये चुकीचा Type= घोषित केलेला असल्यास, तुमचा signal deleted file कधीही धरून न ठेवलेल्या process कडे जाऊ शकतो आणि जागा मोकळी होत नाही.
चौथे म्हणजे, unit restart करा. sudo systemctl restart <unit> जुन्या process ने धरलेले सर्व descriptors बंद करतो. त्यामुळे blocks निश्चितपणे परत मोकळे होतात. वरील उदाहरणात holder हा तुम्ही स्वतः सुरू केलेला sleep आहे. त्यामुळे तो बंद करणे पुरेसे आहे.
kill $holder
df -h .
df --output=used -B1 .
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/nullfile तयार करण्यापूर्वी नोंदवलेल्या value शी used bytes ची तुलना करा. दोन्ही पुन्हा जुळतात आणि find तुमचा descriptor दाखवत नाही. समस्या शोधण्यासाठी वापरलेलीच command पुन्हा वापरून पडताळणी करणे ही सवय ठेवण्यासारखी आहे.
ही value बदलताना पाहणे df वारंवार manually चालवण्यापेक्षा सोपे आहे. watch ठरावीक interval ने command पुन्हा चालवतो आणि output त्याच ठिकाणी पुन्हा दाखवतो. त्यामुळे जागा परत मोकळी होत असताना watch df -h / used column मधील बदल दाखवतो.
जेव्हा एकूण आकडे जुळतात, पण disk तरीही भरलेली असते
df आणि root du -x यांचे आकडे एकमेकांशी जुळत असतील, तर कोणतीही deleted file कारणीभूत नाही. उरलेली कारणे वेगळ्या प्रकारची आहेत आणि प्रत्येक कारणासाठी स्वतंत्र तपासणी आहे.
Inode संपले, blocks नाही
Inode मध्ये एका फाइलचा metadata साठवला जातो. Filesystem तयार करताना ext4 निश्चित संख्येने inodes तयार करते. त्यामुळे filesystem मध्ये blocks उपलब्ध असतानाही inodes संपू शकतात. अशा वेळी df -h मध्ये जागा उपलब्ध दिसत असली, तरी नवीन फाइल तयार करणे अयशस्वी होते.
df -h /
df -i /पहिली command blocks मोजते आणि दुसरी inodes मोजते. दोन्हीमधील use column ची तुलना करा. Block use कमी आणि inode use मर्यादेवर असल्यास, समस्या अतिशय मोठ्या संख्येने असलेल्या अतिशय लहान फाइल्सची आहे.
df एकाच invocation मध्ये -i आणि --output नाकारते. त्यामुळे raw counts वाचायचे असतील किंवा ते दुसऱ्या command कडे द्यायचे असतील, तर inode fields नावाने निवडा आणि -i वगळा.
df --output=itotal,iused,iavail,ipcent /या columns मध्ये df -i दाखवत असलेलेच accounting असते. मात्र ते स्वतंत्रपणे तपासता येईल अशा स्वरूपात असते.
Bytes ऐवजी entries मोजून फाइल्स शोधा.
sudo du --inodes -x -d 1 / 2>/dev/null | sort -rn | headसर्वाधिक entries असलेल्या directory वर हीच command एक स्तर खाली पुन्हा चालवा. फाइल्स तयार करणारे tree सापडेपर्यंत ही प्रक्रिया सुरू ठेवा. तुमचे du --inodes ला support करत नसल्यास, sudo find /var -xdev -type f | wc -l subtree हळू पद्धतीने मोजते.
उपाय म्हणजे त्या फाइल्स delete करणे किंवा हलवणे. विद्यमान ext4 filesystem मध्ये inodes वाढवता येत नाहीत, कारण mkfs वेळी त्यांची संख्या निश्चित केली जाते. त्यामुळे inode count वाढवण्यासाठी filesystem पुन्हा तयार करून backup मधून restore करावे लागते. XFS गरजेनुसार inodes allocate करते, त्यामुळे त्याला त्याच प्रकारची निश्चित मर्यादा येत नाही. Containers चालवणाऱ्या machine वर दोन्ही मर्यादा बहुतेक machines पेक्षा लवकर गाठल्या जातात, कारण image layers मध्ये अनेक लहान फाइल्स असतात. अशा machine वर VPS वरील Docker चा disk usage prune करणे हाच विशिष्ट उपाय आहे. Filesystem च्या सर्वसाधारण sweep पेक्षा यामुळे कितीतरी अधिक जागा मोकळी होते.
माउंट पॉइंटखाली लपलेली जागा
एखाद्या directory वर काहीही mount करण्यापूर्वी त्यात files ठेवता येतात. त्या directory वर filesystem mount केल्यावर आतील files जिथे होत्या तिथेच राहतात: त्या अजूनही allocated असतात, df मध्ये मोजल्या जातात आणि नावाने उपलब्ध राहत नाहीत. Mount त्यांना झाकत असल्यामुळे du त्यांना पाहू शकत नाही.
हे tmpfs वापरून दाखवता येते. त्यासाठी अतिरिक्त disk space लागत नाही. या भागासाठी mount करण्याची परवानगी असलेले machine आवश्यक आहे, त्यामुळे तो 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 केल्यावर पुन्हा दिसते. आता कल्पना करा की एखाद्या volume ने त्या path वर mount होण्यापूर्वी एखाद्या service ने महिनाभर त्यात logs लिहिले.
चालू server वर मूळ files शोधण्यासाठी root filesystem दुसऱ्यांदा वेगळ्या ठिकाणी mount करा. Bind mount आत mount केलेले filesystems वगळून एका filesystem चे दर्शन घडवतो.
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 मध्ये दिसणारी पण नेहमीच्या path खाली न दिसणारी प्रत्येक गोष्ट mount point खाली लपलेली असते. काम पूर्ण झाल्यावर bind mount unmount करा; अन्यथा -x शिवाय केलेला पुढील du त्याच files दोनदा मोजेल.
root साठी राखीव ठेवलेले blocks
ext4 त्यातील काही blocks root user साठी राखून ठेवते. त्यामुळे disk पूर्ण भरली तरी root ला login करून machine दुरुस्त करता येते. सामान्य user म्हणून चालणारी 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 सामान्य user अजून वापरू शकत असलेली जागा दाखवतो. म्हणून used आणि available यांची बेरीज size पेक्षा कमी येते. हा फरक म्हणजे reserve.
ही setting sudo tune2fs -m <percent> "$dev" ने बदला. हा बदल त्वरित लागू होतो आणि remount आवश्यक नसते. स्वतंत्र data filesystem वरील reserve कमी करणे योग्य ठरू शकते. मात्र root filesystem वर root अजून लिहू शकेल इतकी जागा राखून ठेवा. root filesystem वर अजिबात मोकळी जागा नसल्यास दुरुस्ती करणे अधिक कठीण होते. ही reserve तुम्हाला login पासून पूर्णपणे lock out होण्यापासूनही वाचवते. filesystem वर जागा शिल्लक नसताना authorized_keys मध्ये जोडलेली key अपूर्ण लिहिली जाऊ शकते किंवा अजिबात लिहिली जाऊ शकत नाही. त्यानंतरच्या login वेळी Permission denied (publickey) असे उत्तर मिळते. याचे कारण key नसते. tune2fs ext2, ext3 आणि ext4 वर कार्य करते. XFS मध्ये यासाठी equivalent setting नाही.
du स्वतः दिशाभूल करू शकते अशा परिस्थिती
duच्या चार सवयींमुळे चुकीचे दिसणारे एकूण आकडे मिळतात.
- Hard links: अनेक नावे एकाच inode कडे निर्देश करत असली तरी
duinode एकदाच मोजते. त्यामुळे hard links ने भरलेल्या directory tree चा आकडा त्यातील files च्या बेरजेपेक्षा कमी दिसतो. - Sparse files: प्रत्यक्षात allocate झालेले blocks
duदाखवते, तर apparent sizels -lदाखवते. दुसरा आकडा पाहण्यासाठी--apparent-sizeजोडा. - Permissions: ordinary user म्हणून चालवल्यास, जे वाचता येत नाही ते
duवगळते आणि कमी आकडा दाखवते. ते दाखवणाऱ्या errors लोक/dev/nullकडे redirect करून वाचणे थांबवतात. - Filesystem boundaries:
-xशिवायdu /,/च्या खाली mounted असलेले प्रत्येक filesystem मोजते. त्यामुळे त्याचा एकूण आकडाdf /दाखवते त्यापेक्षा जास्त असू शकतो.
dfचीही एक महत्त्वाची सवय आहे. ते प्रत्येक filesystem स्वतंत्रपणे दाखवते. त्यामुळे write ज्या अचूक path वर अपयशी ठरते त्या path वर ते चालवा. स्वतंत्र /boot kernel packages जमा होत असताना स्वतःच्या schedule नुसार भरते. Ubuntu वरील जुने kernels काढणे हे /वरील जागा मोकळी करण्यापेक्षा वेगळे काम आहे.
प्रत्यक्ष घटनेत अनुसरण्याचा क्रम
- अयशस्वी write ज्या filesystem वर करण्याचे लक्ष्य होते, त्यावर
df -h <path>आणिdf -i <path>चालवा; सवयीने/वर चालवू नका. sudo du -xh -d 1 <mountpoint> 2>/dev/null | sort -hचालवा आणि नंतर सर्वात मोठ्या directory मध्ये पुढे जा.dfमध्ये वापरलेली जागा दाखविल्याचेduमधून स्पष्ट होत नसेल, तर अजून open असलेल्या deleted files साठी/procमध्ये शोध घ्या.- दोन्ही परिणाम जुळत असल्यास, filesystem दुसऱ्या ठिकाणी bind mount करा आणि mount point अंतर्गत असलेल्या files शोधा.
- मर्यादा inode वापरामुळे गाठली असल्यास, bytes ऐवजी files मोजा.
वरील प्रत्येक पायरीमध्ये असा command आहे ज्याचे output तुम्ही वाचू शकता. या समस्येचे निराकरण करण्यामध्ये आणि अंदाजाने कृती करण्यामध्ये हाच फरक आहे.
FAQ
df डिस्क पूर्ण असल्याचे दाखवते, पण du ला त्यापेक्षा खूपच कमी वापर आढळतो. असे का?
याचे सामान्य कारण म्हणजे एखादी फाइल delete केली गेली असताना एखाद्या process ने ती open ठेवलेली असते. फाइल remove केल्यावर तिची directory entry काढली जाते. त्यामुळे du कडे तपासण्यासाठी नाव उरत नाही आणि ती फाइल मोजणे थांबवते. शेवटचा descriptor बंद होईपर्यंत inode आणि त्याचे blocks allocated राहतात. df allocated blocks मोजते. /proc/<pid>/fd मध्ये target deleted म्हणून चिन्हांकित असलेल्या symbolic links शोधा. त्यातून फाइल आणि ती धरून ठेवणारा process दोन्ही सापडतात. या तुलना करण्यापूर्वी du root म्हणून आणि -x सह चालवले आहे याची खात्री करा. कारण सामान्य user ला वाचता न येणाऱ्या directories तो कोणतीही सूचना न देता वगळतो.
lsof शिवाय अजून open असलेली deleted file कशी शोधायची?
Open descriptors ची kernel मधील नोंद वापरा. sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null कोणत्याही नावाशिवाय असलेल्या फाइलकडे निर्देश करणारा प्रत्येक descriptor दाखवते. दाखवलेल्या path मध्ये process ID असते. त्या descriptor paths पैकी एखाद्यावर sudo stat -Lc %s चालवल्यास त्याचा size कळतो. त्यामुळे त्यांची क्रमवारी लावून आवश्यक फाइल निवडता येते. यासाठी कोणतेही package आवश्यक नाही. Free space नसलेल्या filesystem वर package install करणे अपयशी ठरू शकते, म्हणून हे महत्त्वाचे आहे.
Process बंद न करता space मोकळी करता येते का?
कधीकधी करता येते. sudo truncate -s 0 /proc/<pid>/fd/<n> descriptor द्वारे त्याच inode पर्यंत पोहोचते आणि process चालू ठेवून त्याचे blocks मोकळे करते. Process ने फाइल append mode मध्ये open केली असेल, तर ही सर्वात स्वच्छ पद्धत आहे. कारण त्याचे writes नेहमी सध्याच्या शेवटी होतात. तसे नसल्यास write offset जिथे होता तिथेच राहतो. पुढील write सुरुवातीला hole असलेली फाइल पुन्हा तयार करते. त्यामुळे दाखवलेला size पुन्हा वाढतो, पण hole खालील blocks मोकळे राहतात. Unit restart करणे किंवा documentation मध्ये नमूद केलेल्या signal ने logs पुन्हा open करण्यास सांगणे हा योग्य उपाय आहे. त्यामुळे शेवटी sparse file राहत नाही.
df free space दाखवते, पण writes तरीही अपयशी ठरतात. आणखी काय कारण असू शकते?
त्याच path वर df -i वापरून inodes तपासा. कारण blocks मोकळे असले तरी inodes मोकळे नसलेल्या filesystem मध्ये नवीन files तयार करता येत नाहीत. ext4 filesystem वर write करणारा non-root user वापरात आहे का ते तपासा. फक्त reserved blocks उरले असल्यास अशी अडचण येऊ शकते. Device वर sudo tune2fs -l वापरल्यास हे दिसेल. तुम्ही write प्रत्यक्ष ज्या filesystem ला लक्ष्य करते तेच filesystem तपासत आहात याची खात्री करा. स्वतंत्र /boot किंवा /var हे / पासून स्वतंत्रपणे भरू शकते.
du चा एकूण आकडा df पेक्षा मोठा का दाखवला जातो?
du मध्ये -x नसल्यास तुम्ही दिलेल्या path खाली mounted असलेल्या प्रत्येक filesystem मध्ये ते प्रवेश करते. त्यामुळे अनेक filesystems ची बेरीज होते, तर df एका filesystem चे वर्णन करते. Bind mounts मुळे ही समस्या वाढते. एकाच files ना ते ज्या प्रत्येक path खाली दिसतात त्या प्रत्येक ठिकाणी मोजले जाते. -x जोडा, जेणेकरून du एका filesystem पुरते मर्यादित राहील. तसेच df ला तोच path द्या, म्हणजे दोन्ही commands एकाच गोष्टीचे वर्णन करतील.