Tarkibga o'tish

Loyiha: Healthcheck skripti

Backup skripti loyihasi fayllarni himoya qilishni avtomatlashtirdi. Bu loyiha e’tiborni boshqa narsaga qaratadi: server hali ham sog'lommi — diskda joy bormi, muhim servislar ishlayaptimi, tizim yuklamasi normalmi? Bunday tekshiruvni kuniga bir necha marta qo'lda qilish shart emas. Uni healthcheck.sh nomli skriptga topshirish mumkin: skript natijani monitoring tizimi tushunadigan aniq exit kod bilan bildiradi.

Maqsad va yakuniy natija

Skript disk bandligini, xotirani va ko'rsatilgan systemd servislarining holatini tekshiradi, har bir tekshiruv natijasini alohida chiqaradi va oxirida umumiy holatni uch darajali exit kod bilan bildiradi: 0 (OK), 1 (WARNING), 2 (CRITICAL). Bu Nagios/Icinga kabi monitoring tizimlarida keng qo'llaniladigan kelishuv. U skriptni mavjud monitoring infratuzilmasiga oson ulash imkonini beradi.

Boshlang'ich holat

mkdir -p ~/lab/healthcheck-project
cd ~/lab/healthcheck-project

Bu loyiha haqiqiy tizim ma’lumotlarini (disk, xotira, systemd servislari) o'qiydi. Alohida test muhiti kerak emas, lekin natijalar joriy tizimingizga qarab farq qiladi.

Talablar

  • df, free, systemctl — Ubuntu Server LTS’da standart holatda mavjud;
  • namuna sifatida tekshirish uchun kamida bitta ishlab turgan systemd servisi (masalan, ssh yoki cron);
  • ixtiyoriy: bu skriptni systemd timer yoki cron orqali muntazam ishga tushirish.

Xavfsizlik bo'yicha eslatma

Bu skript faqat o'qish amallarini bajaradi (df, free, systemctl status) — u hech qanday faylni o'zgartirmaydi yoki o'chirmaydi, shuning uchun maxsus orqaga qaytarish choralari kerak emas. E’tibor berish kerak bo'lgan yagona narsa — systemctl chaqiruvlarini sudo siz, faqat o'qish rejimida ishlatish (restart yoki stop emas, systemctl status/is-active).

Bosqichma-bosqich qurish

1-qadam: diskni tekshirish

#!/bin/bash
set -uo pipefail

# healthcheck.sh — checks disk, memory, and service state
# Exit code: 0 = OK, 1 = WARNING, 2 = CRITICAL

DISK_WARN=75
DISK_CRIT=90
MEM_WARN=80
MEM_CRIT=95
SERVICES=("ssh" "cron")

overall_status=0   # 0=OK, 1=WARNING, 2=CRITICAL

raise_status() {
    local new_status="$1"
    if [ "$new_status" -gt "$overall_status" ]; then
        overall_status="$new_status"
    fi
}

check_disk() {
    local mount="$1"
    local used_percent
    used_percent=$(df --output=pcent "$mount" | tail -n 1 | tr -d '% ')

    if [ "$used_percent" -ge "$DISK_CRIT" ]; then
        echo "CRITICAL: disk ($mount) ${used_percent}% used"
        raise_status 2
    elif [ "$used_percent" -ge "$DISK_WARN" ]; then
        echo "WARNING: disk ($mount) ${used_percent}% used"
        raise_status 1
    else
        echo "OK: disk ($mount) ${used_percent}% used"
    fi
}

check_disk "/"

Note

Bu yerda set -uo pipefail set -e siz ishlatilgan. Sababi — bu skript ichidagi systemctl is-active kabi buyruqlar ba’zan noldan farqli exit kod bilan tugashi kutilgan (ishlamayotgan servisni aniqlash uchun). set -e esa butun skriptni aynan shu "kutilgan muvaffaqiyatsizlik"da to'xtatib qo'ygan bo'lardi. Bu Exit kodlar maqolasidagi ogohlantirishning amaliy misoli: set -e har doim ham to'g'ri tanlov emas, ayniqsa skriptning o'zi muvaffaqiyatsizlik holatlarini faol tekshirishi kerak bo'lgan monitoring vazifasida.

Tekshirish:

