Пишем скрипт для проверки сайта

Пишем скрипт для проверки сайта

Ручная диагностика хороша один раз. Но сайты нужно проверять регулярно: после каждого деплоя, раз в час, при мониторинге. В этом уроке напишем простой health-check скрипт на bash, который проверяет состояние сайта и сообщает о проблемах.

Что должен проверять health-check

Минимальный набор проверок для любого сайта:

  1. Сайт отвечает? (HTTP 200)
  2. HTTPS работает? (редирект с HTTP на HTTPS, сертификат валиден)
  3. Время ответа приемлемое? (TTFB < 1 секунды)
  4. Ключевые заголовки на месте? (HSTS, Content-Type, no-sniff)

Скрипт: базовая версия

#!/bin/bash
# health-check.sh — проверка состояния сайта

DOMAIN="${1:?Укажи домен (например: ./health-check.sh example.com)}"
TIMEOUT=10

echo "=== Health check: $DOMAIN ==="

# 1. Проверка HTTPS (статус-код)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time "$TIMEOUT" "https://$DOMAIN")
if [ "$HTTP_CODE" = "200" ]; then
  echo "✓ HTTPS отвечает 200 OK"
else
  echo "✗ HTTPS: HTTP $HTTP_CODE (ожидался 200)"
fi

