Сервер дискини энг кўп "жимгина" тўлдирадиган нарса лог файллардир. Илова ҳар бир хатони, веб-сервер ҳар бир сўровни, тизим эса ҳар бир ҳодисани ёзиб боради ва ҳеч ким бу файлларни тозаламаса, улар ойлар давомида гигабайтлаб ўсади. Диск 100 фоизга етганда маълумотлар базаси ёзишни тўхтатади, сессиялар сақланмайди ва сайт хато қайтара бошлайди. Linux'да бу муаммонинг стандарт ечими logrotate дастуридир: у логларни белгиланган жадвал бўйича айлантиради, эскиларини сиқади ва керакли сондан ортиғини ўчиради.
Дискни нима тўлдираётганини аниқлаш
Созлашдан олдин айнан қайси логлар катта эканини билиш керак. Аввал дискнинг умумий ҳолатини, сўнгра /var/log ичидаги энг катта папка ва файлларни кўриб чиқинг. Кўп ҳолларда айбдор битта-иккита файл бўлади: илованинг хато логи ёки веб-сервернинг кириш логи.
df -h /
sudo du -sh /var/log/* 2>/dev/null | sort -h | tail -10
journalctl --disk-usage
Агар /var/log кичик бўлса-ю, диск барибир тўла бўлса, илова папкасини ҳам текширинг. Laravel'нинг storage/logs, WordPress'нинг wp-content/debug.log ёки ўзингиз ёзган скриптларнинг логлари кўпинча стандарт ротациядан ташқарида қолади, чунки тизим улар ҳақида билмайди.
Мисол: мактаб сайтидаги 4 ГБ лик хато логи
Самарқанддаги хусусий мактабнинг Laravel'да ёзилган misol.uz сайти бир куни ўқувчилар баҳоларини сақламай қўйди. Текширувда маълум бўлдики, илова бир неча ой давомида ҳар бир сўровда бир хил огоҳлантиришни ёзган ва laravel.log ҳажми 4 ГБ га етиб, дискдаги бўш жойни тугатган. Файлни тозалаш муаммони вақтинча ҳал қилди, лекин асосий тузатиш икки қисмдан иборат бўлди: огоҳлантириш манбаи кодда тузатилди ва логлар учун logrotate қоидаси қўшилди. Шундан кейин лог ҳеч қачон бир неча ўн мегабайтдан ошмади.
logrotate қандай ишлайди
Асосий созламалар /etc/logrotate.conf файлида, алоҳида хизматлар учун қоидалар эса /etc/logrotate.d/ папкасида сақланади. Кўпчилик тарқатмаларда logrotate кунига бир марта systemd таймери ёки cron орқали ишга тушади. Ҳар бир қоида қайси файлларга тегишли эканини, қанчалик тез-тез айлантиришни, нечта эски нусхани сақлашни ва айлантиришдан кейин нима қилишни белгилайди. Масалан, rotate 14 ва daily биргаликда "сўнгги 14 кунлик логни сақла, ундан эскисини ўчир" деган маънони беради.
Илова логлари учун қоида ёзиш
Илова учун алоҳида файл яратинг, масалан /etc/logrotate.d/misol. Қуйидаги қоида логларни ҳар куни айлантиради, 14 та нусхани сақлайди ва уларни gzip билан сиқади. delaycompress энг охирги нусхани бир кун сиқмасдан қолдиради, бу эса ҳали ёзиб бўлинмаган файлни бузиб қўймаслик учун фойдали.
/var/www/misol/storage/logs/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
}
copytruncate директиваси файлни нусхалаб, кейин асл файлни нолга қисқартиради. Бу усул логни очиқ ҳолда ушлаб турадиган ва сигнал орқали қайта очишни билмайдиган иловалар учун қулай. Унинг камчилиги шундаки, нусхалаш ва қисқартириш орасидаги қисқа вақтда ёзилган бир неча қатор йўқолиши мумкин. Агар дастур логни қайта очишни қўллаб-қувватласа, create ва postrotate усули ишончлироқ.
Nginx логлари ва postrotate
Nginx пакети одатда ўз қоидаси билан келади, лекин уни тушуниб олиш фойдали. Бу ерда эски файл бошқа номга ўтказилади, янгиси керакли ҳуқуқлар билан яратилади ва Nginx'га USR1 сигнали юборилади. Сигнал олган Nginx лог файлларини қайта очади ва янги файлга ёза бошлайди, хизматни қайта ишга тушириш шарт эмас.
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
sharedscripts бўлмаса, postrotate блоки ҳар бир лог файл учун алоҳида бажарилади. У билан эса барча файллар айлантирилгандан кейин бир марта ишлайди, бу кўп доменли серверларда ортиқча сигналларнинг олдини олади.
Қоидани синаш
Янги қоидани дарҳол ишончли деб ҳисобламанг. -d параметри ҳеч нарсани ўзгартирмасдан нима қилинишини кўрсатади, -f эса вақтдан қатъи назар айлантиришни мажбуран бажаради. Натижада папкада .1 ва кейинроқ .gz кенгайтмали файллар пайдо бўлиши керак.
sudo logrotate -d /etc/logrotate.d/misol
sudo logrotate -f /etc/logrotate.d/misol
ls -lh /var/www/misol/storage/logs/
systemd журнали ва ўчирилган, лекин очиқ файллар
journalctl --disk-usage катта ҳажм кўрсатса, журнални ҳам чеклаш керак. Уни бир марталик тозалаш ва доимий чегара қўйиш мумкин.
sudo journalctl --vacuum-size=500M
# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
sudo systemctl restart systemd-journald
Баъзан лог файл қўлда rm билан ўчирилган бўлса ҳам диск бўшамайди. Сабаби, уни ёзаётган жараён файлни ҳали очиқ ушлаб туради ва жой жараён тўхтамагунча қайтарилмайди. Бундай файлларни қуйидаги буйруқ кўрсатади; ечим тегишли хизматни қайта ишга тушириш. Шу сабабли фаол логни ўчириш ўрнига уни truncate -s 0 билан бўшатган маъқул.
sudo lsof +L1 | grep -i log
Shared хостингда ўз logrotate'ингиз
Shared хостингда тизим ва веб-сервер логларини провайдер бошқаради, лекин иловангизнинг ўз логлари сизнинг квотангиздан жой олади. Root ҳуқуқи бўлмаса ҳам logrotate'ни оддий фойдаланувчи сифатида ишга тушириш мумкин: бунинг учун ўз созлама файлингиз ва ўз ҳолат файли (-s) керак. Буйруқни ISPmanager панелидаги cron вазифалари орқали кунлик жадвалга қўясиз. Йўлларни ўз аккаунтингизга мосланг ва logrotate серверда қайси манзилда турганини which logrotate билан текширинг.
# ~/logrotate.conf
/home/user/www/misol.uz/storage/logs/*.log {
weekly
rotate 8
compress
missingok
notifempty
copytruncate
}
# cron: har kuni 03:30 da
30 3 * * * /usr/sbin/logrotate -s $HOME/.logrotate.state $HOME/logrotate.conf
Агар хостингда бундай буйруқ мавжуд бўлмаса ёки квота тез-тез тўлса, sayt.uz техник ёрдамига мурожаат қилиб, логларингиз ва диск сарфингизни бирга кўриб чиқишингиз мумкин. Энг муҳими, логни фақат тозалаш эмас, уни ўстираётган такрорий хатони ҳам топиб тузатиш: акс ҳолда ротация муаммони фақат яширади.