chmod +x healthcheck.sh
./healthcheck.sh

Kutilgan natija (foizlar tizimga qarab farq qiladi):

OK: disk (/) 42% used

2-qadam: xotirani tekshirish

check_memory() {
    local mem_used_percent
    mem_used_percent=$(free | awk '/Mem:/ {printf "%.0f", $3/$2 * 100}')

    if [ "$mem_used_percent" -ge "$MEM_CRIT" ]; then
        echo "CRITICAL: memory ${mem_used_percent}% used"
        raise_status 2
    elif [ "$mem_used_percent" -ge "$MEM_WARN" ]; then
        echo "WARNING: memory ${mem_used_percent}% used"
        raise_status 1
    else
        echo "OK: memory ${mem_used_percent}% used"
    fi
}

free ning ikkinchi qatori (Mem:) umumiy ($2) va ishlatilgan ($3) xotirani ustunlar sifatida beradi. awk shu ikkisidan foizni hisoblaydi. Uni chaqiring:

check_disk "/"
check_memory

Tekshirish va kutilgan natija:

OK: disk (/) 42% used
OK: memory 61% used

3-qadam: servis holatini tekshirish

check_service() {
    local service="$1"

    if systemctl is-active --quiet "$service"; then
        echo "OK: service '$service' is running"
    else
        echo "CRITICAL: service '$service' is not running"
        raise_status 2
    fi
}

Ro'yxatdagi (SERVICES massivi) har bir kerakli servisni tekshirish:

for service in "${SERVICES[@]}"; do
    check_service "$service"
done

"${SERVICES[@]}" massivning har bir elementini alohida so'z sifatida beradi — xuddi skript argumentlari uchun "$@" kabi.

Tekshirish:

./healthcheck.sh

Kutilgan natija:

OK: disk (/) 42% used
OK: memory 61% used
OK: service 'ssh' is running
OK: service 'cron' is running

Ro'yxatga ataylab mavjud bo'lmagan servis nomini qo'shib ko'ring:

SERVICES=("ssh" "nonexistent-service")
OK: service 'ssh' is running
CRITICAL: service 'nonexistent-service' is not running

4-qadam: umumiy holatni exit kod sifatida qaytarish

echo "---"
case "$overall_status" in
    0) echo "OVERALL STATUS: OK" ;;
    1) echo "OVERALL STATUS: WARNING" ;;
    2) echo "OVERALL STATUS: CRITICAL" ;;
esac

exit "$overall_status"

Tekshirish:

./healthcheck.sh
echo "Script exit code: $?"

Kutilgan natija (barcha tekshiruvlar OK bo'lganda):

...
OVERALL STATUS: OK
Script exit code: 0

Amaliy vaziyat: monitoring tizimiga ulash

Muammo: healthcheck natijasini har safar qo'lda o'qish kerak emas — u monitoring tizimiga (yoki oddiy ogohlantirish skriptiga) avtomatik uzatilishi kerak.

if ./healthcheck.sh > /tmp/healthcheck-output.txt; then
    echo "Server is healthy"
else
    status=$?
    echo "A problem was detected (level: $status):"
    cat /tmp/healthcheck-output.txt
fi

Chaqiruvchi skript healthcheck.sh ning ichki mantiqini bilishi shart emas — u faqat exit kodni (0, 1 yoki 2) va chiqish matnini o'qiydi. Bu Funksiyalar maqolasidagi "natija exit kod orqali, tafsilotlar matn orqali" tamoyilining butun skript darajasida qo'llanishi.

To'liq skript

#!/bin/bash
set -uo pipefail

# healthcheck.sh — checks disk, memory, and service state
# Exit code: 0 = OK, 1 = WARNING, 2 = CRITICAL

DISK_WARN=75
DISK_CRIT=90
MEM_WARN=80
MEM_CRIT=95
SERVICES=("ssh" "cron")

overall_status=0

raise_status() {
    local new_status="$1"
    if [ "$new_status" -gt "$overall_status" ]; then
        overall_status="$new_status"
    fi
}

check_disk() {
    local mount="$1"
    local used_percent
    used_percent=$(df --output=pcent "$mount" | tail -n 1 | tr -d '% ')

    if [ "$used_percent" -ge "$DISK_CRIT" ]; then
        echo "CRITICAL: disk ($mount) ${used_percent}% used"
        raise_status 2
    elif [ "$used_percent" -ge "$DISK_WARN" ]; then
        echo "WARNING: disk ($mount) ${used_percent}% used"
        raise_status 1
    else
        echo "OK: disk ($mount) ${used_percent}% used"
    fi
}

check_memory() {
    local mem_used_percent
    mem_used_percent=$(free | awk '/Mem:/ {printf "%.0f", $3/$2 * 100}')

    if [ "$mem_used_percent" -ge "$MEM_CRIT" ]; then
        echo "CRITICAL: memory ${mem_used_percent}% used"
        raise_status 2
    elif [ "$mem_used_percent" -ge "$MEM_WARN" ]; then
        echo "WARNING: memory ${mem_used_percent}% used"
        raise_status 1
    else
        echo "OK: memory ${mem_used_percent}% used"
    fi
}

check_service() {
    local service="$1"

    if systemctl is-active --quiet "$service"; then
        echo "OK: service '$service' is running"
    else
        echo "CRITICAL: service '$service' is not running"
        raise_status 2
    fi
}

check_disk "/"
check_memory

for service in "${SERVICES[@]}"; do
    check_service "$service"
done

echo "---"
case "$overall_status" in
    0) echo "OVERALL STATUS: OK" ;;
    1) echo "OVERALL STATUS: WARNING" ;;
    2) echo "OVERALL STATUS: CRITICAL" ;;
