df ফুল দেখাচ্ছে কিন্তু du দেখাচ্ছে না কেন?
আপনার VPS ডিস্কে জায়গা খালি নেই কিন্তু ফাইল খুঁজে পাচ্ছেন না? lsof কমান্ড ব্যবহার করে ডিলিট করা ফাইলটি খুঁজে বের করুন যা প্রসেস ধরে রেখেছে এবং রিবুট ছাড়াই ডিস্কের জায়গা খালি করুন।
কেন df পূর্ণ দেখায় এবং du ভিন্ন তথ্য দেয়
df ডিস্ক পূর্ণ বলে রিপোর্ট করে, কিন্তু du সেই জায়গা খুঁজে পায় না কারণ কোনো একটি প্রসেস এমন একটি ফাইল ধরে রেখেছে যা ইতিমধ্যে ডিলিট করা হয়েছে। কোনো ফাইল ডিলিট করলে ডিরেক্টরি থেকে শুধু তার নাম মুছে যায়। ডেটা ব্লকগুলো তখনই মুক্ত হয় যখন সেই inode-এর দিকে নির্দেশ করা সর্বশেষ open file descriptor বন্ধ করা হয়। du শুধু ফাইলের নামগুলো গণনা করে, তাই এটি সেই ফাইলটিকে হিসেবে ধরে না। df ফাইলসিস্টেমকে জিজ্ঞাসা করে কতগুলো ব্লক বরাদ্দ করা আছে, তাই এটি সেই ফাইলটিকেও গণনা করে যার এখন আর কোনো নাম নেই।
এই নির্দেশিকাটি একটি সাধারণ Ubuntu VPS-এ আগে থেকেই ইনস্টল করা টুল ব্যবহার করে এই পরিস্থিতি তৈরি করে, /proc-এর মাধ্যমে ফাইলটি ধরে রাখা প্রসেসটিকে খুঁজে বের করে এবং রিবুট ছাড়াই জায়গা খালি করে। একই লক্ষণের অন্যান্য কারণগুলো হলো: কোনো খালি এন্ট্রি ছাড়া 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.
ইচ্ছাকৃতভাবে অমিল তৈরি করা
এটি একটি টেস্ট VPS-এ করুন। নিচে সবকিছু bash এবং coreutils ব্যবহার করা হয়েছে, তাই নতুন কিছু ইনস্টল করার প্রয়োজন নেই।
যে ফাইলসিস্টেমে /var/tmp আছে তার শুরুর অবস্থা রেকর্ড করুন।
cd /var/tmp
df -h .
df --output=used -B1 .দ্বিতীয় কমান্ডটি কোনো রাউন্ডিং ছাড়াই ব্যবহৃত বাইট সংখ্যা দেখায়, যা শেষের চেকিংটিকে নিখুঁত করে।
এখন একটি ফাইল তৈরি করুন। এর আকার মেশিনটি যে পরিমাণ খালি জায়গা রিপোর্ট করছে তার ওপর ভিত্তি করে নির্ধারণ করা হয়েছে, ফলে আপনার ডিস্কের আকার যাই হোক না কেন এই ডেমোনস্ট্রেশনটি কাজ করবে।
free=$(df --output=avail -B1 . | tail -n 1)
fallocate -l $((free / 10)) ghost.bin
ls -l ghost.bin
df -h .$(...) হলো command substitution: শেল এর ভেতরের কমান্ডটি চালায় এবং আউটপুটটি free-এর মান হিসেবে সেট করে। যদি এই সিনট্যাক্স আপনার কাছে নতুন মনে হয়, তবে bash-এ command substitution বিষয়টি বিস্তারিত দেখুন। fallocate কোনো ডেটা না লিখেই প্রকৃত ব্লকগুলো রিজার্ভ করে, তাই এটি তাৎক্ষণিকভাবে শেষ হয়। যে ফাইলসিস্টেম এটি সমর্থন করে না সেখানে কমান্ডটি ব্যর্থ হবে, সেক্ষেত্রে head -c $((free / 10)) /dev/zero > ghost.bin একই কাজ করবে তবে বাইটগুলো লিখে।
এই df -h .-এর সাথে আপনার রেকর্ড করা মানটি তুলনা করুন। ব্যবহৃত (used) কলামটি বেড়েছে এবং খালি (available) কলামটি কমেছে।
এখন অন্য একটি প্রসেস থেকে ফাইলটি ওপেন রাখুন, তারপর এটি ডিলিট করুন।
sleep infinity < ghost.bin &
holder=$!
rm ghost.bin
ls -l ghost.bin
df -h .
sudo du -xhs . 2>/dev/nullরিডাইরেকশনটিই এখানে মূল কৌশল। sleep infinity < ghost.bin & একটি ব্যাকগ্রাউন্ড প্রসেস শুরু করে যার স্ট্যান্ডার্ড ইনপুট হলো ওই ফাইলটি, তাই শেল ফাইলটি ওপেন করে এবং এর ডেসক্রিপটর sleep-এর কাছে হস্তান্তর করে, যা এটিকে ওপেন রাখে। $! ওই ব্যাকগ্রাউন্ড জবের প্রসেস আইডি ধরে রাখে। এরপর rm ফাইলটির নাম মুছে ফেলে কিন্তু ডেসক্রিপটরটি ওপেন থাকে।
আউটপুটটি পড়ুন। ls ফাইলটি খুঁজে পাবে না, কারণ নামটির অস্তিত্ব নেই। du প্রায় আগের অবস্থানে ফিরে এসেছে, কারণ এটি ফাইলের নাম ধরে হিসাব করে। df পরিবর্তিত হয়নি, কারণ ব্লকগুলো এখনও বরাদ্দ করা আছে। ফাইলসিস্টেম এবং ডিরেক্টরি ট্রি এখন আর একমত নয়, এবং তাদের মধ্যকার এই পার্থক্যটিই হলো সেই ফাইলটি যা আপনি এইমাত্র ডিলিট করেছেন।
ডিলিট করা ফাইলটি যে প্রসেস ধরে রেখেছে তা খুঁজে বের করা
প্রতিটি ওপেন ফাইল ডেসক্রিপ্টর /proc/<pid>/fd/-এর অধীনে একটি সিম্বলিক লিঙ্ক হিসেবে থাকে যা মূল ফাইলটিকে নির্দেশ করে। যখন ফাইলটি আনলিঙ্ক করা হয়, কার্নেল সেই লিঙ্কের লক্ষ্যবস্তুকে ডিলিট করা হিসেবে চিহ্নিত করে। তাই ফাইলটি কোন প্রসেস ধরে রেখেছে তা বের করার অর্থ হলো এমন একটি লিঙ্ক খুঁজে বের করা যার লক্ষ্যবস্তুতে এই মার্কারটি আছে।
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/nulllsof +L1
-lname সিম্বলিক লিঙ্কের নামের পরিবর্তে তার লক্ষ্যবস্তুর সাথে মিল খোঁজে, %p ডেসক্রিপ্টরের পাথ প্রিন্ট করে এবং %l সেটি কী নির্দেশ করছে তা দেখায়। প্রিন্ট করা পাথের দ্বিতীয় উপাদানটিই হলো প্রসেস আইডি। এটি 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 | headlsof +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"ps -p PID -o comm,etime
stat /proc/PID/fd/N
ps প্রোগ্রামটির নাম বলে এবং এটি কতক্ষণ ধরে চলছে তা দেখায়। stat -L ডিলিট করা ইনোডের সাইজ এবং বরাদ্দকৃত ব্লকের সংখ্যা প্রিন্ট করে। এগুলো একত্রে সেই প্রশ্নের উত্তর দেয় যা সবচেয়ে গুরুত্বপূর্ণ: কোন সার্ভিসটি এই ফাইলটিকে জীবিত রেখেছে।
যদি মেশিনে আগে থেকেই lsof থাকে, তবে sudo lsof +L1 সেই ওপেন ফাইলগুলোর তালিকা দেখায় যাদের লিঙ্ক কাউন্ট শূন্য হয়ে গেছে এবং একটি টেবিলে সেগুলোর সাইজ প্রদর্শন করে। এটি একটি মিনিমাল Ubuntu ইমেজে থাকে না এবং ডিস্কে জায়গা না থাকলে নতুন প্যাকেজ ইনস্টল করা ব্যর্থ হতে পারে, তাই /proc পদ্ধতিটিই সব সময় কার্যকর।
Free the space without a reboot
A reboot does fix it, and it is the wrong first move: it takes the service down and it destroys the evidence. Four gentler options exist, in the order to try them.
First, copy the data out if you still want it. Reading the descriptor path reads the live inode.
sudo cp /proc/<pid>/fd/<n> /root/recovered.logThis is the one case where a deleted file is easy to get back, which is why recovering files deleted with rm -rf starts by asking whether a process still holds the file open. Once the last descriptor closes, that route is gone.
Second, empty the file through the descriptor. The /proc path leads to the same inode, so truncating it releases the blocks while the process keeps running.
sudo truncate -s 0 "/proc/$pid/fd/$n"
df -h /This works cleanly when the writer opened the file in append mode, because every write then goes to the current end of the file. When it did not, the process keeps its old write offset, so its next write lands far into the file and recreates it with a hole at the front. A hole is not allocated, so the blocks stay free and df keeps the space it just returned. What springs back is the size alone: run sudo stat -L "/proc/$pid/fd/$n" again after the process writes, and it reports the old size next to a block count that no longer matches it. Restart the process when you want the size to start from zero as well.
Third, ask the service to reopen its logs. A daemon whose log file was deleted underneath it is the common real version of this problem. Many daemons reopen their log files on a signal: nginx uses SIGUSR1 and rsyslog uses SIGHUP. Check the documentation for the daemon in front of you instead of guessing, because the wrong signal sent to the wrong daemon stops it.
sudo systemctl kill -s USR1 nginxThat sends the signal to whichever process systemd records as the unit's main one, so a unit that declares the wrong Type= for how its daemon actually starts can deliver your signal to a process that never held the deleted file, and the space stays where it was.
Fourth, restart the unit. sudo systemctl restart <unit> closes every descriptor the old process held, so the blocks come back with certainty. For the demonstration above the holder is a sleep you started yourself, so ending it is enough.
kill $holder
df -h .
df --output=used -B1 .
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/nullCompare the used bytes against the value you recorded before you created the file. They agree again, and the find no longer reports your descriptor. Verifying with the same command that found the problem is the habit worth keeping.
Watching that value move is easier than running df by hand over and over. watch repeats a command on a fixed interval and reprints the output in place, so watch df -h / shows the used column change as the space comes back.
যখন মোট পরিমাণ মিলে যায় কিন্তু ডিস্ক এখনো পূর্ণ থাকে
যদি df এবং রুট du -x একে অপরের সাথে মিলে যায়, তবে কোনো ডিলিট করা ফাইল এর কারণ নয়। অবশিষ্ট কারণগুলো ভিন্ন প্রকৃতির এবং প্রতিটির জন্য আলাদা যাচাইকরণ পদ্ধতি রয়েছে।
ব্লক নয়, ইনোড (inode) শেষ হয়ে যাওয়া
একটি ইনোড একটি ফাইলের মেটাডেটা ধারণ করে। ফাইলসিস্টেম তৈরির সময় ext4 নির্দিষ্ট সংখ্যক ইনোড তৈরি করে, তাই ফাইলসিস্টেমে খালি ব্লক থাকা সত্ত্বেও ইনোড শেষ হয়ে যেতে পারে। এমন অবস্থায় df -h কমান্ডে জায়গা দেখালেও নতুন ফাইল তৈরি করা সম্ভব হয় না।
df -h /
df -i /প্রথম কমান্ডটি ব্লক গণনা করে এবং দ্বিতীয়টি ইনোড গণনা করে। প্রতিটি কমান্ডের use কলামটি তুলনা করুন। ব্লকের ব্যবহার কম কিন্তু ইনোড ব্যবহার সর্বোচ্চ পর্যায়ে থাকলে বুঝতে হবে যে খুব ছোট ছোট অনেকগুলো ফাইল তৈরি হওয়ার কারণে এই সমস্যা হচ্ছে।
df একই ইনভোকেশনে -i এবং --output গ্রহণ করে না। তাই যখন আপনি raw count পড়তে চান বা অন্য কোনো কমান্ডে পাঠাতে চান, তখন ইনোড ফিল্ডগুলো নাম ধরে নির্বাচন করুন এবং -i বাদ দিন।
df --output=itotal,iused,iavail,ipcent /এই কলামগুলো df -i-এর প্রিন্ট করা একই হিসাব বহন করে, যা আপনি সহজেই আলাদা করতে পারবেন।
বাইট গণনা না করে এন্ট্রি গণনা করে ফাইলগুলো খুঁজে বের করুন।
sudo du --inodes -x -d 1 / 2>/dev/null | sort -rn | headযে ডিরেক্টরিটিতে সবচেয়ে বেশি ফাইল পাওয়া গেছে, সেটির ভেতরে গিয়ে একই কমান্ড পুনরায় চালান। এভাবে ততক্ষণ পর্যন্ত করুন যতক্ষণ না আপনি সেই ট্রি-টি খুঁজে পান যা ফাইলগুলো তৈরি করছে। যদি আপনার du-এ --inodes সাপোর্ট না থাকে, তবে sudo find /var -xdev -type f | wc -l ব্যবহার করে ধীরগতিতে সাবট্রি গণনা করা সম্ভব।
এর সমাধান হলো ফাইলগুলো মুছে ফেলা বা সরিয়ে নেওয়া। বিদ্যমান ext4 ফাইলসিস্টেমে ইনোড বাড়ানো যায় না, কারণ এর সংখ্যা mkfs-এর সময় নির্দিষ্ট করে দেওয়া হয়। তাই ইনোড বাড়াতে হলে ফাইলসিস্টেম নতুন করে তৈরি করে ব্যাকআপ থেকে ডেটা রিস্টোর করতে হবে। XFS প্রয়োজনে ইনোড বরাদ্দ করে, তাই এতে নির্দিষ্ট কোনো সীমা থাকে না। কন্টেইনার ব্যবহার করা মেশিনে খুব দ্রুত এই সীমা পূর্ণ হয়ে যায়, কারণ ইমেজ লেয়ারে অনেক ছোট ছোট ফাইল থাকে। সেই মেশিনের ক্ষেত্রে VPS-এ Docker-এর ডিস্ক ব্যবহার কমানো হলো নির্দিষ্ট সমাধান, যা সাধারণ ফাইলসিস্টেম ক্লিনআপের চেয়ে অনেক বেশি জায়গা খালি করে।
মাউন্ট পয়েন্টের নিচে লুকিয়ে থাকা জায়গা
কোনো ডিরেক্টরিতে কিছু মাউন্ট করার আগেও সেখানে ফাইল থাকতে পারে। সেই ডিরেক্টরির ওপর একটি ফাইলসিস্টেম মাউন্ট করলে নিচের ফাইলগুলো ঠিক আগের জায়গাতেই থেকে যায়: সেগুলো তখনও বরাদ্দ থাকে, 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 একটি খালি ডিরেক্টরি দেখাচ্ছে। কপিটি কোথাও যায়নি: এটি এখনও রুট ফাইলসিস্টেমে আছে এবং আনমাউন্ট করার সাথে সাথেই তা আবার ফিরে আসবে। এখন এমন একটি সার্ভিসের কথা চিন্তা করুন যা কোনো ভলিউম মাউন্ট করার আগে এক মাস ধরে সেই পাথে লগ ফাইল লিখেছে।
চলমান সার্ভারে আসল ফাইলগুলো খুঁজে পেতে, রুট ফাইলসিস্টেমটিকে অন্য কোথাও দ্বিতীয়বার মাউন্ট করুন। একটি বাইন্ড মাউন্ট (bind mount) এমন একটি ফাইলসিস্টেম দেখায় যার ভেতরে অন্য কোনো ফাইলসিস্টেম মাউন্ট করা নেই।
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 কমান্ডটি available কলামে সেই জায়গাটি দেখায় যা একজন সাধারণ ব্যবহারকারী ব্যবহার করতে পারেন, আর এ কারণেই used এবং available যোগ করলে তা মোট সাইজের চেয়ে কম হয়। এই পার্থক্যটুকুই হলো সংরক্ষিত অংশ।
sudo tune2fs -m <percent> "$dev" ব্যবহার করে এটি পরিবর্তন করুন। এই পরিবর্তন তাৎক্ষণিকভাবে কার্যকর হয় এবং ফাইলসিস্টেম remount করার প্রয়োজন পড়ে না। আলাদা কোনো ডেটা ফাইলসিস্টেমের ক্ষেত্রে সংরক্ষিত ব্লকের পরিমাণ কমিয়ে রাখা যুক্তিসঙ্গত। তবে root ফাইলসিস্টেমের ক্ষেত্রে পর্যাপ্ত জায়গা খালি রাখুন যাতে root প্রয়োজনে লিখতে পারে, কারণ সম্পূর্ণ পূর্ণ হয়ে যাওয়া root ফাইলসিস্টেম মেরামত করা অনেক বেশি কঠিন। এটি আপনাকে সিস্টেম থেকে বিচ্ছিন্ন হওয়া থেকেও রক্ষা করে: যদি ফাইলসিস্টেমে কোনো জায়গা খালি না থাকে, তবে authorized_keys ফাইলে নতুন কোনো key যুক্ত করা সম্ভব হয় না বা ফাইলটি অসম্পূর্ণ থেকে যায়। এর ফলে পরবর্তী লগইনের সময় Permission denied (publickey) ত্রুটি দেখা দেয়, যার সাথে মূল key-এর কোনো সম্পর্ক থাকে না। tune2fs কমান্ডটি ext2, ext3 এবং ext4-এ কাজ করে। XFS-এ এর সমতুল্য কোনো সেটিং নেই।
Where du misleads you on its own
Four habits of du produce totals that look wrong.
- Hard links:
ducounts an inode once even when several names point at it, so a tree full of hard links reports less than the sum of its files. - Sparse files:
dureports the blocks actually allocated, whilels -lreports the apparent size. Add--apparent-sizeto see the other number. - Permissions: run as an ordinary user,
duskips what it cannot read and under-reports. The errors it prints are the ones people redirect to/dev/nulland stop reading. - Filesystem boundaries: without
-x,du /counts every filesystem mounted below/, so its total can exceed whatdf /reports.
df has one habit worth knowing as well. It reports each filesystem separately, so run it against the exact path the failing write targets. A separate /boot fills on its own schedule as kernel packages accumulate, and removing old kernels on Ubuntu is a different job from clearing space on /.
একটি বাস্তব ঘটনার জন্য কার্যকর কর্মপদ্ধতি
- ব্যর্থ রাইট অপারেশন যে ফাইলসিস্টেমকে লক্ষ্য করে করা হয়েছিল, সেটিতে
df -h <path>এবংdf -i <path>চালান; অভ্যাসবশত সরাসরি/-এ চালাবেন না। sudo du -xh -d 1 <mountpoint> 2>/dev/null | sort -hচালান, এরপর সবচেয়ে বড় ডিরেক্টরিটির ভেতরে প্রবেশ করুন।- যদি
dfযে পরিমাণ জায়গা ব্যবহারের রিপোর্ট দিচ্ছে,duতা মেলাতে না পারে, তবে/proc-এ এমন ডিলিট করা ফাইল খুঁজুন যা এখনও ওপেন অবস্থায় আছে। - যদি উভয়ই একই তথ্য দেয়, তবে ফাইলসিস্টেমটিকে অন্য কোথাও bind mount করুন এবং মাউন্ট পয়েন্টের নিচে কোনো ফাইল জমে আছে কি না তা পরীক্ষা করুন।
- যদি inode ব্যবহারের হার সীমার মধ্যে থাকে, তবে বাইটের পরিবর্তে ফাইলের সংখ্যা গণনা করুন।
এখানে প্রতিটি ধাপেই একটি কমান্ড রয়েছে যার আউটপুট আপনি পড়তে পারবেন। সমস্যাটি অনুমান করে সমাধান করা এবং নিশ্চিতভাবে সমাধান করার মধ্যে পার্থক্য এখানেই।
FAQ
কেন df ডিস্ক পূর্ণ দেখায় যখন du অনেক কম জায়গা ব্যবহার হতে দেখে?
সাধারণ কারণ হলো এমন একটি ফাইল যা মুছে ফেলা হয়েছে কিন্তু কোনো প্রসেস এখনো সেটি ওপেন করে রেখেছে। ফাইলটি মুছে ফেললে এর ডিরেক্টরি এন্ট্রি চলে যায়, তাই du সেটির কোনো নাম খুঁজে পায় না এবং গণনা করা বন্ধ করে দেয়। ফাইলটির inode এবং এর ব্লকগুলো বরাদ্দকৃতই থাকে যতক্ষণ না শেষ ডেসক্রিপটরটি বন্ধ হয়, আর df বরাদ্দকৃত ব্লকগুলোই গণনা করে। /proc/<pid>/fd-এ এমন সব symbolic link খুঁজুন যার টার্গেট মুছে ফেলা হয়েছে বলে চিহ্নিত, এতে আপনি ফাইলটি এবং সেটি ধরে রাখা প্রসেস উভয়ই খুঁজে পাবেন। এই তুলনার ওপর আস্থা রাখার আগে নিশ্চিত করুন যে আপনি du কমান্ডটি root হিসেবে এবং -x ফ্ল্যাগসহ চালিয়েছেন, কারণ সাধারণ ব্যবহারকারী হিসেবে চালালে যেসব ডিরেক্টরি পড়া সম্ভব নয় সেগুলো নীরবে বাদ পড়ে যায়।
lsof ছাড়া মুছে ফেলা কিন্তু ওপেন থাকা ফাইল কীভাবে খুঁজে পাব?
কার্নেলের নিজস্ব ওপেন ডেসক্রিপটর রেকর্ড ব্যবহার করুন। sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null এমন প্রতিটি ডেসক্রিপটর তালিকাভুক্ত করে যা কোনো নামহীন ফাইলের দিকে নির্দেশ করছে, এবং এর প্রিন্ট করা পাথের ভেতরেই প্রসেস আইডি (PID) থাকে। সেই ডেসক্রিপটর পাথগুলোর একটিতে sudo stat -Lc %s চালালে এর আকার জানা যায়, ফলে আপনি সেগুলোকে সাজিয়ে গুরুত্বপূর্ণ ফাইলটি বেছে নিতে পারেন। এর জন্য কোনো প্যাকেজ ইনস্টল করার প্রয়োজন নেই, যা গুরুত্বপূর্ণ কারণ ডিস্কে খালি জায়গা না থাকলে নতুন প্যাকেজ ইনস্টল করা ব্যর্থ হতে পারে।
প্রসেস বন্ধ না করেই কি জায়গা খালি করা সম্ভব?
কখনও কখনও সম্ভব। sudo truncate -s 0 /proc/<pid>/fd/<n> ডেসক্রিপটরের মাধ্যমে একই inode-এ পৌঁছে এর ব্লকগুলো মুক্ত করে দেয় যখন প্রসেসটি চলমান থাকে। এটি সবচেয়ে কার্যকর হয় যখন প্রসেসটি ফাইলটিকে append মোডে ওপেন করে, কারণ এর রাইট অপারেশন সবসময় ফাইলের শেষে হয়। যদি তা না হয়, তবে রাইট অফসেট আগের জায়গাতেই থেকে যায় এবং পরবর্তী রাইট অপারেশনে ফাইলের শুরুতে একটি গর্ত (hole) তৈরি হয়; ফলে রিপোর্ট করা আকার আবার বেড়ে যায় কিন্তু গর্তের নিচের ব্লকগুলো খালিই থাকে। ইউনিটটি রিস্টার্ট করা অথবা এর ডকুমেন্টেশনে উল্লেখিত সিগন্যাল পাঠিয়ে লগ ফাইল পুনরায় ওপেন করতে বলা হলো সঠিক সমাধান, যা কোনো sparse file অবশিষ্ট রাখে না।
df খালি জায়গা দেখাচ্ছে কিন্তু রাইট অপারেশন ব্যর্থ হচ্ছে। আর কী কারণ হতে পারে?
একই পাথে df -i চালিয়ে inode পরীক্ষা করুন, কারণ খালি ব্লক থাকলেও পর্যাপ্ত free inode না থাকলে নতুন ফাইল তৈরি করা যায় না। পরীক্ষা করুন রাইট অপারেশনটি কোনো non-root ব্যবহারকারী চালাচ্ছেন কি না এমন একটি ext4 ফাইলসিস্টেমে যেখানে শুধুমাত্র সংরক্ষিত (reserved) ব্লকগুলো অবশিষ্ট আছে, যা ডিভাইসের ওপর sudo tune2fs -l চালালে দেখা যাবে। নিশ্চিত করুন যে আপনি সেই ফাইলসিস্টেমটিই দেখছেন যেখানে রাইট অপারেশনটি হচ্ছে, কারণ আলাদা /boot বা /var ফাইলসিস্টেমগুলো / থেকে স্বাধীনভাবে পূর্ণ হয়।
কেন du, df-এর চেয়ে বেশি মোট জায়গা রিপোর্ট করে?
-x ছাড়া du কমান্ডটি আপনার দেওয়া পাথের অধীনে মাউন্ট করা প্রতিটি ফাইলসিস্টেমে প্রবেশ করে, ফলে এটি একাধিক ফাইলসিস্টেমের যোগফল দেখায় যেখানে df শুধুমাত্র একটির বর্ণনা দেয়। Bind mount-এর কারণে এটি আরও জটিল হয়, কারণ একই ফাইল প্রতিটি পাথে একবার করে গণনা করা হয়। du-কে একটি নির্দিষ্ট ফাইলসিস্টেমে সীমাবদ্ধ রাখতে -x যোগ করুন এবং df-কে একই পাথ দিন, যাতে উভয় কমান্ড একই বিষয়ের বর্ণনা দেয়।