Asosiy kontentga o‘tish

Maqolalar 7 daqiqa 215 ko‘rish

«Sayt yotibdi!» — journalctl bilan sababni besh daqiqada topish

Xizmat yiqilganda taxmin bilan emas, loglar bilan ishlanadi. journalctl'ning kundalik ishda kerak bo'ladigan qismini o'rganamiz: to'g'ri savol berish, vaqt bo'yicha toraytirish, yashirin restart-halqalarni ushlash va jurnal diskni yeb qo'ymasligini ta'minlash.

linux devops

Mundarija

Qo'ng'iroq keladi: "sayt ochilmayapti". Shu daqiqada ikki xil yo'l bor. Birinchisi — taxmin qilish: restart berib ko'ramiz, balki o'tib ketar. Ikkinchisi — jurnalga qarash va nima bo'lganini bilib harakat qilish. Birinchi yo'l ba'zan tezroq tuyuladi, lekin sabab topilmagani uchun muammo ertaga yana qaytadi. Bu maqola ikkinchi yo'l haqida.

Seriya davomida hamma xizmatni systemd ostiga olib, loglarni stdout'ga yozdirib keldik — endi shu intizom o'z mevasini beradi: hamma narsaning jurnali bitta joyda, bitta tool bilan o'qiladi.

Boshlanish nuqtasi: status va oxirgi satrlar#

Muammo bo'lganda birinchi buyruq har doim bitta:

Terminal
systemctl status mysite-web

Bu yerda uch narsani birdan ko'rasiz: xizmat holati (active, failed, activating auto-restart...), qachondan beri shu holatda ekani va — eng foydalisi — jurnaldan oxirgi o'nta satr. Ko'p hollarda sabab shu o'nta satrning ichida yozib turadi: import xatosi, band port, topilmagan fayl.

Yetmasa, jurnalning o'zini ochamiz:

Terminal
journalctl -u mysite-web -e     # -e: oxiridan boshlab ko'rsat
journalctl -u mysite-web -f     # -f: jonli oqim (yangi satrlar tushib turadi)

Jurnalni o'qish huquqi

1-qismda yaratgan deploy foydalanuvchisi jurnalni to'liq ko'rmaydi. Ilovaning o'z chiqishi ko'rinadi, lekin systemd'ning xabarlari (Started, Failed) va nginx, postgres kabi boshqa xizmatlarning yozuvlari chiqmaydi — pastdagi tekshiruvlar esa aynan shularga tayanadi. Buyruqlarni sudo bilan bering yoki deployni bir marta jurnal guruhiga qo'shing: sudo usermod -aG systemd-journal deploy, keyin serverdan chiqib, qayta kiring.

To'g'ri savol berish san'ati#

journalctl -u mysite-web ni ochsangiz, oldingizda minglab satr turadi. Loglar bilan ishlashning asosiy mahorati — hammasini o'qish emas, so'rovni toraytirish. Uchta filtr kundalik ishning to'qson foizini yopadi:

Terminal
# vaqt bo'yicha: muammo qachon boshlangan bo'lsa, o'sha atrofga qaraymiz
journalctl -u mysite-web --since "14:20" --until "14:40"
journalctl -u mysite-web --since "10 min ago"

# matn bo'yicha: Python xatolari (pattern kichik harfda — katta-kichikka qaramaydi)
journalctl -u mysite-web -g "traceback|error" --since today
journalctl -u mysite-web -g "Timeout" --since yesterday   # katta harf bor — aniq moslik

# daraja bo'yicha: systemd'ning ogohlantirish va xatolari (yiqilishlar)
journalctl -u mysite-web -p warning --since today

Ilova xatolarini nega -p err bilan emas, matn bilan qidiryapmiz? systemd xizmatning stdout va stderr'iga yozilgan har bir satrni jurnalga bir xil info darajasida yozadi — Python traceback'i ham bundan mustasno emas. Shuning uchun journalctl -u mysite-web -p err ilova yiqilib yotgan paytda ham -- No entries -- deyishi mumkin. -p daraja bilan yozadigan dasturlarda va systemd'ning o'z xabarlarida ishlaydi: masalan, xizmat yiqilganda chiqadigan Failed with result 'exit-code' — warning.

Sayt 500 qaytaryapti, jurnal esa jim

DEBUG = False bo'lganda Django 500 xatolarining traceback'ini standart holatda konsolga chiqarmaydi — faqat ADMINS ga email yuborishga urinadi. Natijada foydalanuvchi "Server Error" ko'radi, jurnalda esa hech narsa yo'q.

Xatolar jurnalga tushishi uchun sozlamaga bitta blok qo'shing:

Python
# config/settings.py
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {"console": {"class": "logging.StreamHandler"}},
    "loggers": {"django": {"handlers": ["console"], "level": "ERROR"}},
}

Endi har 500 xato jurnalda Internal Server Error: /yo'l/ va to'liq traceback bilan paydo bo'ladi.

Va yana bittasi — reboot bilan bog'liq muammolarda oltinga teng:

Terminal
journalctl -b          # faqat shu yonishdan beri
journalctl -b -1 -e    # OLDINGI yonishning oxiri — o'chishdan avval nima bo'lgan?

