Asosiy kontentga o‘tish

Maqolalar

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

systemd timer va avtomatik backup: tiklanmagan zaxira — zaxira emas

#linux #devops #database #deploy

Mundarija

Serverda muntazam bajariladigan ishlar bo'ladi: bazani zaxiralash, eski loglarni tozalash, hisobot yig'ish. An'anaviy javob — cron. Lekin systemd bilan ishlayotgan serverda (seriyaning 2-qismidan beri hamma xizmatimiz shunda) timer'lar ancha qulay: ishga tushish loglari journalctlda xizmatniki bilan yonma-yon turadi, vazifani qo'lda bir buyruq bilan sinash mumkin, server o'chiq paytga to'g'ri kelgan ishga tushishni esa keyin quvib yetish imkoni bor. Cron'da bularning har biri alohida bosh og'rig'i edi.

Timer'ni eng kerakli ishda ko'rsataman — kunlik baza zaxirasi. Yo'l-yo'lakay zaxiraning eng katta sirini ham aytaman: hech qachon tiklab ko'rilmagan backup — backup emas, umid xolos.

Juftlik: service + timer#

systemd'da rejali vazifa ikki fayldan iborat: ishning o'zi (.service) va jadval (.timer). Ular bir xil nomlanadi:

# /etc/systemd/system/db-backup.service
[Unit]
Description=Kunlik baza zaxirasi

[Service]
# oneshot: ishga tushdi, bajarib bo'ldi, chiqdi — doimiy xizmat emas
Type=oneshot
User=deploy
ExecStart=/opt/mysite/scripts/backup.sh
# /etc/systemd/system/db-backup.timer
[Unit]
Description=Har kuni 03:30 da zaxira

[Timer]
OnCalendar=*-*-* 03:30:00
# server o'sha payt o'chiq bo'lsa, yoqilgach darhol bajaradi —
# "kecha backup bo'lmabdi" degan bo'shliq qolmaydi
Persistent=true

[Install]
WantedBy=timers.target

E'tibor bering, yoqilganda service emas, timer enable qilinadi:

sudo systemctl daemon-reload
sudo systemctl enable --now db-backup.timer

systemctl list-timers db-backup.timer   # NEXT ustunida ertangi 03:30 ko'rinadi

Sinash uchun kutish shart emas

Timer'ning eng yoqimli tomoni shu: vazifani hoziroq qo'lda ishga tushirib ko'rasiz — sudo systemctl start db-backup.service — va natijani journalctl -u db-backup bilan o'qiysiz. Cron'da "yarim tunni kutamiz yoki jadvalni vaqtincha o'zgartiramiz" o'yini bor edi, bu yerda yo'q.

Zaxira skriptining o'zi#

Endi backup.shni yozamiz. Ikki keng tarqalgan holatni ko'rsataman — qaysi baza bo'lsa, o'shanisini oling:

#!/usr/bin/env bash
# /opt/mysite/scripts/backup.sh
set -euo pipefail   # xato bo'lsa jim davom etmasin — timer failed holatga tushsin

BACKUP_DIR=/var/backups/mysite
STAMP=$(date +%Y-%m-%d_%H%M)
mkdir -p "$BACKUP_DIR"

# --- SQLite bo'lsa ---
# oddiy cp EMAS: yozuv paytida ko'chirilgan fayl buzuq chiqishi mumkin.
# .backup buyrug'i esa bazani izchil holatda nusxalaydi
sqlite3 /opt/mysite/db.sqlite3 ".backup '$BACKUP_DIR/db_$STAMP.sqlite3'"
gzip "$BACKUP_DIR/db_$STAMP.sqlite3"

# --- PostgreSQL bo'lsa (yuqoridagi ikki qator o'rniga) ---
# pg_dump -Fc mysite > "$BACKUP_DIR/db_$STAMP.dump"

# 14 kundan eski nusxalarni tozalaymiz — disk cheksiz emas
find "$BACKUP_DIR" -name "db_*" -mtime +14 -delete

echo "backup tayyor: db_$STAMP"
chmod +x /opt/mysite/scripts/backup.sh
sudo systemctl start db-backup.service    # birinchi sinov
ls -lh /var/backups/mysite/               # fayl paydo bo'ldi

set -euo pipefail qatori mayda ko'ringani bilan muhim: usiz skript o'rtada xato bersa ham "muvaffaqiyatli" tugagan hisoblanadi va siz oylab bo'sh zaxira yig'ib yurishingiz mumkin. U bilan esa xato timer'ni failed holatga tushiradi — systemctl list-timers yoki monitoring buni darhol ko'rsatadi.

Zaxira serverning o'zida qolsa — bu ham yarim ish#

Server diski kuysa, undagi zaxiralar ham birga ketadi. Shuning uchun kamida bitta nusxa boshqa joyda turishi kerak. Eng arzon yo'l — skript oxiriga bitta qator qo'shib, faylni boshqa serverga yoki bulutga jo'natish:

# boshqa serverga (SSH kalit 1-qismda sozlangan edi):
rsync -a "$BACKUP_DIR/" backup@boshqa-server:/backups/mysite/

# yoki S3-ga o'xshash saqlashga (rclone oldindan sozlangan bo'lsa):
# rclone copy "$BACKUP_DIR" remote:mysite-backups

Eng muhim qadam: tiklashni sinash#

Endi va'da qilingan gap. Zaxira tizimini sozlagan odamlarning ko'pi bitta savolga javob berolmaydi: "shu fayldan bazani tiklab ko'rganmisiz?" Fayl har kuni yaratilayotgani hali hech narsani anglatmaydi — u buzuq bo'lishi, yarim bo'lishi, kerakli jadvallarsiz bo'lishi mumkin. Buni bilishning yagona yo'li — tiklab ko'rish:

# alohida papkada, jonli bazaga TEGMASDAN:
cd /tmp
gunzip -k /var/backups/mysite/db_2026-08-16_0330.sqlite3.gz -c > sinov.sqlite3

# ichi joyidami? jadvallar va yozuvlar sonini tekshiramiz:
sqlite3 sinov.sqlite3 ".tables"
sqlite3 sinov.sqlite3 "SELECT count(*) FROM auth_user;"
rm sinov.sqlite3

Tiklash mashqini kalendarga yozing

Bu bir martalik ish emas. Choraklik odat qiling: zaxiradan bazani sinov muhitiga tiklash, ilovani unga ulab bir aylanib chiqish. O'n besh daqiqa oladi, lekin "backup bor edi-ku!" degan eng achchiq jumladan saqlaydi — u odatda ma'lumot yo'qolgandan keyin, tiklash urinishi muvaffaqiyatsiz chiqqanda aytiladi.

Yakun#

Endi serverda o'zini o'zi qutqaradigan mexanizm bor: timer har kuni 03:30 da uyg'onadi, skript bazani izchil nusxalab siqadi, eskilarini tozalaydi va nusxani serverdan tashqariga jo'natadi. Xato bo'lsa failed holat ko'rinadi, o'chiq qolgan kun esa Persistent=true tufayli o'tkazib yuborilmaydi. Va siz vaqti-vaqti bilan tiklab ko'rasiz — chunki sinalmagan zaxira shunchaki fayl.

Keyingi qismda shu qurilgan tizimning yaxlitligini tekshiramiz: reboot'ga chidamlilik — server o'chib yonganda hamma narsa o'z-o'zidan qaytadigan holatga kelganini qanday kafolatlaymiz.