183 lines
9.9 KiB
Bash
Executable File
183 lines
9.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
# export_adsb_bundle.sh — Empaquette le stack ADS-B fonctionnel de Linux-25
|
|
# Version 2.0 — JCA 2026
|
|
#
|
|
# À LANCER SUR LINUX-25 (la machine source, celle qui fonctionne déjà).
|
|
# Produit une archive .tar.gz portable, prête à copier sur la machine neuve
|
|
# et à installer avec install_adsb_stack.sh.
|
|
#
|
|
# v2.0 (05/07/2026) : inclut les correctifs découverts lors des incidents
|
|
# du 03-05/07/2026 :
|
|
# - adsb2pg.py : clean_altitude() (bug "ground") + rollback() sur exception
|
|
# - watchdog_readsb.sh v2 : seuil adaptatif jour/nuit (évite le flapping
|
|
# nocturne sur les creux de trafic réels)
|
|
# - schema_adsb_base.sql : schéma générique SANS les partitions datées
|
|
# spécifiques à Linux-25 (w25-w28, 2026/2027) — la nouvelle machine
|
|
# amorce ses propres partitions à la date réelle d'installation
|
|
# - check_adsb.sh v3.4 : watchdog crontab, continuité partitions, RestartCount
|
|
# - cron d'automatisation des partitions (dimanche 20h, +14 jours)
|
|
#
|
|
# Usage : ./export_adsb_bundle.sh [chemin_sortie.tar.gz]
|
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
set -euo pipefail
|
|
|
|
ADSB_DIR="/data/adsb"
|
|
OUT_FILE="${1:-/tmp/adsb_bundle_$(date +%Y%m%d_%H%M%S).tar.gz}"
|
|
WORK_DIR=$(mktemp -d)
|
|
BUNDLE_DIR="$WORK_DIR/adsb_bundle"
|
|
|
|
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
|
|
ok() { echo -e " ${GREEN}✓${NC} $1"; }
|
|
fail() { echo -e " ${RED}✗${NC} $1"; }
|
|
warn() { echo -e " ${YELLOW}⚠${NC} $1"; }
|
|
info() { echo -e " ${CYAN}→${NC} $1"; }
|
|
step() { echo -e "\n${BOLD}▸ $1${NC}"; }
|
|
|
|
trap 'rm -rf "$WORK_DIR"' EXIT
|
|
|
|
echo -e "${BOLD}╔══════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${BOLD}║ Export bundle ADS-B — source : $(hostname) ║${NC}"
|
|
echo -e "${BOLD}╚══════════════════════════════════════════════════════╝${NC}"
|
|
|
|
mkdir -p "$BUNDLE_DIR"/{adsb2pg,webapp,scripts,sql,docs}
|
|
|
|
# ── 1. docker-compose.yml (nettoyé des secrets) ───────────────────────────────
|
|
step "1. docker-compose.yml"
|
|
if [ -f "$ADSB_DIR/docker-compose.yml" ]; then
|
|
# Remplace le mot de passe en dur par un placeholder — install_adsb_stack.sh
|
|
# en génère un nouveau et l'injecte à l'installation.
|
|
sed -E 's/(PG_PASSWORD=)[^[:space:]]+/\1__PG_PASSWORD_PLACEHOLDER__/' \
|
|
"$ADSB_DIR/docker-compose.yml" > "$BUNDLE_DIR/docker-compose.yml"
|
|
ok "docker-compose.yml exporté (mot de passe neutralisé)"
|
|
else
|
|
fail "docker-compose.yml introuvable dans $ADSB_DIR"
|
|
fi
|
|
|
|
# ── 2. adsb2pg (code source complet) ──────────────────────────────────────────
|
|
step "2. adsb2pg"
|
|
if [ -d "$ADSB_DIR/adsb2pg" ]; then
|
|
# --exclude .git : tar1090-db est un dépôt Git cloné en sous-répertoire —
|
|
# son historique n'a aucune utilité dans l'image Docker et alourdit
|
|
# inutilement le bundle (souvent plusieurs dizaines de Mo).
|
|
if command -v rsync &>/dev/null; then
|
|
rsync -a --exclude='.git' "$ADSB_DIR/adsb2pg/" "$BUNDLE_DIR/adsb2pg/"
|
|
else
|
|
cp -r "$ADSB_DIR/adsb2pg/." "$BUNDLE_DIR/adsb2pg/"
|
|
find "$BUNDLE_DIR/adsb2pg" -type d -name ".git" -exec rm -rf {} + 2>/dev/null
|
|
fi
|
|
GIT_LEFT=$(find "$BUNDLE_DIR/adsb2pg" -type d -name ".git" | wc -l)
|
|
if [ "$GIT_LEFT" -eq 0 ]; then
|
|
ok "Code adsb2pg copié ($(find "$BUNDLE_DIR/adsb2pg" -name '*.py' | wc -l) fichier(s) .py), .git exclu"
|
|
else
|
|
warn ".git non exclu proprement — vérifier manuellement la taille du bundle"
|
|
fi
|
|
if grep -q "clean_altitude" "$BUNDLE_DIR/adsb2pg/adsb2pg.py" 2>/dev/null; then
|
|
ok "Correctif clean_altitude() présent"
|
|
else
|
|
warn "Correctif clean_altitude() ABSENT — bundle basé sur une version non corrigée !"
|
|
fi
|
|
if grep -q "conn.rollback()" "$BUNDLE_DIR/adsb2pg/adsb2pg.py" 2>/dev/null; then
|
|
ok "Correctif rollback() présent"
|
|
else
|
|
warn "Correctif rollback() ABSENT — bundle basé sur une version non corrigée !"
|
|
fi
|
|
else
|
|
fail "Répertoire adsb2pg introuvable dans $ADSB_DIR"
|
|
fi
|
|
|
|
# ── 3. webapp (code source complet) ───────────────────────────────────────────
|
|
step "3. webapp"
|
|
if [ -d "$ADSB_DIR/webapp" ]; then
|
|
cp -r "$ADSB_DIR/webapp/." "$BUNDLE_DIR/webapp/"
|
|
ok "Code webapp copié"
|
|
else
|
|
fail "Répertoire webapp introuvable dans $ADSB_DIR"
|
|
fi
|
|
|
|
# ── 4. Schéma SQL générique (SANS les partitions datées) ──────────────────────
|
|
step "4. Schéma PostgreSQL"
|
|
if [ -f "$ADSB_DIR/schema_adsb_base.sql" ]; then
|
|
cp "$ADSB_DIR/schema_adsb_base.sql" "$BUNDLE_DIR/sql/schema_adsb_base.sql"
|
|
ok "schema_adsb_base.sql copié depuis $ADSB_DIR"
|
|
else
|
|
warn "schema_adsb_base.sql absent de $ADSB_DIR — utilisation de la copie du bundle courant"
|
|
info "Pense à le régénérer si le schéma a changé depuis :"
|
|
info " docker exec wordpress-postgres pg_dump -U pgz_admin -d wpz_postgres --schema-only -n adsb > schema_full.sql"
|
|
info " puis en retirer les partitions datées (w25-w28, aircraft_history_2026/2027)"
|
|
fi
|
|
|
|
# ── 5. Scripts opérationnels (watchdog v2, check_adsb v3.4) ───────────────────
|
|
step "5. Scripts opérationnels"
|
|
for f in scripts/watchdog_readsb.sh check_adsb.sh; do
|
|
SRC="$ADSB_DIR/$f"
|
|
DEST="$BUNDLE_DIR/scripts/$(basename "$f")"
|
|
if [ -f "$SRC" ]; then
|
|
cp "$SRC" "$DEST"
|
|
chmod +x "$DEST"
|
|
ok "$(basename "$f") copié"
|
|
else
|
|
warn "$SRC introuvable — à ajouter manuellement au bundle avant install"
|
|
fi
|
|
done
|
|
|
|
# Vérifier que le watchdog copié est bien la v2 (seuil adaptatif)
|
|
if grep -q "THRESHOLD" "$BUNDLE_DIR/scripts/watchdog_readsb.sh" 2>/dev/null; then
|
|
ok "watchdog_readsb.sh : v2 (seuil adaptatif jour/nuit) confirmée"
|
|
else
|
|
warn "watchdog_readsb.sh : semble être la v1 (pas de seuil adaptatif) — flapping nocturne possible sur la nouvelle machine"
|
|
fi
|
|
|
|
# ── 6. udev rule (RTL-SDR) ────────────────────────────────────────────────────
|
|
step "6. Règle udev RTL-SDR"
|
|
if [ -f /etc/udev/rules.d/99-adsb-docker.rules ]; then
|
|
cp /etc/udev/rules.d/99-adsb-docker.rules "$BUNDLE_DIR/scripts/99-adsb-docker.rules"
|
|
ok "Règle udev copiée"
|
|
else
|
|
warn "Règle udev absente sur cette machine — la nouvelle machine n'aura pas de relance auto USB"
|
|
fi
|
|
|
|
# ── 7. Documentation / notes de version ───────────────────────────────────────
|
|
step "7. Documentation"
|
|
cat > "$BUNDLE_DIR/docs/CHANGELOG_BUNDLE.md" << 'EOF'
|
|
# Bundle ADS-B — historique des correctifs inclus
|
|
|
|
## v2.0 (05/07/2026)
|
|
- **adsb2pg.py** : fix `clean_altitude()` — readsb/tar1090 renvoient la chaîne
|
|
littérale `"ground"` pour l'altitude d'un avion au sol, ce qui plantait
|
|
l'INSERT PostgreSQL (colonne integer). Sans `conn.rollback()` derrière,
|
|
cette unique erreur bloquait tout le collecteur pendant 13h (incident du
|
|
03/07/2026 sur Linux-25).
|
|
- **watchdog_readsb.sh v2** : seuil adaptatif jour (1 cycle/5min) / nuit
|
|
(3 cycles/15min) — la v1 redémarrait le dongle sur de simples creux de
|
|
trafic nocturne, confondus avec un vrai gel matériel.
|
|
- **schema_adsb_base.sql** : schéma généré à partir d'un pg_dump --schema-only
|
|
de Linux-25, DÉLIBÉRÉMENT expurgé des partitions datées (semaines/années
|
|
spécifiques à Linux-25). L'installeur amorce les partitions à la date
|
|
réelle d'installation via `create_week_partition()`/`create_year_partition()`.
|
|
- **check_adsb.sh v3.4** : ajout des vérifications watchdog (crontab, fraîcheur,
|
|
flapping), continuité des partitions, RestartCount Docker, sync NTP.
|
|
- Automatisation cron de création des partitions (dimanche 20h, +14 jours).
|
|
|
|
## Notes de déploiement
|
|
- Le récepteur RTL-SDR de la nouvelle machine aura un numéro de série USB
|
|
différent — install_adsb_stack.sh le détecte automatiquement et met à jour
|
|
RECEIVER_SERIAL dans docker-compose.yml + une ligne dans adsb.receivers.
|
|
- Le mot de passe PostgreSQL est régénéré à l'installation, jamais réutilisé
|
|
tel quel entre machines.
|
|
EOF
|
|
ok "CHANGELOG_BUNDLE.md généré"
|
|
|
|
# ── 8. Archivage ───────────────────────────────────────────────────────────────
|
|
step "8. Création de l'archive"
|
|
tar czf "$OUT_FILE" -C "$WORK_DIR" adsb_bundle
|
|
SIZE=$(du -sh "$OUT_FILE" | cut -f1)
|
|
ok "Archive créée : $OUT_FILE ($SIZE)"
|
|
|
|
echo -e "\n${BOLD}╔══════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${BOLD}║ Bundle prêt : $OUT_FILE"
|
|
echo -e "${BOLD}║ Copie sur la nouvelle machine puis lance : ║${NC}"
|
|
echo -e "${BOLD}║ tar xzf $(basename "$OUT_FILE") ║${NC}"
|
|
echo -e "${BOLD}║ cd adsb_bundle && sudo ./install_adsb_stack.sh ║${NC}"
|
|
echo -e "${BOLD}╚══════════════════════════════════════════════════════╝${NC}"
|