-b -1 ko'p narsani ochib beradi: server o'zi o'chib qolgan bo'lsa, sababning izi (masalan OOM-killer ishi) aynan oldingi sessiyaning so'nggi satrlarida qoladi.

Yashirin kasallik: restart-halqa#

Restart=always bilan ishlaydigan xizmatning bir ayyor holati bor: u yiqilib-turib ishlayotgan bo'lishi mumkin — har safar restart uni qutqaradi va tashqaridan hammasi joyida ko'rinadi. Buni Aladdin seriyasida ogohlantirgan edim, endi ushlash usulini ko'rsataman:

Terminal
# bugun necha marta ishga tushgan?
sudo journalctl -u mysite-web --since today | grep -c "Started"

# oxirgi qo'lda start/restart'dan beri systemd uni necha marta o'zi qayta ko'targan?
systemctl show mysite-web -p NRestarts

Bugun deploy ham, reboot ham bo'lmagan bo'lsa, birinchi javob 0 bo'lishi kerak; bo'lgan bo'lsa — ularning soniga teng. NRestarts=0 bo'lishi kerak. Javob 47 chiqsa — xizmatingiz kun bo'yi o'lib-tirilib yurgan. Sabab odatda takrorlanuvchi xato bo'ladi va uni yiqilish paytlarining logidan topasiz:

Terminal
# oxirgi yiqilish atrofi: "Main process exited" dan oldingi satrlarda traceback turadi
sudo journalctl -u mysite-web -n 60 --no-pager

Qatlamlarni ajratish: log qaysi savolga javob beradi#

Muammo har doim ham ilovada emas. "Sayt ochilmayapti" degan shikoyat ortida to'rt xil qatlam turishi mumkin va har birining o'z jurnali bor:

Savol Qayerga qaraymiz
Umuman serverga yetib kelyaptimi? tashqaridan curl -I va serverda sudo tail -f /var/log/nginx/access.log — bu ayrimda server emas, tarmoq muammosi bo'lib chiqadi
Nginx qabul qilib, orqaga uzatolmayaptimi? /var/log/nginx/error.log — 502 tekshiruv tartibi
Ilova ichida xato bormi? journalctl -u mysite-web -g traceback
Baza javob bermayaptimi? sudo tail -n 50 /var/log/postgresql/postgresql-16-main.log

Birinchi va oxirgi qatorga e'tibor bering: Ubuntu'da nginx va PostgreSQL o'z loglarini jurnalga emas, fayllarga yozadi. journalctl -u nginx yoki journalctl -u postgresql da faqat ishga tushish va to'xtash xabarlari bo'ladi (nginx konfiguratsiyasi xato bo'lib ishga tushmasa, sababi ham shu yerda). Fayl nomidagi 16-main — PostgreSQL versiyasi va klaster nomi, o'zingizdagisini ls /var/log/postgresql/ ko'rsatadi.

Tartib muhim: tashqaridan ichkariga qarab yurasiz. Har qatlamda "bu qatlam sog'mi?" degan bitta savolga javob olasiz va muammo qaysi chegarada yotganini toraytirasiz — xuddi binar qidiruv kabi.

Jurnalning o'zi diskni yemasin#

Bitta amaliy detal ko'pincha e'tibordan chetda qoladi: journald ham disk egallaydi va default sozlamalarda ancha keng yashaydi. Kichik VPS'da buni chegaralab qo'ygan ma'qul:

Terminal
sudo nano /etc/systemd/journald.conf
INI
[Journal]
# jurnal reboot'dan keyin ham saqlansin (default ba'zan RAM'da!)
Storage=persistent
# jami hajm chegarasi — eski yozuvlar o'zi o'chadi
SystemMaxUse=500M

Izohlarni qiymat bilan bir qatorga yozmang. systemd qator ichidagi # ni izoh deb bilmaydi: Storage=persistent # ... ni butun holicha qiymat deb o'qiydi, Failed to parse storage setting, ignoring deydi va sozlamani jimgina tashlab yuboradi.

Terminal
sudo systemctl restart systemd-journald
# sozlama qabul qilinganini tekshiramiz — "max 500.0M" ko'rinishi kerak:
sudo journalctl -u systemd-journald -n 3 --no-pager
sudo journalctl --disk-usage    # hozir qancha joy egallayotganini ko'rsatadi

Storage=persistent'ni tekshiring

Ba'zi tizimlarda jurnal faqat xotirada yashaydi — reboot bo'ldi, loglar yo'q. Ayni "server nega o'chdi" degan eng muhim savolni tekshirayotganda -b -1 bo'sh chiqadi. Storage=persistent bir qator, lekin aynan qora kunda kerak bo'ladigan qator.

Yakun#

Loglar bilan ishlash tartibi qisqa: systemctl statusdan boshlang, vaqt va daraja bilan toraytiring, reboot masalasida -b -1ni unutmang, restart- halqani grep -c "Started" bilan tekshiring va qatlamma-qatlam tashqaridan ichkariga yuring. Restart — davolash emas, og'riq qoldiruvchi; tashxis esa har doim jurnalda.

Seriyaning so'nggi qismi oldinda: sirlarni boshqarish — token va parollar qayerda yashashi kerak, qayerda esa hech qachon ko'rinmasligi kerak.

7 daqiqa 215 marta o‘qildi