Maqolalar 8 daqiqa 86 ko‘rish
nohup emas, systemd: bot serverda qanday qilib 24/7 yashaydi
«nohup python app.py &» bilan ishga tushirilgan bot server reboot bo'lgan kuni jimgina o'ladi — va buni birinchi bo'lib mijoz sezadi. Botni systemd xizmatiga aylantiramiz: o'zi qayta ko'tariladi, reboot'dan omon chiqadi, loglari bir joyda turadi.
Mundarija
Bu qismni real voqea bilan boshlayman. Yaqinda serverga reboot berildi.
Saytlar ko'tarildi, systemd ostidagi xizmatlar ko'tarildi — lekin bitta bot
jim qoldi. Sababi oddiy ekan: u yillar oldin nohup python app.py & bilan
ishga tushirilgan va shu holicha ishlab yurgan. nohup jarayonni terminal
yopilishidan asraydi, ammo reboot'dan asramaydi. Bot o'ldi, hech qanday
ogohlantirish kelmadi, uzilishni birinchi bo'lib foydalanuvchi payqadi.
Bunday holatga qayta tushmaslik uchun bot oddiy jarayon emas, tizim xizmati bo'lishi kerak. Linux'da buning standart yo'li — systemd. Keling, Aladdin botini misol qilib, uni boshdan-oyoq systemd xizmatiga aylantiramiz.
Boshlashdan oldin: foydalanuvchi va papka#
Bot alohida tizim foydalanuvchisi nomidan ishlaydi. Bu foydalanuvchi serverga login qila olmaydi — uning yagona vazifasi botni ko'tarish:
sudo useradd --system --home-dir /opt/aladdin_bot --shell /usr/sbin/nologin botuser
# loyiha /opt/aladdin_bot da: ichida oldingi qismlardagi bot/ paketi,
# kutubxonalar (aiogram va boshqalar) esa .venv ichida; keyin egasini almashtiramiz:
sudo chown -R botuser:botuser /opt/aladdin_bot
ls /opt/aladdin_bot/.venv/bin/python /opt/aladdin_bot/bot/app.py # ikkalasi ham ko'rinishi kerak
Unit fayl: xizmatning pasporti#
systemd xizmati bitta matnli fayl bilan tavsiflanadi. Uni
/etc/systemd/system/ papkasiga qo'yamiz:
# /etc/systemd/system/aladdin_bot.service
[Unit]
Description=Aladdin Catalog Telegram Bot
# tarmoq ko'tarilmaguncha botni boshlamaymiz — aks holda birinchi
# so'rovlar "connection refused" bilan yiqiladi
After=network-online.target
Wants=network-online.target
# qayta urinishlar soniga cheklov qo'ymaymiz — pastda tushuntiraman
StartLimitIntervalSec=0
[Service]
Type=simple
# alohida foydalanuvchi: bot root bo'lib ishlamasligi kerak
User=botuser
WorkingDirectory=/opt/aladdin_bot
# sirlar unit faylda emas, .env faylda turadi (pastda tushuntiraman)
EnvironmentFile=/opt/aladdin_bot/.env
# print() chiqishi jurnalga darhol tushsin (pastda tushuntiraman)
Environment=PYTHONUNBUFFERED=1
# 2-qismdagidek paket sifatida: "python bot/app.py" import'larda yiqiladi
ExecStart=/opt/aladdin_bot/.venv/bin/python -m bot.app
# yiqilsa — 5 soniyadan keyin o'zi turadi; ketma-ket yiqilsa kutish asta
# uzayib boradi (5, 8, 13, 22... soniya), lekin 60 soniyadan oshmaydi
Restart=always
RestartSec=5
RestartSteps=5
RestartMaxDelaySec=60
[Install]
# multi-user.target'ga "ilingan" xizmat reboot'dan keyin avtomatik ko'tariladi
WantedBy=multi-user.target
Har satrning vazifasi izohda yozilgan, lekin uchta eng muhimini alohida
ta'kidlayman: Restart=always botni yiqilganda turg'izadi, WantedBy esa
reboot'dan keyin ishga tushiradi — ikkalasi birga bo'lgandagina bot chinakam
24/7 bo'ladi. User=botuser esa xavfsizlik odati: bot buzilsa ham, buzgan
odam root emas, oddiy foydalanuvchi huquqida qoladi.
«1 daqiqada 5 marta yiqilsa — to'xtasin» degan tuzoq
Ko'p qo'llanmalarda StartLimitIntervalSec=60 va StartLimitBurst=5
tavsiya qilinadi: buzuq deploy cheksiz qayta urinmasin, deb. Ikki narsani
bilib qo'ying. Birinchidan, bu qatorlar [Unit] bo'limida turishi shart —
[Service] ga yozilsa, systemd Unknown key name 'StartLimitIntervalSec'
deb interval'ni jimgina tashlab yuboradi. Ikkinchidan, to'g'ri joyda bu
cheklov "to'xtab turish" emas, butunlay taslim bo'lish: limitga
yetgan xizmat failed holatda qoladi va sabab yo'qolgach ham o'zi
qaytmaydi — sudo systemctl reset-failed aladdin_bot va qayta start
kerak. Sinovda Telegram API'ga yarim daqiqa ulana olmagan bot aynan
shunday abadiy o'ldi. 24/7 bot uchun yaxshirog'i yuqoridagi yo'l:
cheklov o'chiq, kutish esa RestartSteps va RestartMaxDelaySec
bilan o'sib boradi — buzuq deploy serverni qiynamaydi, tarmoq tiklangach
bot o'zi qaytadi.
RestartSteps va RestartMaxDelaySec systemd 254 dan beri bor
(Ubuntu 24.04 da 255). Eskiroq tizimda (masalan Debian 12) ular
Unknown key bilan e'tiborsiz qoladi va bot shunchaki har 5 soniyada
qayta urinadi — bu ham ishlaydigan holat. Versiyani systemctl --version
ko'rsatadi.
Ishga tushirish: uch buyruq#
# unit faylni o'qitamiz (har tahrirdan keyin ham shu kerak)
sudo systemctl daemon-reload
# hozir ishga tushirish + reboot ro'yxatiga qo'shish, bitta buyruqda
sudo systemctl enable --now aladdin_bot
# holatini ko'ramiz
sudo systemctl status aladdin_bot
status chiqishida Active: active (running) va enabled so'zlarini
ko'rsangiz — bo'ldi, bot endi xizmat. enabled aynan reboot'dan keyin
ko'tarilishni anglatadi; active bo'lib turgan, lekin disabled xizmat
keyingi reboot'da yana jim qoladi — yuqoridagi voqeadagi xatoning o'zi.
Loglar: nohup.out o'rniga journalctl#
nohup davrida loglar nohup.out degan faylga oqib borardi — u nazoratsiz
o'sadi va hech kim uni o'qimaydi. systemd'da esa stdout'ga yozilgan har
narsa avtomatik jurnalga tushadi. Ya'ni bot kodida oddiy print yoki
logging.StreamHandler yetarli, fayl bilan ishlash umuman shart emas.
Faqat print bilan bitta nozik joy bor — unit'dagi PYTHONUNBUFFERED=1
qatori shuning uchun. Terminalda Python har print ni darhol chiqaradi,
jurnalga yozganda esa chiqishni buferda yig'ib turadi. Sinovda bu qatorsiz
botning print xabarlari jurnalga umuman tushmadi — jarayon o'ldirilganda
bufer ham birga yo'qoldi. logging modulining xabarlari esa (aiogram ham
shu orqali yozadi) buferlanmaydi.
# jonli oqim (Ctrl+C bilan chiqiladi)
sudo journalctl -u aladdin_bot -f
# oxirgi soatdagi Python xatolari (traceback'lar)
sudo journalctl -u aladdin_bot --since "1 hour ago" -g "traceback|error"
# kecha kechqurun nima bo'lgani
sudo journalctl -u aladdin_bot --since "yesterday 18:00" --until "yesterday 23:00"
Log fayl emas, oqim
Ilova o'z logini faylga yozmasin — shunchaki stdout'ga chiqarsin, qolganini tizim hal qiladi. Bu 12-factor tamoyillaridan biri va systemd bilan u o'z-o'zidan ishlaydi: rotatsiya, saqlash muddati, qidiruv — hammasi journald zimmasida.
Sirlar: EnvironmentFile#
Bot tokeni, API kalitlari unit faylga yozilmaydi, chunki unit fayl
/etc/systemd/system/da hamma o'qiy oladigan joyda turadi. Ular alohida
faylga chiqariladi:
# /opt/aladdin_bot/.env
BOT_TOKEN=1234567890:AAF...
CATALOG_API_URL=https://catalog.misol.uz/api/telegram
# faqat egasi o'qiy oladi:
sudo chown botuser:botuser /opt/aladdin_bot/.env
sudo chmod 600 /opt/aladdin_bot/.env
EnvironmentFile= qatori tufayli bu o'zgaruvchilar botga muhit orqali
yetib boradi — kodda os.environ["BOT_TOKEN"] deb o'qiladi, fayl yo'li
haqida bot hech narsa bilmaydi.
Ishonch hosil qilish: ikkita sinov#
Sozlab bo'ldik — endi haqiqatan ishlashini tekshiramiz. Birinchi sinov, jarayonni ataylab o'ldiramiz:
sudo pkill -f "bot.app"
sleep 6
sudo systemctl status aladdin_bot # yana active (running) bo'lishi kerak
Ikkinchi sinov — reboot'ning o'zi. Buni "qachondir kerak bo'lganda" emas,
sozlagan kuningiz qiling: sudo reboot, bir daqiqadan keyin ulanib
systemctl status qarang. Ishlayaptimi — endi kechasi ham, ta'tilda ham
xotirjam uxlayverasiz. Bizning holatda aynan shu sinov qilinmagani uchun
bot yillar o'tib "jim o'lgan" edi.
Restart har dardga davo emas
Restart=always yiqilgan botni turg'izadi, lekin nega yiqilganini
aytmaydi. Bot har besh daqiqada qayta tug'ilib ishlayotgan bo'lishi ham
mumkin — tashqaridan hammasi joyida ko'rinadi. Vaqti-vaqti bilan
systemctl show aladdin_bot -p NRestarts va
sudo journalctl -u aladdin_bot -g traceback --since today qarab turing
(-p err bu yerda yordam bermaydi — botning chiqishi jurnalga oddiy
info darajasida tushadi), yoki
yaxshisi, xatolarni adminga yuboradigan bildirishnoma qo'shing —
Humo seriyasida shunga
o'xshash yondashuvni ko'rgan edik.
Xulosa#
Botni serverda uzoq yashatishning retsepti qisqa: nohup unutiladi, o'rniga
bitta unit fayl yoziladi. Unda uchta narsa hal qiluvchi — Restart=always
(yiqilsa turadi), WantedBy=multi-user.target + enable (reboot'dan omon
chiqadi) va EnvironmentFile (sirlar o'z joyida). Loglar journalctl'da,
sinov esa sozlagan kuni qilinadi, keyinga qoldirilmaydi.
Shu bilan Aladdin bot amaliyoti seriyasi yakunlandi: backend'dan ajratilgan katalog, adashtirmaydigan navigatsiya, uch til va o'lmas xizmat — besh yildan beri ishlab turgan botning to'liq retsepti. Server sozlashning qolgan qismi — nginx, TLS, backup va boshqalar — alohida DevOps seriyasida davom etadi.