# 2. Проверка редиректа HTTP → HTTPS
REDIRECT=$(curl -s -o /dev/null -w "%{redirect_url}" --max-time "$TIMEOUT" "http://$DOMAIN")
if [[ "$REDIRECT" == https://* ]]; then
  echo "✓ HTTP редиректит на HTTPS ($REDIRECT)"
else
  echo "✗ HTTP не редиректит на HTTPS"
fi

# 3. Измерение времени ответа
TTFB=$(curl -s -o /dev/null -w "%{time_starttransfer}" --max-time "$TIMEOUT" "https://$DOMAIN")
if (( $(echo "$TTFB < 1.0" | bc -l) )); then
  echo "✓ TTFB: ${TTFB}с (хорошо, < 1с)"
elif (( $(echo "$TTFB < 3.0" | bc -l) )); then
  echo "⚠ TTFB: ${TTFB}с (медленно, < 3с)"
else
  echo "✗ TTFB: ${TTFB}с (очень медленно!)"
fi

Добавляем проверку заголовков

# 4. Проверка HSTS
if curl -sI "https://$DOMAIN" --max-time "$TIMEOUT" | grep -qi 'strict-transport-security'; then
  echo "✓ HSTS присутствует"
else
  echo "✗ HSTS отсутствует — рекомендуется добавить"
fi

# 5. Проверка X-Content-Type-Options
if curl -sI "https://$DOMAIN" --max-time "$TIMEOUT" | grep -qi 'x-content-type-options: nosniff'; then
  echo "✓ X-Content-Type-Options: nosniff"
else
  echo "✗ X-Content-Type-Options: nosniff отсутствует"
fi

# 6. Проверка Content-Type HTML-страницы
CONTENT_TYPE=$(curl -sI "https://$DOMAIN" --max-time "$TIMEOUT" | grep -i 'content-type' | head -1)
if echo "$CONTENT_TYPE" | grep -q 'text/html'; then
  echo "✓ Content-Type: text/html"
else
  echo "✗ Content-Type: $CONTENT_TYPE (ожидался text/html)"
fi

Добавляем проверку DNS

# 7. DNS A-запись
if host "$DOMAIN" > /dev/null 2>&1; then
  IP=$(host "$DOMAIN" | grep 'has address' | awk '{print $NF}')
  echo "✓ DNS: $DOMAIN → $IP"
else
  echo "✗ DNS: $DOMAIN не резолвится"
fi

# 8. Проверка www-поддомена
if host "www.$DOMAIN" > /dev/null 2>&1; then
  echo "✓ DNS: www.$DOMAIN резолвится"
else
  echo "⚠ DNS: www.$DOMAIN не резолвится (возможно, нет редиректа)"
fi

Добавляем проверку сертификата

# 9. Срок действия сертификата
CERT_EXPIRY=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null \
  | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -n "$CERT_EXPIRY" ]; then
  EXPIRY_EPOCH=$(date -j -f "%b %d %T %Y" "$CERT_EXPIRY" +%s 2>/dev/null)
  NOW_EPOCH=$(date +%s)
  DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
  if [ "$DAYS_LEFT" -gt 30 ]; then
    echo "✓ Сертификат действителен ещё $DAYS_LEFT дней"
  elif [ "$DAYS_LEFT" -gt 0 ]; then
    echo "⚠ Сертификат истекает через $DAYS_LEFT дней!"
  else
    echo "✗ Сертификат истёк!"
  fi
else
  echo "✗ Не удалось получить сертификат"
fi

echo "=== Проверка завершена ==="

Запуск и использование

# Сделать исполняемым
chmod +x health-check.sh

# Проверить сайт
./health-check.sh example.com

# Вывод:
# === Health check: example.com ===
# ✓ HTTPS отвечает 200 OK
# ✓ HTTP редиректит на HTTPS (https://example.com/)
# ✓ TTFB: 0.18с (хорошо, < 1с)
# ✓ HSTS присутствует
# ✓ X-Content-Type-Options: nosniff
# ✓ Content-Type: text/html
# ✓ DNS: example.com → 93.184.216.34
# ✓ DNS: www.example.com резолвится
# ✓ Сертификат действителен ещё 77 дней
# === Проверка завершена ===

Что можно добавить

Health-check можно расширять под конкретные нужды:

  • Проверка API-эндпоинта. POST /api/health должен вернуть {"status":"ok"}.
  • Проверка robots.txt. Должен быть доступен и не блокировать важные страницы.
  • Проверка CORS. Есть ли Access-Control-Allow-Origin на API-эндпоинте.
  • Проверка CSP. Не в Report-Only ли режиме (проверить наличие Content-Security-Policy-Report-Only).
  • Проверка через разные локации. Использовать внешний сервис для проверки из другого региона.

Интеграция с CI/CD

Такой скрипт можно запускать после каждого деплоя:

# .github/workflows/deploy.yml
- name: Health check
  run: |
    sleep 10  # дать серверу перезагрузиться
    ./scripts/health-check.sh ${{ vars.DOMAIN }}

Или настроить периодический запуск через cron (раз в 5 минут), слать алерт в Telegram/Slack, если скрипт вернул ненулевой код.

Проверь себя

  1. Зачем проверять HTTP-редирект на HTTPS, а не только HTTPS напрямую?
  2. Что такое TTFB и почему оно важно для health-check?
  3. Почему проверку DNS включают в health-check?
<details> <summary>Ответы</summary>
  1. Пользователь может набрать сайт без https://, и если сервер не делает редирект — соединение останется на HTTP, уязвимо к перехвату. Проверка редиректа гарантирует, что все посетители получат HTTPS.
  2. TTFB — время до первого байта. Если оно резко выросло, это сигнал проблемы: сервер перегружен, база данных медленно отвечает. Базовый мониторинг TTFB ловит деградацию до того, как сайт упадёт.
  3. Если DNS не работает — сайт недоступен. Также часты ошибки: забыли продлить домен, неправильно настроили www-поддомен.
</details>

Что унести с урока

  • Health-check скрипт — автоматическая проверка ключевых показателей: HTTPS, редирект, TTFB, заголовки, DNS, сертификат.
  • curl + bash — простой и мощный инструмент для мониторинга без внешних зависимостей.
  • Скрипт можно запускать в CI/CD после деплоя или по cron для мониторинга.

Заключительный урок курса — итоги и направления для роста: что мы изучили за 12 модулей, и куда двигаться дальше.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике