#!/usr/bin/env bash # audit_containers.sh — сравнивает код в Docker-контейнерах с локальным репо # Запускать перед любым ручным запуском воркеров FR24! set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO="$(dirname "$SCRIPT_DIR")" SSH="$HOME/.openclaw/skills/installer/scripts/ssh_exec.sh" declare -A CONTAINERS CONTAINERS["fr24-tracks-fr24"]="ingest/tracks_fr24" CONTAINERS["fr24-schedule"]="ingest/schedule" CONTAINERS["fr24-mart"]="ingest/mart" CONTAINERS["fr24-tracks-fa"]="ingest/tracks_fa" ERRORS=0 WARNINGS=0 for container in "${!CONTAINERS[@]}"; do local_dir="$REPO/${CONTAINERS[$container]}" echo "=== $container ===" if [[ ! -d "$local_dir" ]]; then echo " ⚠️ Локальная папка не найдена: $local_dir" WARNINGS=$((WARNINGS + 1)) echo "" continue fi remote_md5=$("$SSH" --host fr24 --cmd "docker exec $container sh -c 'md5sum /app/*.py 2>/dev/null'" 2>/dev/null || echo "") if [[ -z "$remote_md5" ]]; then echo " ⚠️ Контейнер недоступен или нет .py файлов" WARNINGS=$((WARNINGS + 1)) echo "" continue fi while IFS= read -r line; do [[ -z "$line" ]] && continue remote_hash=$(echo "$line" | awk '{print $1}') remote_file=$(basename "$(echo "$line" | awk '{print $2}')") local_file="$local_dir/$remote_file" if [[ ! -f "$local_file" ]]; then echo " ⚠️ $remote_file — нет локального файла (только в контейнере)" WARNINGS=$((WARNINGS + 1)) continue fi local_hash=$(md5sum "$local_file" | awk '{print $1}') if [[ "$remote_hash" == "$local_hash" ]]; then echo " ✅ $remote_file" else echo " ❌ MISMATCH: $remote_file" echo " container: $remote_hash" echo " local: $local_hash" ERRORS=$((ERRORS + 1)) fi done <<< "$remote_md5" echo "" done echo "========================================" if [[ $ERRORS -eq 0 && $WARNINGS -eq 0 ]]; then echo "✅ Всё совпадает — можно запускать воркеры" elif [[ $ERRORS -eq 0 ]]; then echo "⚠️ Предупреждений: $WARNINGS (ошибок нет)" else echo "❌ Расхождений: $ERRORS — задеплоить актуальные версии ПЕРЕД запуском воркеров!" exit 1 fi