df full காட்டும் ஆனால் du காட்டவில்லை: தீர்வு என்ன?
VPS வட்டு நிரம்பியிருந்தும் கோப்புகளைக் கண்டறிய முடியவில்லையா? நீக்கப்பட்ட கோப்புகளைத் திறந்து வைத்திருக்கும் process-ஐ lsof மூலம் கண்டறிந்து, வட்டு இடத்தை மீட்பது எப்படி?
df ஏன் வட்டு நிரம்பியுள்ளதாகக் காட்டுகிறது, ஆனால் du அவ்வாறு காட்டவில்லை
df வட்டு நிரம்பியுள்ளதாக அறிக்கை செய்கிறது, ஆனால் du அந்த இடத்தைக் கண்டறிய முடியவில்லை. இதற்குக் காரணம், நீக்கப்பட்ட ஒரு கோப்பை ஒரு process இன்னும் தன் வசம் வைத்திருப்பதுதான். ஒரு கோப்பை நீக்கும்போது, அதன் பெயர் மட்டுமே கோப்பகத்திலிருந்து (directory) நீக்கப்படும். அந்த inode-ஐச் சுட்டிக்காட்டும் கடைசி open file descriptor மூடப்படும்போது மட்டுமே, அந்தத் தரவுத் தொகுதிகள் (data blocks) விடுவிக்கப்படும். du கோப்புப் பெயர்களை மட்டுமே கணக்கிடுவதால், அது எதையும் கண்டறியாது. df கோப்பு முறைமையிடம் (filesystem) எத்தனை தொகுதிகள் ஒதுக்கப்பட்டுள்ளன என்று கேட்பதால், பெயர் இல்லாத அந்தத் தரவையும் அது கணக்கில் கொள்கிறது.
இந்த வழிகாட்டி, ஏற்கனவே நிறுவப்பட்ட கருவிகளைக் கொண்டு ஒரு சாதாரண Ubuntu VPS-ல் இதைச் செய்து காட்டுகிறது. /proc மூலம் அந்தத் தரவை வைத்திருக்கும் process-ஐக் கண்டறிந்து, கணினியை reboot செய்யாமலேயே இடத்தை விடுவிப்பது எப்படி என்பதை விளக்குகிறது. இதே அறிகுறிக்குக் காரணமான பிற விஷயங்கள்: காலியான இடமில்லாத inode table, mount point-க்கு அடியில் மறைந்துள்ள கோப்புகள், மற்றும் root பயனருக்காக ஒதுக்கப்பட்ட தொகுதிகள்.
ஒவ்வொரு கட்டளையையும் இயக்கி, உங்கள் வெளியீட்டை நீங்களே கவனியுங்கள். மதிப்புகள் உங்கள் வட்டைப் பொறுத்து மாறுபடும். எனவே, வழிகாட்டியில் உள்ள எண்களுடன் ஒப்பிடாமல், உங்கள் கணினியில் கட்டளையை இயக்குவதற்கு முன்பும் பின்பும் உள்ள மதிப்புகளை ஒப்பிட்டுப் பாருங்கள்.
df மற்றும் du எவற்றைக் கணக்கிடுகின்றன
df (disk free) ஒவ்வொரு mounted filesystem-இடமும் அதன் கணக்கீட்டைக் கேட்கிறது: எத்தனை blocks உள்ளன, எத்தனை ஒதுக்கப்பட்டுள்ளன, எத்தனை காலியாக உள்ளன என்பதுதான் அது. இது எந்தவொரு directory-யையும் திறப்பதில்லை. எந்தவொரு directory entry-யும் சுட்டிக்காட்டாத கோப்புக்குச் சொந்தமான blocks உட்பட, ஒதுக்கப்பட்ட அனைத்து blocks-களையும் இந்த விடை உள்ளடக்கும்.
du (disk usage) இதற்கு நேர்மாறாகச் செயல்படுகிறது. நீங்கள் கொடுக்கும் பாதையில் தொடங்கி, directory-களை வாசித்து, அதில் உள்ள ஒவ்வொரு entry-யையும் stat செய்து, blocks-களைக் கூட்டுகிறது. பெயரில்லாத ஒரு கோப்பு இதற்குத் தெரிவதில்லை. அதேபோல், வாசிக்க அனுமதி இல்லாத எந்தவொரு directory-யும் இதற்குத் தெரிவதில்லை; இதனால்தான் ஒரு சாதாரண user-க்கு root-ஐ விடக் குறைவான மொத்த அளவு கிடைக்கிறது. ஒப்பீடு செய்து முடிவெடுக்கும் முன் sudo-ன் கீழ் du-ஐ இயக்கவும்.
இவ்விரண்டையும் ஒப்பிடும்போது ஒவ்வொரு முறையும் இரண்டு options முக்கியத்துவம் பெறுகின்றன.
-xஎன்பதுdu-ஐ ஒரே filesystem-க்குள் வைத்திருக்கும். இது இல்லையென்றால்,du /என்பது/-க்குக் கீழே mounted செய்யப்பட்ட அனைத்து filesystem-களுக்குள்ளும் சென்று,df /அளவிடாத ஒரு மொத்த மதிப்பைக் கொடுக்கும்.-sஎன்பது ஒவ்வொரு directory-க்கும் ஒரு வரியைக் கொடுப்பதற்குப் பதிலாக, ஒவ்வொரு argument-க்கும் ஒரு சுருக்க வரியை மட்டும் அச்சிடும்.
நீங்கள் கவனிக்க வேண்டிய filesystem-ல் இவ்விரண்டையும் அருகருகே இயக்க இது உதவும்.
df -h /
sudo du -xhs / 2>/dev/nulldf உடனடியாகப் பதிலளிக்கும். du பெரிய filesystem-களில் பல நிமிடங்கள் எடுத்துக்கொள்ளும், ஏனெனில் அது வழியில் உள்ள ஒவ்வொரு கோப்பையும் stat செய்கிறது. இவ்விரண்டு மொத்த மதிப்புகளும் வெகுவாக வேறுபடும்போது, மற்றும் -x உடன் root-ஆக du இயக்கப்பட்டிருந்தால், விடுபட்ட இடம் பெயரில்லாத ஏதோ ஒன்றுக்கு ஒதுக்கப்பட்டுள்ளது என்று அர்த்தம்.
முரண்பாட்டை வேண்டுமென்றே உருவாக்குதல்
இதை ஒரு test VPS-ல் செய்யவும். கீழே உள்ளவை அனைத்தும் bash மற்றும் coreutils என்பதால், எதையும் புதிதாக நிறுவ வேண்டியதில்லை.
/var/tmp-ஐக் கொண்டுள்ள filesystem-ன் தொடக்க நிலையைப் பதிவு செய்யவும்.
cd /var/tmp
df -h .
df --output=used -B1 .இரண்டாவது கட்டளை பயன்படுத்தப்பட்ட bytes-ஐ எந்தவிதமான rounding-ம் இன்றி அச்சிடுகிறது, இது இறுதியில் செய்யப்படும் சரிபார்ப்பை துல்லியமாக்குகிறது.
இப்போது ஒரு கோப்பை உருவாக்கவும். அதன் அளவு அந்த machine-ஆகவே தெரிவிக்கும் free space-லிருந்து எடுக்கப்படுகிறது, எனவே இந்த செயல்முறை உங்கள் வட்டில் உள்ள இடத்திற்கு ஏற்ப அமையும்.
free=$(df --output=avail -B1 . | tail -n 1)
fallocate -l $((free / 10)) ghost.bin
ls -l ghost.bin
df -h .$(...) என்பது command substitution ஆகும்: shell அதற்குள் உள்ள கட்டளையை இயக்கும், அதன் வெளியீடு free-ன் மதிப்பாக மாறும். இந்த syntax உங்களுக்குப் புதியது என்றால், bash-ல் command substitution இதைப் பற்றி விரிவாக விளக்குகிறது. fallocate தரவுகளை எழுதாமலேயே உண்மையான blocks-ஐ ஒதுக்குகிறது, அதனால்தான் அது உடனடியாக முடிவடைகிறது. இதை ஆதரிக்காத filesystem-ல் இந்த கட்டளை தோல்வியடையும், அப்போது head -c $((free / 10)) /dev/zero > ghost.bin அந்த bytes-ஐ எழுதி அதே வேலையைச் செய்யும்.
இந்த df -h .-ஐ நீங்கள் பதிவு செய்ததோடு ஒப்பிட்டுப் பார்க்கவும். பயன்படுத்தப்பட்ட (used) நெடுவரிசை அதிகரித்திருக்கும் மற்றும் கிடைக்கக்கூடிய (available) நெடுவரிசை குறைந்திருக்கும்.
இப்போது மற்றொரு process மூலம் அந்த கோப்பைத் திறந்து வைத்துவிட்டு, பின் அதை நீக்கவும்.
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 அந்த கோப்பாகும். எனவே shell அந்த கோப்பைத் திறந்து, அதன் descriptor-ஐ sleep-க்கு வழங்குகிறது, அது அதைத் திறந்து வைத்திருக்கும். $! அந்த background job-ன் process ID-ஐ வைத்திருக்கும். rm அந்த descriptor திறந்திருக்கும்போதே கோப்பின் பெயரை நீக்குகிறது.
வெளியீட்டைப் படிக்கவும். ls-ஆல் கோப்பைக் கண்டுபிடிக்க முடியாது, ஏனெனில் அதன் பெயர் நீக்கப்பட்டுவிட்டது. du அது தொடங்கிய இடத்திற்கு அருகில் வந்துவிட்டது, ஏனெனில் அது பெயர்களை அடிப்படையாகக் கொண்டு கணக்கிடுகிறது. df மாறவில்லை, ஏனெனில் blocks இன்னும் ஒதுக்கீடு செய்யப்பட்டே உள்ளன. இப்போது filesystem-க்கும் directory tree-க்கும் இடையே முரண்பாடு ஏற்பட்டுள்ளது, அவற்றுக்கு இடையே உள்ள இடைவெளிதான் நீங்கள் இப்போது நீக்கிய கோப்பு.
நீக்கப்பட்ட கோப்பை வைத்திருக்கும் process-ஐக் கண்டறிதல்
ஒவ்வொரு திறந்த கோப்பு descriptor-ம் /proc/<pid>/fd/-ன் கீழ், அது குறிக்கும் கோப்பிற்கான symbolic link-ஆகக் காணப்படும். கோப்பு unlinked செய்யப்பட்டவுடன், அந்த link-ன் இலக்கை kernel நீக்கப்பட்டதாகக் குறிக்கும். எனவே, அந்த marker-ஐக் கொண்ட link-ஐக் கண்டறிவதே கோப்பை வைத்திருப்பவரைக் கண்டறியும் வழியாகும்.
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null-lname என்பது symbolic link-ன் பெயரை விட அதன் இலக்கைப் பொருத்துகிறது, %p descriptor பாதையை அச்சிடுகிறது, மற்றும் %l அது எதைச் சுட்டிக்காட்டுகிறது என்பதை அச்சிடுகிறது. அது அச்சிடும் பாதையின் இரண்டாவது உறுப்பு process ID ஆகும். இதை sudo உடன் இயக்கவும், இல்லையெனில் உங்கள் சொந்த process-களுக்கான /proc/<pid>/fd-ஐ மட்டுமே உங்களால் படிக்க முடியும். stderr redirect, find இயங்கும்போது வெளியேறும் process-களிலிருந்து வரும் தேவையற்ற தகவல்களை நீக்குகிறது.
ஒரு busy server-ல் எந்த நேரத்திலும் பல நீக்கப்பட்ட கோப்புகள் இருக்கும், அவற்றில் பெரும்பாலானவை சிறியவை மற்றும் பாதிப்பில்லாதவை. அவற்றை அளவின் அடிப்படையில் வரிசைப்படுத்தினால் மட்டுமே முக்கியமானவை மேலே இருக்கும்.
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 பெயர் இல்லாத கோப்பின் அளவைப் புகாரளிக்கிறது. அந்த எண்ணின் அடிப்படையில் வரிசைப்படுத்தினால் பெரிய கோப்பு முதலில் வரும்.
பின்னர், அந்த descriptor-க்கு பின்னால் உள்ள process-ஐ அடையாளம் காணவும். அந்தப் பட்டியலின் உச்சியில் உள்ள பாதையில் உங்களுக்குத் தேவையான இரண்டு எண்களும் உள்ளன, எனவே அவற்றை முதலில் variables-ல் சேமிக்கவும், PID மற்றும் N ஆகியவற்றை உங்கள் பட்டியலில் அச்சிடப்பட்ட எண்களைக் கொண்டு மாற்றவும்.
pid=PID
n=N
ps -o pid,user,etime,args -p "$pid"
sudo stat -L "/proc/$pid/fd/$n"ps நிரலின் பெயரைக் குறிப்பிடுகிறது மற்றும் அது எவ்வளவு காலம் இயங்குகிறது என்பதைக் காட்டுகிறது. stat -L நீக்கப்பட்ட inode-ன் அளவு மற்றும் ஒதுக்கப்பட்ட block எண்ணிக்கையை அச்சிடுகிறது. இவை இரண்டும் சேர்ந்து, எந்த service இந்த கோப்பை உயிர்ப்புடன் வைத்திருக்கிறது என்ற முக்கியமான கேள்விக்கு விடையளிக்கிறது.
இயந்திரத்தில் ஏற்கனவே lsof இருந்தால், sudo lsof +L1 என்பது link எண்ணிக்கை பூஜ்ஜியமாகக் குறைந்த திறந்த கோப்புகளைப் பட்டியலிட்டு, அவற்றின் அளவுகளை ஒரே அட்டவணையில் காட்டுகிறது. இது minimal Ubuntu image-ல் இருக்காது, மேலும் போதிய இடவசதி இல்லாத filesystem-ல் ஒரு package-ஐ நிறுவுவது தோல்வியடையக்கூடும், எனவே /proc முறை எப்போதும் செயல்படும் பதிப்பாகும்.
Reboot செய்யாமல் இடவசதியை விடுவித்தல்
Reboot செய்வது இந்தச் சிக்கலைச் சரிசெய்யும், ஆனால் அதுவே முதல் நடவடிக்கையாக இருக்கக்கூடாது: அது சேவையை நிறுத்துவதுடன், ஆதாரங்களையும் அழித்துவிடும். இதைச் சரிசெய்ய நான்கு மென்மையான வழிகள் உள்ளன; அவற்றை வரிசைப்படி முயற்சிக்கவும்.
முதலில், உங்களுக்குத் தரவு தேவைப்பட்டால் அதை நகலெடுத்துக்கொள்ளுங்கள். Descriptor பாதையை வாசிப்பது, தற்போது பயன்பாட்டில் உள்ள inode-ஐ வாசிப்பதற்குச் சமம்.
sudo cp /proc/<pid>/fd/<n> /root/recovered.logநீக்கப்பட்ட கோப்பை மீட்டெடுக்கக்கூடிய ஒரே சூழல் இதுதான். இதனால்தான் rm -rf மூலம் நீக்கப்பட்ட கோப்புகளை மீட்டெடுத்தல் பகுதியில், ஏதேனும் ஒரு process அந்த கோப்பைத் திறந்து வைத்துள்ளதா என்று முதலில் கேட்கப்படுகிறது. கடைசி descriptor மூடப்பட்டவுடன், அந்த வழி அடைக்கப்பட்டுவிடும்.
இரண்டாவதாக, descriptor வழியாகக் கோப்பை காலி செய்யுங்கள். /proc பாதை அதே inode-ஐக் குறிப்பதால், அதை truncate செய்வது process இயங்கிக்கொண்டிருக்கும்போதே கோப்பின் தொகுதிகளை (blocks) விடுவிக்கும்.
sudo truncate -s 0 "/proc/$pid/fd/$n"
df -h /எழுதும் process கோப்பை append முறையில் திறந்திருந்தால் இது சரியாக வேலை செய்யும், ஏனெனில் ஒவ்வொரு எழுதும் செயலும் கோப்பின் இறுதிப் பகுதியிலேயே நடக்கும். இல்லையெனில், process அதன் பழைய write offset-ஐ வைத்திருக்கும்; எனவே அடுத்தமுறை எழுதும்போது கோப்பின் முன்பகுதியில் ஒரு இடைவெளி (hole) உருவாகும். இந்த இடைவெளிக்குத் தொகுதிகள் ஒதுக்கப்படுவதில்லை, எனவே அவை காலியாகவே இருக்கும் மற்றும் df விடுவிக்கப்பட்ட இடத்தைத் தக்கவைக்கும். கோப்பின் அளவு மட்டுமே மீண்டும் பழைய நிலைக்குத் திரும்பும்: process எழுதிய பிறகு மீண்டும் sudo stat -L "/proc/$pid/fd/$n" கட்டளையை இயக்கினால், அது தொகுதிகளின் எண்ணிக்கையுடன் பொருந்தாத பழைய அளவையே காட்டும். கோப்பின் அளவு பூஜ்ஜியத்திலிருந்து தொடங்க வேண்டுமெனில், process-ஐ restart செய்யவும்.
மூன்றாவதாக, log கோப்புகளை மீண்டும் திறக்குமாறு சேவையிடம் கேளுங்கள். ஒரு daemon-ன் log கோப்பு நீக்கப்பட்டால் ஏற்படும் சிக்கல் இதுவே. பல daemon-கள் ஒரு signal கிடைத்தவுடன் log கோப்புகளை மீண்டும் திறக்கும்: nginx-க்கு SIGUSR1 மற்றும் rsyslog-க்கு SIGHUP பயன்படுத்தப்படுகிறது. யூகிக்காமல், அந்தந்த daemon-ன் ஆவணங்களைச் சரிபார்க்கவும், ஏனெனில் தவறான daemon-க்குத் தவறான signal அனுப்பினால் அது நின்றுவிடும்.
sudo systemctl kill -s USR1 nginxநான்காவதாக, unit-ஐ restart செய்யவும். sudo systemctl restart <unit> பழைய process வைத்திருந்த அனைத்து descriptor-களையும் மூடிவிடும், எனவே தொகுதிகள் நிச்சயமாகத் திரும்பக் கிடைக்கும். மேலே உள்ள உதாரணத்தில், நீங்களே தொடங்கிய 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-ஐக் காட்டாது. சிக்கலைக் கண்டறிந்த அதே கட்டளையைக் கொண்டு சரிபார்ப்பது ஒரு நல்ல பழக்கம்.
ஒவ்வொரு முறையும் df கட்டளையை நீங்களே இயக்குவதை விட, அந்த மதிப்பு மாறுவதைக் கவனிப்பது எளிது. watch ஒரு கட்டளையை குறிப்பிட்ட இடைவெளியில் மீண்டும் இயக்குகிறது மற்றும் வெளியீட்டை அதே இடத்தில் புதுப்பிக்கும், எனவே df கட்டளையைப் பயன்படுத்தும்போது, இடம் விடுவிக்கப்படுவதை watch df -h / மூலம் நிகழ்நேரத்தில் பார்க்கலாம்.
மொத்த அளவுகள் சரியாக இருந்தும் வட்டு நிரம்பியிருக்கும்போது
df மற்றும் root du -x ஆகியவற்றுக்கு இடையே கணக்கீடு ஒத்துப்போனால், நீக்கப்பட்ட கோப்புகள் எதற்கும் இதில் தொடர்பில்லை. மீதமுள்ள காரணங்கள் வேறுபட்ட தன்மையைக் கொண்டவை, ஒவ்வொன்றையும் தனித்தனியாகச் சரிபார்க்க வேண்டும்.
இனோட்கள் (inodes) தீர்ந்துவிடுதல், பிளாக்குகள் (blocks) அல்ல
ஒரு கோப்பின் மெட்டாடேட்டாவை (metadata) ஒரு இனோடு (inode) வைத்திருக்கும். ஒரு கோப்பு முறைமையை (filesystem) உருவாக்கும்போதே ext4 ஒரு குறிப்பிட்ட எண்ணிக்கையிலான இனோட்களை உருவாக்கிவிடும். எனவே, காலியான பிளாக்குகள் இருந்தபோதிலும், இனோட்கள் தீர்ந்துபோக வாய்ப்புள்ளது. அப்போது df -h கட்டளை இடமிருப்பதாகக் காட்டினாலும், புதிய கோப்புகளை உருவாக்க முடியாது.
df -h /
df -i /முதல் கட்டளை பிளாக்குகளையும், இரண்டாவது கட்டளை இனோட்களையும் கணக்கிடுகிறது. ஒவ்வொன்றின் பயன்பாட்டு நெடுவரிசையையும் (use column) ஒப்பிட்டுப் பார்க்கவும். பிளாக் பயன்பாடு குறைவாகவும், இனோடு பயன்பாடு உச்சத்திலும் இருந்தால், மிகச்சிறிய கோப்புகள் அதிக எண்ணிக்கையில் இருப்பதுதான் பிரச்சினை.
df கட்டளையானது -i மற்றும் --output ஆகியவற்றை ஒரே நேரத்தில் ஏற்காது. எனவே, மூல எண்களைப் பெற அல்லது மற்றொரு கட்டளைக்கு உள்ளீடாக வழங்க விரும்பினால், இனோடு புலங்களை மட்டும் பெயரிட்டுத் தேர்வு செய்யவும், -i-ஐத் தவிர்க்கவும்.
df --output=itotal,iused,iavail,ipcent /அந்த நெடுவரிசைகள் df -i காட்டும் அதே கணக்கீடுகளைக் கொண்டுள்ளன, அவற்றை எளிதாகப் பிரித்தெடுக்க முடியும்.
பைட்டுகளுக்குப் பதிலாக கோப்புகளின் எண்ணிக்கையைக் கொண்டு அவற்றைக் கண்டறியவும்.
sudo du --inodes -x -d 1 / 2>/dev/null | sort -rn | headஅதிக எண்ணிக்கையிலான கோப்புகளைக் கொண்ட கோப்பகத்தில் (directory), அதே கட்டளையை அடுத்தடுத்த நிலைகளில் மீண்டும் இயக்கவும். கோப்புகளை உருவாக்கும் கோப்பகக் கட்டமைப்பை அடையும் வரை இதைத் தொடரவும். உங்கள் du கட்டளை --inodes-ஐ ஆதரிக்கவில்லை என்றால், sudo find /var -xdev -type f | wc -l கட்டளையைப் பயன்படுத்தி ஒரு துணை மரத்தை (subtree) மெதுவான முறையில் கணக்கிடலாம்.
இதற்கான தீர்வு, அந்தக் கோப்புகளை நீக்குவது அல்லது நகர்த்துவது ஆகும். ஏற்கனவே உள்ள ext4 கோப்பு முறைமையில் இனோட்களை அதிகரிக்க முடியாது, ஏனெனில் அதன் எண்ணிக்கை mkfs நேரத்திலேயே நிர்ணயிக்கப்பட்டுவிடும். அதை அதிகரிக்க வேண்டுமெனில், கோப்பு முறைமையை மீண்டும் உருவாக்கி, பேக்கப்பிலிருந்து தரவுகளை மீட்டெடுக்க வேண்டும். XFS கோப்பு முறைமை தேவைக்கேற்ப இனோட்களை ஒதுக்கீடு செய்யும், எனவே அதில் இத்தகைய நிலையான வரம்பு இருப்பதில்லை. கண்டெய்னர்களை (containers) இயக்கும் ஒரு கணினியில், இமேஜ் லேயர்கள் (image layers) பல சிறிய கோப்புகளைக் கொண்டிருப்பதால், இந்த வரம்புகள் விரைவில் எட்டப்படும். அத்தகைய கணினிகளில் VPS-ல் Docker வட்டு பயன்பாட்டைச் சுத்தம் செய்தல் என்பதே சரியான தீர்வாகும்; இது கோப்பு முறைமையைச் பொதுவாகச் சுத்தம் செய்வதை விட அதிக இடத்தைச் சேமித்துத் தரும்.
Mount point-க்கு அடியில் மறைந்துள்ள இடம்
ஒரு directory-ல் எதையும் mount செய்வதற்கு முன்பே அதில் கோப்புகள் இருக்கலாம். அந்த directory-ன் மேல் ஒரு filesystem-ஐ mount செய்தால், அடியில் உள்ள கோப்புகள் அப்படியே இருக்கும்: அவை தொடர்ந்து ஒதுக்கீடு செய்யப்பட்டிருக்கும், df மூலம் கணக்கிடப்படும், ஆனால் அவற்றின் பெயரால் அவற்றை அணுக முடியாது. அந்த mount அவற்றை மறைத்துவிடுவதால் du-ஆல் அவற்றைப் பார்க்க முடியாது.
இதை tmpfs கொண்டு நிரூபிப்போம், இதற்கு கூடுதல் disk தேவையில்லை. இதற்கு 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-ஐக் காட்டுகிறது. அந்த நகல் எங்கும் செல்லவில்லை: அது root filesystem-லேயே உள்ளது, நீங்கள் unmount செய்தவுடன் மீண்டும் தெரிந்துவிடும். இப்போது, யாராவது ஒரு volume-ஐ mount செய்வதற்கு முன்பு ஒரு மாதம் அந்தப் பாதையில் log செய்த ஒரு service-ஐக் கற்பனை செய்து பாருங்கள்.
இயங்கிக்கொண்டிருக்கும் server-ல் உண்மையான கோப்புகளைக் கண்டறிய, root filesystem-ஐ வேறொரு இடத்தில் மீண்டும் mount செய்யவும். ஒரு bind mount, தனக்குள் mount செய்யப்பட்டுள்ள பிற filesystem-கள் இல்லாமல், அந்த 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அந்தப் பட்டியலில் தோன்றும் எதற்கும், சாதாரண பாதையில் தெரியாத கோப்புகள் ஒரு mount point-க்கு அடியில் மறைந்துள்ளன என்று அர்த்தம். உங்கள் வேலை முடிந்ததும் அந்த bind mount-ஐ unmount செய்யவும், இல்லையெனில் -x இல்லாத ஒரு du அதே கோப்புகளை இரண்டு முறை கணக்கிடும்.
root பயனருக்காக ஒதுக்கப்பட்ட தொகுதிகள் (Blocks)
ext4 கோப்பு முறைமை, தனது தொகுதிகளில் ஒரு பகுதியை root பயனருக்காக ஒதுக்கி வைக்கிறது. இதனால் வட்டு (disk) முழுமையாக நிரம்பினாலும், root பயனர் உள்நுழைந்து கணினியைச் சரிசெய்ய முடியும். சாதாரண பயனர் இயக்கும் ஒரு செயல்முறை (process) வட்டு நிரம்பியவுடன் தடையைச் சந்திக்கும், ஆனால் df கட்டளை இன்னும் சிறிது இடம் இருப்பதை காட்டும். இயல்புநிலை அமைப்பை அப்படியே நம்பாமல், உங்கள் கோப்பு முறைமையில் உள்ள அமைப்பைச் சரிபார்க்கவும்.
dev=$(df --output=source / | tail -n 1)
sudo tune2fs -l "$dev" | grep -i 'block count'tune2fs -l /dev/sda1 | grep -E 'Block count|Reserved block count'
இது மொத்த தொகுதி எண்ணிக்கை மற்றும் ஒதுக்கப்பட்ட தொகுதி எண்ணிக்கையை ஒரே அலகுகளில் அச்சிடும், எனவே அவற்றுக்கு இடையேயான விகிதத்தை நேரடியாக அறியலாம். df கட்டளை, சாதாரண பயனர் பயன்படுத்தக்கூடிய இடத்தையே 'available' நெடுவரிசையில் காட்டுகிறது. இதனால்தான், பயன்படுத்தப்பட்ட இடம் மற்றும் கிடைக்கக்கூடிய இடத்தைக் கூட்டினால், மொத்த அளவை விடக் குறைவாக வருகிறது. இந்த இடைவெளிதான் ஒதுக்கப்பட்ட பகுதி (reserve).
sudo tune2fs -m <percent> "$dev" கட்டளையைப் பயன்படுத்தி இதை மாற்றலாம். இந்த மாற்றம் உடனடியாகச் செயல்படும், கோப்பு முறைமையை மீண்டும் mount (remount) செய்யத் தேவையில்லை. தனிப்பட்ட தரவு கோப்பு முறைமைகளில் (data filesystem) இந்த ஒதுக்கப்பட்ட அளவைக் குறைப்பது நியாயமானது. ஆனால், root கோப்பு முறைமையில் (root filesystem) root பயனர் எழுதுவதற்குத் தேவையான இடத்தைப் போதுமான அளவு விட்டுவிடவும்; ஏனெனில், முற்றிலும் காலியாக இல்லாத ஒரு root கோப்பு முறைமையைச் சரிசெய்வது மிகவும் கடினம். tune2fs கட்டளை ext2, ext3 மற்றும் ext4 ஆகியவற்றில் செயல்படும். XFS கோப்பு முறைமையில் இதற்கு இணையான அமைப்பு எதுவும் இல்லை.
du கட்டளை தவறான தகவல்களைத் தரும் சூழல்கள்
du-ன் நான்கு பழக்கவழக்கங்கள் தவறான மொத்த அளவுகளைக் காட்டக்கூடும்.
- Hard links: பல பெயர்கள் ஒரே inode-ஐக் குறிப்பிட்டாலும்,
duஅதை ஒருமுறை மட்டுமே கணக்கிடும். எனவே, hard links நிறைந்த ஒரு கோப்பகத்தின் அளவு, அதன் கோப்புகளின் கூட்டுத்தொகையை விடக் குறைவாகக் காட்டும். - Sparse files:
duதற்போது ஒதுக்கப்பட்டுள்ள blocks-ன் அளவை மட்டுமே காட்டும், ஆனால்ls -lகோப்பின் தோற்ற அளவை (apparent size) காட்டும். மற்றொன்றைக் காண--apparent-size-ஐச் சேர்க்கவும். - Permissions: சாதாரண பயனராக இயக்கும்போது,
duதம்மால் படிக்க முடியாத கோப்புகளைத் தவிர்த்துவிடும், இதனால் அளவு குறைவாகக் காட்டப்படும். இது காட்டும் பிழைகளை மக்கள் பெரும்பாலும்/dev/null-க்குத் திருப்பிவிட்டு, அவற்றைப் படிக்காமல் விட்டுவிடுவார்கள். - Filesystem boundaries:
-xஇல்லாமல் இயக்கும்போது,du /என்பது/-க்குக் கீழே mount செய்யப்பட்டுள்ள அனைத்து filesystem-களையும் கணக்கிடும். இதனால் இதன் மொத்த அளவுdf /காட்டும் அளவை விட அதிகமாக இருக்கலாம்.
df-க்கும் தெரிந்துகொள்ள வேண்டிய ஒரு பழக்கம் உள்ளது. இது ஒவ்வொரு filesystem-ஐயும் தனித்தனியாகக் காட்டும். எனவே, எழுதும் பணி தோல்வியடையும் குறிப்பிட்ட பாதையில் இதை இயக்கவும். kernel packages சேரும்போது, ஒரு தனி /boot அதன் சொந்த கால அட்டவணையில் நிரம்பும். எனவே, Ubuntu-வில் பழைய kernel-களை நீக்குவது என்பது /-ல் இடத்தைச் சுத்தம் செய்வதிலிருந்து மாறுபட்ட ஒரு பணியாகும்.
ஒரு உண்மையான சம்பவத்திற்கான செயல்பாட்டு முறை
- தோல்வியுற்ற எழுத்து (failed write) எந்த filesystem-ஐ இலக்காகக் கொண்டதோ, அதில்
df -h <path>மற்றும்df -i <path>கட்டளைகளை இயக்கவும்; மாறாக, பழக்கத்தின் அடிப்படையில்/-ல் இயக்க வேண்டாம். sudo du -xh -d 1 <mountpoint> 2>/dev/null | sort -hகட்டளையை இயக்கவும், பின் அதிக அளவு இடத்தைப் பயன்படுத்தும் directory-க்குள் செல்லவும்.dfகாட்டும் பயன்பாட்டிற்கு,du-ஆல் கணக்கு காட்ட முடியவில்லை என்றால், நீக்கப்பட்டும் இன்னும் open நிலையில் உள்ள கோப்புகளைக் கண்டறிய/proc-ல் தேடவும்.- இரண்டும் ஒத்துப்போனால், அந்த filesystem-ஐ வேறொரு இடத்தில் bind mount செய்து, mount point-க்கு அடியில் மறைந்திருக்கும் கோப்புகளைத் தேடவும்.
- inode பயன்பாடு வரம்பை எட்டியிருந்தால், bytes-க்கு பதிலாக கோப்புகளின் எண்ணிக்கையை கணக்கிடவும்.
மேலே உள்ள ஒவ்வொரு படியிலும் ஒரு கட்டளை உள்ளது, அதன் வெளியீட்டை நீங்கள் வாசிக்க முடியும். இதுவே, யூகத்தின் அடிப்படையில் செயல்படுவதற்கும், சிக்கலைத் தீர்ப்பதற்கும் உள்ள வேறுபாடாகும்.
FAQ
du குறைவான இடத்தையே காட்டும்போது, df ஏன் வட்டு முழுமையாக இருப்பதாகக் காட்டுகிறது?
ஒரு கோப்பு (file) நீக்கப்பட்ட பிறகும், ஒரு process அதைத் தொடர்ந்து திறந்து வைத்திருப்பதே இதற்குப் பொதுவான காரணம். கோப்பை நீக்கும்போது அதன் directory entry நீக்கப்பட்டுவிடுகிறது, எனவே du அந்தப் பாதையைத் தேட முடியாமல் கணக்கீட்டை நிறுத்திவிடுகிறது. ஆனால், கடைசி descriptor மூடப்படும் வரை அந்த inode மற்றும் அதன் blocks ஒதுக்கீடு செய்யப்பட்டே இருக்கும்; df அந்த ஒதுக்கீடு செய்யப்பட்ட blocks-ஐயே கணக்கிடுகிறது. நீக்கப்பட்டதாகக் குறிக்கப்பட்ட symbolic links-ஐக் கண்டறிய /proc/<pid>/fd-ஐப் பயன்படுத்தவும்; இதன் மூலம் அந்தப் பெரிய கோப்பையும் அதை வைத்திருக்கும் process-ஐயும் கண்டறியலாம். இந்த ஒப்பீட்டை நம்புவதற்கு முன், du-ஐ root பயனராகவும் -x flag-உடனும் இயக்கியுள்ளீர்களா என்பதை உறுதிப்படுத்தவும்; இல்லையெனில், சாதாரண பயனரால் படிக்க முடியாத directories தானாகவே தவிர்க்கப்படும்.
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null இல்லாமல், திறந்திருக்கும் நீக்கப்பட்ட கோப்பை எப்படிக் கண்டறிவது?
Kernel-ன் open descriptors பதிவுகளைப் பயன்படுத்தவும். sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null பெயரற்ற கோப்புகளைச் சுட்டிக்காட்டும் அனைத்து descriptors-களையும் பட்டியலிடும்; அது காட்டும் பாதையிலேயே process ID இருக்கும். அந்த descriptor பாதைகளில் sudo stat -Lc %s-ஐ இயக்கினால் அதன் அளவு தெரியும், இதன் மூலம் பெரிய கோப்புகளை வரிசைப்படுத்தித் தேவையற்றதை நீக்கலாம். இதற்கு எந்தப் புதிய package-உம் தேவையில்லை; வட்டில் இடமில்லாதபோது புதிய மென்பொருளை நிறுவுவது தோல்வியடையக்கூடும் என்பதால் இது முக்கியமானது.
process-ஐ நிறுத்தாமலேயே இடத்தைச் (space) சுதந்திரமாக்க முடியுமா?
சில நேரங்களில் முடியும். sudo truncate -s 0 /proc/<pid>/fd/<n> அந்த descriptor வழியாக அதே inode-ஐ அணுகி, process இயங்கிக்கொண்டிருக்கும்போதே அதன் blocks-ஐ விடுவிக்கும். process அந்தக்கோப்பை append mode-ல் திறந்திருந்தால் இது மிகவும் பாதுகாப்பானது, ஏனெனில் அதன் எழுதும் செயல்பாடு எப்போதும் கோப்பின் இறுதிப்பகுதியிலேயே நடக்கும். இல்லையெனில், write offset பழைய இடத்திலேயே இருக்கும்; அடுத்தமுறை எழுதும்போது கோப்பின் தொடக்கத்தில் இடைவெளியுடன் (hole) புதிய கோப்பு உருவாகும், இதனால் வட்டு அளவு மீண்டும் நிரம்பியதாகக் காட்டும். இதற்கான சரியான தீர்வு, அந்த unit-ஐ restart செய்வது அல்லது அதன் ஆவணங்களில் குறிப்பிடப்பட்டுள்ள signal-ஐ அனுப்பி logs-ஐ மீண்டும் திறக்கச் செய்வதுதான்; இது sparse file உருவாவதைத் தடுக்கும்.
df இடவசதி இருப்பதாகக் காட்டுகிறது, ஆனால் கோப்புகளை எழுத முடியவில்லை. வேறு என்ன காரணமாக இருக்கும்?
df -i மூலம் inodes-ஐச் சரிபார்க்கவும், ஏனெனில் வட்டில் blocks காலியாக இருந்தாலும் inodes காலியாக இல்லையெனில் புதிய கோப்புகளை உருவாக்க முடியாது. நீங்கள் root அல்லாத பயனராக இயங்கும்போது, ext4 filesystem-ல் reserved blocks மட்டுமே எஞ்சியிருக்கலாம்; இதைச் சரிபார்க்க சாதனத்தில் sudo tune2fs -l-ஐ இயக்கவும். நீங்கள் எழுதும் கோப்பு எந்த filesystem-ல் உள்ளது என்பதைச் சரிபார்க்கவும், ஏனெனில் தனித்தனி /boot அல்லது /var ஆகியவை /-லிருந்து சுதந்திரமாகவே நிரம்பும்.
df-ஐ விட du ஏன் அதிக மொத்த அளவைக் காட்டுகிறது?
-x இல்லாமல் du-ஐ இயக்கினால், அது நீங்கள் குறிப்பிட்ட பாதைக்குக் கீழே உள்ள அனைத்து mounted filesystems-களையும் சேர்த்து கணக்கிடும்; இதனால் பல filesystems-ன் அளவு கூட்டப்படும், ஆனால் df ஒரு குறிப்பிட்ட filesystem-ஐ மட்டுமே விவரிக்கும். Bind mounts இருந்தால் இது இன்னும் சிக்கலாகும், ஏனெனில் ஒரே கோப்பு அது தோன்றும் ஒவ்வொரு பாதையிலும் மீண்டும் மீண்டும் கணக்கிடப்படும். du-ஐ ஒரே filesystem-க்குள் வைத்திருக்க -x-ஐச் சேர்க்கவும், மேலும் df-க்கு அதே பாதையைக் கொடுக்கவும்; அப்போதுதான் இரண்டு கட்டளைகளும் ஒரே தரவை விவரிக்கும்.