df डिस्क फुल दिखाता है पर du नहीं: जगह कैसे खाली करें
VPS पर df और du के बीच अंतर क्यों आता है? जब फाइल डिलीट करने के बाद भी डिस्क फुल दिखे तो lsof कमांड से ओपन फाइल हैंडल ढूंढें और बिना रीबूट किए स्टोरेज स्पेस वापस पाएं।
df डिस्क फुल क्यों बताता है जबकि du कुछ और दिखाता है
df डिस्क को फुल रिपोर्ट करता है जबकि du जगह नहीं ढूंढ पाता क्योंकि कोई process अभी भी एक ऐसी फाइल को होल्ड किए हुए है जिसे delete किया जा चुका है। किसी फाइल को delete करने से केवल उसका नाम directory से हटता है। डेटा ब्लॉक्स तभी रिलीज होते हैं जब उस inode को पॉइंट करने वाला अंतिम open file descriptor बंद हो जाता है। du नामों को ट्रैक करता है, इसलिए यह कुछ भी काउंट नहीं करता। df फाइलसिस्टम से पूछता है कि कितने ब्लॉक्स allocate किए गए हैं, इसलिए यह उस फाइल को भी काउंट करता है जिसका अब कोई नाम नहीं है।
यह गाइड एक साधारण Ubuntu VPS पर इसे दोहराती है, पहले से इंस्टॉल किए गए टूल्स का उपयोग करती है, /proc के माध्यम से होल्ड करने वाली process को ढूंढती है, और बिना reboot किए जगह खाली करती है। इसी लक्षण के अन्य कारण निम्नलिखित हैं: बिना फ्री एंट्री वाली inode टेबल, माउंट पॉइंट के नीचे दबी फाइलें, और root के लिए आरक्षित ब्लॉक्स।
प्रत्येक कमांड चलाएं और अपना आउटपुट पढ़ें। मान आपकी डिस्क पर निर्भर करते हैं, इसलिए गाइड में छपे आंकड़ों से तुलना करने के बजाय अपनी मशीन पर पहले और बाद की स्थिति की तुलना करें।
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 बिना rounding के उपयोग किए गए bytes को print करता है, जिससे अंत में की गई जाँच सटीक रहती है।
अब एक file बनाएँ। इसका आकार उस free space से आता है जिसकी रिपोर्ट machine स्वयं देती है, इसलिए यह प्रदर्शन आपकी 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 का मान बन जाता है। यदि यह syntax आपके लिए नया है, तो bash में command substitution इसे विस्तार से कवर करता है। fallocate बिना लिखे वास्तविक blocks को reserve करता है, यही कारण है कि यह तुरंत पूरा हो जाता है। जिस filesystem पर यह support नहीं होता, वहाँ यह command fail हो जाता है, और head -c $((free / 10)) /dev/zero > ghost.bin bytes को लिखकर वही काम करता है।
इस df -h . की तुलना उस स्थिति से करें जिसे आपने रिकॉर्ड किया था। used column बढ़ गया है और available column घट गया है।
अब file को किसी अन्य process से open रखें, फिर उसे delete कर दें।
sleep infinity < ghost.bin &
holder=$!
rm ghost.bin
ls -l ghost.bin
df -h .
sudo du -xhs . 2>/dev/nullredirection ही पूरी तरकीब है। sleep infinity < ghost.bin & एक background process शुरू करता है जिसका standard input वह file है, इसलिए shell file को open करता है और descriptor को sleep को सौंप देता है, जो इसे open रखता है। $! उस background job की process ID को hold करता है। rm फिर नाम को हटा देता है जबकि descriptor अभी भी open है।
output पढ़ें। ls file को नहीं ढूँढ सकता, क्योंकि नाम हट चुका है। du लगभग वहीं वापस आ गया है जहाँ से शुरू हुआ था, क्योंकि यह नामों को scan करता है। df नहीं बदला है, क्योंकि blocks अभी भी allocated हैं। filesystem और directory tree अब असहमत हैं, और उनके बीच का अंतर वही file है जिसे आपने अभी delete किया है।
डिलीट की गई फाइल को होल्ड करने वाली प्रोसेस ढूँढें
हर खुली फाइल का फाइल डिस्क्रिप्टर /proc/<pid>/fd/ के अंतर्गत उस फाइल के सिम्बॉलिक लिंक के रूप में दिखाई देता है जिसे वह रेफर करता है। जब फाइल को अनलिंक कर दिया जाता है, तो कर्नल उस लिंक के टारगेट को डिलीट के रूप में मार्क कर देता है। इसलिए, होल्डर को खोजने का मतलब है ऐसा लिंक ढूँढना जिसका टारगेट यह मार्कर रखता हो।
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/nullsudo lsof +L1
-lname सिम्बॉलिक लिंक के नाम के बजाय उसके टारगेट से मैच करता है, %p डिस्क्रिप्टर पाथ को प्रिंट करता है, और %l यह प्रिंट करता है कि वह कहाँ पॉइंट कर रहा है। प्रोसेस ID उसके द्वारा प्रिंट किए गए पाथ का दूसरा एलिमेंट होता है। इसे sudo के साथ चलाएं, क्योंकि अन्यथा आप केवल अपनी प्रोसेस के लिए /proc/<pid>/fd पढ़ पाएंगे। stderr रीडायरेक्ट उन प्रोसेस से आने वाले शोर को हटा देता है जो find के चलने के दौरान समाप्त हो जाती हैं।
एक व्यस्त सर्वर पर किसी भी समय कई डिलीट की गई फाइलें होल्ड पर रहती हैं, और उनमें से अधिकांश छोटी और हानिरहित होती हैं। उन्हें साइज के अनुसार सॉर्ट करें ताकि केवल महत्वपूर्ण फाइलें ही सबसे ऊपर रहें।
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 | headsudo lsof +L1 | sort -k7 -n
stat -L लिंक को सीधे इनोड (inode) तक फॉलो करता है, इसलिए %s उस फाइल का साइज रिपोर्ट करता है जिसका अब कोई नाम नहीं है। उस नंबर पर सॉर्ट करने से सबसे बड़ी फाइल सबसे पहले आ जाती है।
फिर जीतने वाले डिस्क्रिप्टर के पीछे की प्रोसेस की पहचान करें। उस लिस्ट के सबसे ऊपर मौजूद पाथ में वे दोनों नंबर होते हैं जिनकी आपको आवश्यकता है, इसलिए उन्हें पहले वेरिएबल में डालें, और PID तथा N को अपनी लिस्टिंग में प्रिंट हुए नंबरों से बदलें।
pid=PID
n=N
ps -o pid,user,etime,args -p "$pid"
sudo stat -L "/proc/$pid/fd/$n"PID=...; N=...; ps -p $PID -o comm,etime; stat /proc/$PID/fd/$N
ps प्रोग्राम का नाम बताता है और दिखाता है कि वह कितनी देर से चल रहा है। stat -L डिलीट किए गए इनोड का साइज और एलोकेटेड ब्लॉक काउंट प्रिंट करता है। साथ मिलकर वे उस महत्वपूर्ण प्रश्न का उत्तर देते हैं: कौन सी सर्विस इस फाइल को जीवित रख रही है।
यदि मशीन पर पहले से lsof मौजूद है, तो sudo lsof +L1 उन खुली फाइलों को लिस्ट करता है जिनका लिंक काउंट शून्य हो गया है और एक टेबल में उनका साइज दिखाता है। यह एक मिनिमल Ubuntu इमेज पर मौजूद नहीं होता है, और बिना खाली स्पेस वाले फाइलसिस्टम पर पैकेज इंस्टॉल करना खुद विफल हो सकता है, इसलिए /proc वॉक वह वर्जन है जो हमेशा काम करता है।
Reboot किए बिना जगह खाली करना
Reboot करने से समस्या हल हो जाती है, लेकिन यह पहला कदम नहीं होना चाहिए: इससे service बंद हो जाती है और सबूत नष्ट हो जाते हैं। इसे हल करने के चार बेहतर विकल्प हैं, जिन्हें इसी क्रम में आज़माना चाहिए।
सबसे पहले, यदि आपको डेटा की आवश्यकता है, तो उसे कॉपी कर लें। Descriptor path को पढ़ने से live inode पढ़ा जाता है।
sudo cp /proc/<pid>/fd/<n> /root/recovered.logयह एकमात्र ऐसी स्थिति है जहाँ डिलीट की गई फाइल को वापस पाना आसान है, इसीलिए rm -rf से डिलीट की गई फाइलों को रिकवर करना इस सवाल से शुरू होता है कि क्या किसी process ने अभी भी फाइल को open रखा है। एक बार आखिरी descriptor बंद हो जाने पर, यह रास्ता खत्म हो जाता है।
दूसरा, descriptor के माध्यम से फाइल को खाली करें। /proc path उसी inode की ओर ले जाता है, इसलिए इसे truncate करने से blocks रिलीज़ हो जाते हैं और process चलती रहती है।
sudo truncate -s 0 "/proc/$pid/fd/$n"
df -h /यह तब अच्छी तरह काम करता है जब writer ने फाइल को append mode में open किया हो, क्योंकि हर write ऑपरेशन फाइल के अंत में होता है। यदि ऐसा नहीं है, तो process अपना पुराना write offset बनाए रखती है, जिससे उसका अगला write फाइल में काफी आगे जाकर होता है और शुरुआत में एक hole बन जाता है। Hole के लिए blocks allocate नहीं होते, इसलिए blocks खाली रहते हैं और df जगह को मुक्त रखता है। जो वापस आता है वह केवल size है: process के write करने के बाद फिर से sudo stat -L "/proc/$pid/fd/$n" चलाएं, तो यह पुराने size को ऐसे block count के साथ दिखाएगा जो अब उससे मेल नहीं खाता। जब आप चाहते हैं कि size भी शून्य से शुरू हो, तो process को restart करें।
तीसरा, service को अपने logs फिर से open करने के लिए कहें। जिस daemon की log file उसके नीचे से डिलीट कर दी गई हो, वह इस समस्या का एक सामान्य वास्तविक उदाहरण है। कई daemons signal मिलने पर अपनी log files को फिर से open कर लेते हैं: nginx SIGUSR1 का उपयोग करता है और rsyslog SIGHUP का। अनुमान लगाने के बजाय अपने सामने मौजूद daemon के लिए documentation देखें, क्योंकि गलत daemon को गलत signal भेजने से वह बंद हो सकता है।
sudo systemctl kill -s USR1 nginxयह signal उस process को भेजता है जिसे systemd unit के मुख्य process के रूप में रिकॉर्ड करता है, इसलिए यदि कोई unit daemon के शुरू होने के तरीके के लिए गलत Type= घोषित करती है, तो वह signal ऐसी process को मिल सकता है जिसने कभी डिलीट की गई फाइल को hold नहीं किया था, और जगह खाली नहीं होगी।
चौथा, unit को restart करें। sudo systemctl restart <unit> पुरानी process द्वारा रखे गए हर descriptor को बंद कर देता है, इसलिए 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/nullफाइल बनाने से पहले रिकॉर्ड किए गए मान के साथ उपयोग किए गए bytes की तुलना करें। वे फिर से मेल खाते हैं, और find अब आपके descriptor को रिपोर्ट नहीं करता है। समस्या खोजने वाले उसी command के साथ verify करना एक अच्छी आदत है।
उस मान को बदलते हुए देखना, बार-बार हाथ से df चलाने से आसान है। watch एक निश्चित अंतराल पर command को दोहराता है और output को उसी स्थान पर फिर से print करता है, इसलिए df के साथ watch df -h / यह दिखाता है कि जगह वापस आने पर used column कैसे बदलता है।
जब totals मेल खाते हैं और disk फिर भी full है
यदि df और root du -x एक-दूसरे से सहमत हैं, तो इसमें कोई deleted file शामिल नहीं है। शेष कारण प्रकृति में भिन्न हैं, और प्रत्येक की अपनी जाँच होती है।
Inodes समाप्त होना, न कि blocks समाप्त होना
एक inode किसी एक file के metadata को सुरक्षित रखता है। filesystem बनाते समय ext4 निश्चित संख्या में inodes बनाता है, इसलिए filesystem में inodes समाप्त हो सकते हैं जबकि blocks अभी भी खाली हों। ऐसी स्थिति में नई files नहीं बन पातीं, भले ही df -h में जगह दिखाई दे रही हो।
df -h /
df -i /पहली command blocks की गणना करती है और दूसरी inodes की। प्रत्येक के use column की तुलना करें। यदि block का उपयोग कम है और inode का उपयोग अपनी सीमा पर है, तो इसका अर्थ है कि बहुत सारी छोटी-छोटी files मौजूद हैं।
df एक ही invocation में -i और --output को स्वीकार नहीं करता है, इसलिए जब आप raw counts को पढ़ना चाहते हैं या किसी अन्य command को देना चाहते हैं, तो inode fields को नाम से चुनें और -i को हटा दें।
df --output=itotal,iused,iavail,ipcent /ये columns वही accounting दर्शाते हैं जिसे df -i print करता है, एक ऐसे format में जिसे आप आसानी से अलग कर सकते हैं।
bytes के बजाय entries की गणना करके files को ढूँढें।
sudo du --inodes -x -d 1 / 2>/dev/null | sort -rn | headजो directory सबसे ऊपर आए, उस पर एक स्तर नीचे जाकर वही command दोहराएँ, जब तक कि आप उस 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 करता है, इसलिए इसमें इस तरह की निश्चित सीमा नहीं होती। containers चलाने वाली machine अन्य की तुलना में इन सीमाओं तक जल्दी पहुँच जाती है, क्योंकि image layers में बहुत सारी छोटी files होती हैं। ऐसी machine पर pruning Docker's disk usage on a VPS इसका सटीक समाधान है, और यह filesystem की सामान्य सफाई की तुलना में कहीं अधिक जगह खाली करता है।
माउंट पॉइंट के नीचे छिपा हुआ स्पेस
किसी डायरेक्टरी पर कुछ भी माउंट करने से पहले उसमें फाइलें हो सकती हैं। उस डायरेक्टरी के ऊपर एक फाइलसिस्टम माउंट करें और नीचे मौजूद फाइलें वहीं बनी रहती हैं: वे अभी भी एलोकेटेड होती हैं, df द्वारा गिनी जाती हैं, और नाम से अब उन तक नहीं पहुँचा जा सकता। du उन्हें देख नहीं सकता क्योंकि माउंट उन्हें ढक लेता है।
इसे tmpfs के साथ दिखाएं, जिसके लिए किसी अतिरिक्त डिस्क की आवश्यकता नहीं होती। इस भाग के लिए ऐसी मशीन चाहिए जहाँ आपको माउंट करने की अनुमति हो, इसलिए यह 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 एक खाली डायरेक्टरी दिखाता है। कॉपी कहीं नहीं गई: यह अभी भी रूट फाइलसिस्टम पर है, और अनमाउंट करते ही वापस आ जाती है। अब एक ऐसी सर्विस की कल्पना करें जिसने किसी के द्वारा उस पर वॉल्यूम माउंट करने से पहले एक महीने तक उस पाथ पर लॉग किया हो।
चल रहे सर्वर पर वास्तविक स्थिति खोजने के लिए, रूट फाइलसिस्टम को कहीं और दूसरी बार माउंट करें। एक बाइंड माउंट एक फाइलसिस्टम को उसके अंदर माउंट किए गए फाइलसिस्टम के बिना दिखाता है।
sudo mkdir -p /mnt/rootcheck
sudo mount --bind / /mnt/rootcheck
sudo du -xhs /mnt/rootcheck/* 2>/dev/null | sort -h
sudo umount /mnt/rootcheckजो कुछ भी उस लिस्टिंग में दिखाई देता है लेकिन सामान्य पाथ के नीचे नहीं, वह एक माउंट पॉइंट के नीचे दबा हुआ है। काम पूरा होने पर बाइंड माउंट को अनमाउंट करें, अन्यथा -x के बिना बाद वाला du उन्हीं फाइलों को दो बार गिन लेगा।
root के लिए आरक्षित ब्लॉक्स
ext4 फाइल सिस्टम अपने कुछ ब्लॉक्स को root यूजर के लिए आरक्षित रखता है, ताकि डिस्क फुल होने की स्थिति में भी root लॉगिन कर सके और मशीन को रिपेयर कर सके। एक सामान्य यूजर के रूप में चलने वाली प्रक्रिया पहले इस सीमा से टकराती है, जबकि df में अभी भी थोड़ी जगह खाली दिखती है। डिफॉल्ट मान मानने के बजाय अपने फाइल सिस्टम पर सेटिंग की जाँच करें।
dev=$(df --output=source / | tail -n 1)
sudo tune2fs -l "$dev" | grep -i 'block count'यह कमांड कुल ब्लॉक काउंट और आरक्षित ब्लॉक काउंट को समान यूनिट्स में प्रिंट करता है, इसलिए उनके बीच का अनुपात सीधा होता है। df उपलब्ध कॉलम को उस स्पेस के रूप में दिखाता है जिसे एक सामान्य यूजर इस्तेमाल कर सकता है, यही कारण है कि 'used' और 'available' का योग कुल साइज से कम आता है। यह अंतर ही आरक्षित स्पेस है।
इसे sudo tune2fs -m <percent> "$dev" के साथ बदलें। यह बदलाव तुरंत लागू होता है और इसके लिए remount की आवश्यकता नहीं होती। अलग डेटा फाइल सिस्टम पर आरक्षित स्पेस को कम करना उचित है। रूट फाइल सिस्टम पर इतना स्पेस जरूर छोड़ें कि root लिख सके, क्योंकि पूरी तरह फुल हो चुके रूट फाइल सिस्टम को रिपेयर करना बहुत कठिन होता है। यही वह स्पेस है जो आपको सिस्टम से बाहर होने (locked out) से बचाता है: यदि फाइल सिस्टम में जगह न हो, तो authorized_keys में जोड़ी गई की (key) अधूरी लिखी जा सकती है या बिल्कुल नहीं लिखी जाएगी, और अगला लॉगिन Permission denied (publickey) एरर देगा, जिसका कारण की (key) से नहीं बल्कि डिस्क स्पेस से संबंधित होगा। tune2fs, ext2, ext3 और ext4 पर काम करता है। XFS में इसके समकक्ष कोई सेटिंग नहीं है।
जहाँ du आपको गलत जानकारी दे सकता है
du की चार आदतें ऐसे कुल योग दिखाती हैं जो गलत प्रतीत होते हैं।
- Hard links:
duएक inode को एक ही बार गिनता है, भले ही कई नाम उसकी ओर संकेत कर रहे हों। इसलिए, hard links से भरी हुई डायरेक्टरी का कुल आकार उसकी फाइलों के योग से कम दिखाई देता है। - Sparse files:
duकेवल उन ब्लॉक्स की रिपोर्ट करता है जो वास्तव में आवंटित (allocated) हैं, जबकिls -lफाइल के स्पष्ट (apparent) आकार को दर्शाता है। दूसरी संख्या देखने के लिए--apparent-sizeजोड़ें। - Permissions: यदि आप इसे एक सामान्य user के रूप में चलाते हैं, तो
duउन फाइलों को छोड़ देता है जिन्हें वह पढ़ नहीं सकता, जिससे रिपोर्ट कम आती है। यह जो त्रुटियाँ प्रिंट करता है, उन्हें अक्सर लोग/dev/nullपर रीडायरेक्ट कर देते हैं और पढ़ना बंद कर देते हैं। - Filesystem boundaries:
-xके बिना,du /उन सभी फाइलों को गिनता है जो/के नीचे माउंट की गई हैं। इसलिए, इसका कुल योगdf /द्वारा रिपोर्ट किए गए आंकड़ों से अधिक हो सकता है।
df की भी एक आदत है जिसे जानना उपयोगी है। यह प्रत्येक filesystem की अलग-अलग रिपोर्ट देता है, इसलिए इसे उसी सटीक पथ (path) पर चलाएं जहाँ विफल राइट ऑपरेशन हो रहा है। जैसे-जैसे kernel packages जमा होते हैं, एक अलग /boot अपने समय-सारणी के अनुसार भर जाता है, और Ubuntu पर पुराने kernels को हटाना / पर जगह खाली करने से एक अलग कार्य है।
वास्तविक incident के लिए कार्य-प्रणाली
df -h <path>औरdf -i <path>को उस filesystem पर चलाएं जहां failed write हो रही थी, न कि केवल आदतवश/पर।sudo du -xh -d 1 <mountpoint> 2>/dev/null | sort -hचलाएं, फिर सबसे बड़ी directory के भीतर जाएं।- यदि
duयह नहीं बता पा रहा है किdfके अनुसार कितनी जगह इस्तेमाल हुई है, तो/procमें उन deleted files को खोजें जो अभी भी open हैं। - यदि दोनों के आंकड़े मेल खाते हैं, तो filesystem को कहीं और bind mount करें और mount point के नीचे मौजूद files की जांच करें।
- यदि समस्या inode की सीमा तक पहुंचने की है, तो bytes के बजाय files की संख्या गिनें।
ऊपर दिए गए प्रत्येक चरण में एक command है जिसका output आप पढ़ सकते हैं। समस्या का अनुमान लगाने और उसे ठीक करने के बीच यही अंतर है।
FAQ
df डिस्क को फुल क्यों दिखाता है जबकि du बहुत कम जगह घेरता है?
इसका सामान्य कारण वह फाइल है जिसे डिलीट तो कर दिया गया है, लेकिन किसी process ने उसे अभी भी open रखा है। फाइल को हटाने से उसकी directory entry हट जाती है, इसलिए du के पास गिनने के लिए कोई नाम नहीं बचता और वह उसे छोड़ देता है। inode और उसके blocks तब तक allocated रहते हैं जब तक कि आखिरी descriptor बंद न हो जाए, और df उन्हीं allocated blocks की गणना करता है। /proc/<pid>/fd में उन symbolic links को खोजें जिनका target डिलीट हो चुका है, इससे आपको फाइल और उसे पकड़े हुए process दोनों मिल जाएंगे। तुलना पर भरोसा करने से पहले यह सुनिश्चित करें कि आपने du को root के रूप में और -x के साथ चलाया है, क्योंकि एक सामान्य user उन directories को चुपचाप छोड़ देता है जिन्हें वह पढ़ नहीं सकता।
lsof के बिना खुली हुई डिलीट फाइल को कैसे खोजें?
kernel के open descriptors के रिकॉर्ड का उपयोग करें। sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null उन सभी descriptors को लिस्ट करता है जो ऐसी फाइल की ओर इशारा कर रहे हैं जिसका कोई नाम नहीं है, और process ID उस path के अंदर होती है जिसे यह प्रिंट करता है। उन descriptor paths में से किसी एक पर sudo stat -Lc %s चलाने से उसका size पता चल जाता है, जिससे आप उन्हें sort करके महत्वपूर्ण फाइल चुन सकते हैं। इसके लिए किसी package की आवश्यकता नहीं होती, जो तब उपयोगी है जब खाली जगह न होने के कारण नया package install करना विफल हो सकता है।
क्या मैं process को kill किए बिना जगह खाली कर सकता हूँ?
कभी-कभी। sudo truncate -s 0 /proc/<pid>/fd/<n> descriptor के माध्यम से उसी inode तक पहुँचता है और process के चलते रहने के दौरान ही उसके blocks को release कर देता है। यह तब सबसे अच्छा काम करता है जब process ने फाइल को append mode में खोला हो, क्योंकि उसका write हमेशा अंत में होता है। यदि ऐसा नहीं है, तो write offset वहीं रहता है जहाँ वह था और अगला write फाइल को शुरुआत में एक hole के साथ फिर से बना देता है, जिससे रिपोर्ट किया गया size वापस बढ़ जाता है जबकि hole के नीचे के blocks खाली रहते हैं। unit को restart करना, या उसके documentation में बताए गए signal के साथ उसे logs फिर से खोलने का निर्देश देना ही वह समाधान है जिससे कोई sparse file पीछे नहीं बचती।
df खाली जगह दिखाता है लेकिन write विफल हो जाता है। और क्या कारण हो सकता है?
उसी path पर df -i के साथ inodes की जाँच करें, क्योंकि खाली blocks होने के बावजूद यदि inodes खाली नहीं हैं, तो नई फाइलें नहीं बनेंगी। जाँचें कि क्या write एक non-root user द्वारा ext4 filesystem पर किया जा रहा है जहाँ केवल reserved blocks बचे हैं, जिसे device पर sudo tune2fs -l चलाने से देखा जा सकता है। यह भी सुनिश्चित करें कि आप उसी filesystem को पढ़ रहे हैं जिसे write target कर रहा है, क्योंकि एक अलग /boot या /var, / से स्वतंत्र रूप से भरता है।
du का कुल योग df से अधिक क्यों आता है?
-x के बिना du आपके द्वारा दिए गए path के अंतर्गत mount किए गए हर filesystem में चला जाता है, इसलिए यह कई filesystems को जोड़ देता है जबकि df केवल एक का विवरण देता है। Bind mounts इसे और खराब कर देते हैं, क्योंकि एक ही फाइल हर उस path पर गिनी जाती है जहाँ वह दिखाई देती है। du को एक ही filesystem पर सीमित रखने के लिए -x जोड़ें, और df को वही path दें, ताकि दोनों commands एक ही चीज़ का विवरण दें।