Прогрев кэша сайта

Универсальный подход для CMS и статических витрин · скрипт warm-cache.sh

~/snippet
#!/bin/bash
# Universal HTTP cache warmer (sitemap-driven).
# Usage:
#   SITE=https://example.com ./warm-cache.sh
#   nohup env SITE=https://example.com WAIT=1 ./warm-cache.sh >> warm.log 2>&1 &
#
# Optional: copy config.example.env to config.env and edit.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="${CONFIG_FILE:-$SCRIPT_DIR/config.env}"
WORKDIR="${WORKDIR:-$SCRIPT_DIR/data}"
WAIT="${WAIT:-1}"
USER_AGENT="${USER_AGENT:-Mozilla/5.0 (compatible; CacheWarm/1.0; +https://example.com/bot)}"
WGET_TIMEOUT="${WGET_TIMEOUT:-90}"
SITEMAP_URL="${SITEMAP_URL:-}"
CONNECT_TIMEOUT="${CONNECT_TIMEOUT:-30}"
SITEMAP_MAX_TIME="${SITEMAP_MAX_TIME:-600}"
LOG_FILE="${LOG_FILE:-$SCRIPT_DIR/warm.log}"

if [[ -f "$CONFIG_FILE" ]]; then
  # shellcheck source=/dev/null
  source "$CONFIG_FILE"
fi

: "${SITE:?Set SITE=https://your-domain.tld or create config.env from config.example.env}"

SITE="${SITE%/}"
SITEMAP_URL="${SITEMAP_URL:-$SITE/sitemap.xml}"

mkdir -p "$WORKDIR"
cd "$WORKDIR"

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

extract_loc() {
  grep -o '<loc>[^<]*' | sed 's/<loc>//'
}

collect_from_sitemap() {
  local index_url="$1"
  local tmp_index="$WORKDIR/sitemap_index.txt"

  log "Fetch sitemap index: $index_url"
  curl -fsS --connect-timeout "$CONNECT_TIMEOUT" --max-time 120 "$index_url" | extract_loc > "$tmp_index"

  if [[ ! -s "$tmp_index" ]]; then
    log "ERROR: empty sitemap index ($index_url)"
    exit 1
  fi

  : > urls.txt
  while IFS= read -r sm; do
    [[ -z "$sm" ]] && continue
    if [[ "$sm" == *.xml ]]; then
      log "  nested sitemap: $sm"
      curl -fsS --connect-timeout "$CONNECT_TIMEOUT" --max-time "$SITEMAP_MAX_TIME" "$sm" | extract_loc >> urls.txt
    else
      echo "$sm" >> urls.txt
    fi
  done < "$tmp_index"

  sort -u urls.txt -o urls.txt
}

warm_urls() {
  local total
  total=$(wc -l < urls.txt)
  local eta_h
  eta_h=$(awk -v n="$total" -v w="$WAIT" 'BEGIN{printf "%d", n*w/3600}')

  log "URLs to warm: $total (~${eta_h}h at ${WAIT}s per request)"
  log "Target: $SITE | UA: $USER_AGENT"

  wget \
    --input-file=urls.txt \
    --no-cookies \
    --delete-after \
    --timeout="$WGET_TIMEOUT" \
    --tries=2 \
    --wait="$WAIT" \
    --random-wait \
    --user-agent="$USER_AGENT" \
    --no-verbose \
    2>&1 | while IFS= read -r line; do log "wget: $line"; done
}

main() {
  log "=== cache warm start ==="

  if [[ -s urls.txt ]]; then
    log "Skip sitemap collect (urls.txt exists: $(wc -l < urls.txt) lines)"
  else
    log "Collect URLs from sitemap"
    collect_from_sitemap "$SITEMAP_URL"
  fi

  if [[ ! -s urls.txt ]]; then
    log "ERROR: urls.txt is empty"
    exit 1
  fi

  log "Start wget warm"
  warm_urls
  log "=== cache warm done ==="
}

main "$@"

Зачем это нужно

Первый запрос к странице почти всегда самый медленный: сервер собирает HTML, ходит в БД, собирает шаблон. Повторные запросы отдаются из кэша — быстрее в разы.

Прогрев кэша — заранее обойти важные URL так, как это делает поисковый робот или гость без cookies. После прогрева:

  • ниже время ответа сервера (TTFB);
  • меньше пиковой нагрузки в часы трафика;
  • спокойнее диагностика в Вебмастере и аналогах.

Как это работает

  1. Скачивается sitemap.xml (или указанный вами индекс).
  2. Из sitemap собирается список URL (поддерживаются вложенные sitemap-файлы).
  3. wget по очереди запрашивает каждый URL с паузой, без cookies, без сохранения файлов на диск (--delete-after).

Скрипт не привязан к конкретной CMS: подойдёт для 1С-Битрикс (композит + memcached), WordPress, Laravel, OpenCart и любого сайта с публичным sitemap.

Где запускать

МестоПлюсыМинусы
На самом сервереБыстро, не грузит канал, стабильная связьДополнительная нагрузка на CPU/RAM/диск
С другого VPSНе нагружает диск целевого сервераНужен нормальный доступ к сайту; легко «положить» сайт без лимитов

Рекомендуется запускать на сервере сайта в nohup и с паузой между запросами.

Быстрый старт

~/snippet
cd ~/cache-warm
cp config.example.env config.env
# отредактируйте SITE и WAIT в config.env

chmod +x warm-cache.sh
nohup ./warm-cache.sh >> warm.log 2>&1 &
tail -f warm.log

Или без файла конфигурации:

~/snippet
SITE=https://example.com WAIT=1 nohup ./warm-cache.sh >> warm.log 2>&1 &

Параметры

ПеременнаяПо умолчаниюОписание
SITEБазовый URL сайта (обязательно)
SITEMAP_URL$SITE/sitemap.xmlURL корневого sitemap
WAIT1Пауза между запросами (секунды, целое число)
USER_AGENTCacheWarm/1.0User-Agent для запросов
WORKDIR./dataКаталог для urls.txt и служебных файлов

Особенности по платформам

  • 1С-Битрикс: включите композитный кэш и memcached; для прогрева используйте UA поискового бота, --no-cookies уже в скрипте.
  • WordPress: прогревайте после плагинов кэша (WP Super Cache, W3 Total Cache и т.д.); sitemap часто от Yoast/Rank Math.
  • Любой фреймворк: убедитесь, что /sitemap.xml доступен и не закрыт basic auth.

Безопасная нагрузка

  • Не ставьте WAIT=0 на продакшене — параллельный шквал запросов забьёт PHP-FPM/Apache.
  • Для каталога на 100k+ URL при WAIT=1 прогрев займёт сутки и больше — это нормально.
  • Повторный запуск не качает sitemap заново, если уже есть data/urls.txt.
  • Остановка: pkill -f 'warm-cache.sh' или pkill -f 'wget.*urls.txt'.

Проверка результата

~/snippet
wc -l ~/cache-warm/data/urls.txt
tail -20 ~/cache-warm/warm.log
curl -sI -H "User-Agent: YourBot" https://example.com/ | grep -i cache

В Битрикс: админка → Производительность → Композитный сайт — должны появляться записи о сгенерированных страницах.

Зависимости

На сервере нужны: bash, curl, wget, grep, sed, awk.

CentOS/RHEL: yum install -y curl wget · Debian/Ubuntu: apt install -y curl wget

Рубрика:

Оставить комментарий

Ваш адрес эл. почты не будет опубликован. Обязательные поля помечены *