esac

exit "$overall_status"

Troubleshooting bo'yicha maslahatlar

  • df --output=pcent ishlamayapti — bu flag coreutils ning yetarlicha yangi versiyasini talab qiladi. Juda eski tizimda muqobil sifatida df -h / | awk 'NR==2 {print $5}' | tr -d '%' dan foydalanish mumkin.
  • check_service har doim CRITICAL deb xabar beradi — servis nomi to'g'ri yozilganini tekshiring (systemctl list-units --type=service bilan). Ba’zi servislar .service qo'shimchasi bilan ham, usiz ham ishlaydi, lekin nom aynan mos kelishi kerak.
  • Skript set -e bilan kutilmaganda to'xtaydi — yuqorida tushuntirilganidek, bu loyihada set -e ataylab ishlatilmagan. Uni qo'shish "muvaffaqiyatsizlik normal holat" bo'lgan systemctl is-active kabi buyruqlar skriptni to'xtatib qo'yishiga olib kelishi mumkin.
  • Turli monitoring tizimlari exit kodni turlicha talqin qilishi mumkin — skriptni haqiqiy monitoring tizimiga ulashdan oldin har doim uning hujjatlarida qaysi exit kod qaysi jiddiylik darajasiga mos kelishini tekshiring.

Orqaga qaytarish va tozalash

Skript tizim holatini o'zgartirmagani uchun orqaga qaytarish kerak emas. Shunchaki lab fayllarini o'chiring:

rm -rf ~/lab/healthcheck-project

Yakuniy baholash mezoni

Quyidagilarning hammasi bajarilsa, loyiha muvaffaqiyatli hisoblanadi:

  • disk, xotira va kamida ikkita servis tekshiriladi;
  • har bir tekshiruv natijasi alohida, aniq xabar bilan chiqariladi;
  • umumiy holat alohida tekshiruvlarning o'rtachasidan emas, eng yomon (eng yuqori) darajadan hisoblanadi;
  • skriptning exit kodi (0/1/2) uning chiqishida ko'rsatilgan "OVERALL STATUS" ga mos keladi;
  • ataylab ishlamaydigan servis qo'shilganda skript uni to'g'ri ravishda CRITICAL deb aniqlaydi.

Xulosa

Bu loyiha Exit kodlar maqolasidagi "har bir vaziyat uchun alohida kod" tamoyilini uch darajali monitoring kelishuviga (OK/WARNING/CRITICAL) kengaytirdi va bir nechta mustaqil tekshiruvni (check_disk, check_memory, check_service) funksiyalar orqali tartibli tashkil qildi. Keyingi loyiha, Log tozalash skripti, e’tiborni tekshirishdan yana tozalashga qaratadi — disk joyini egallab turgan eski log'larni xavfsiz o'chirishga.

Manbalar