Asosiy kontentga o‘tish

Maqolalar

Maqola · 2026-08-16 · ~6 daqiqa o‘qiladi · o'rta

nohup emas, systemd: bot serverda qanday qilib 24/7 yashaydi

#linux #systemd #telegram-bot #devops #deploy

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.

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

[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
ExecStart=/opt/aladdin_bot/.venv/bin/python app.py

# yiqilsa — 5 soniyadan keyin o'zi turadi
Restart=always
RestartSec=5
# lekin cheksiz emas: 1 daqiqada 5 martadan ko'p yiqilsa, to'xtab turadi
# (buzuq deploy'ni cheksiz qayta urinishdan saqlaydi)
StartLimitIntervalSec=60
StartLimitBurst=5

[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.

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:

# jonli oqim (Ctrl+C bilan chiqiladi)
sudo journalctl -u aladdin_bot -f

# oxirgi soatdagi xatolar
sudo journalctl -u aladdin_bot --since "1 hour ago" -p err

# 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 "python app.py"
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 journalctl -u aladdin_bot -p err --since today qarab turing, 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.