#!/bin/bash # ============================================= # Script de vérification complète de la stack ADS-B # Version : 6.0 (Avec adresses IP pour chaque port) # Date : 26/06/2026 # Auteur : JC Abiven (avec Mistral AI) # ============================================= # Vérifier que jq est installé if ! command -v jq &> /dev/null; then echo -e "\033[0;31m✗ jq n'est pas installé. Installez-le avec : sudo apt install jq\033[0m" exit 1 fi # Couleurs pour l'affichage GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # Fonction pour afficher un message avec une couleur print_status() { echo -e "${1}${2}${NC}" } # Fonction pour afficher un titre print_title() { echo -e "\n${BLUE}═══ ${1} ═══${NC}" } # Fonction pour afficher une section print_section() { echo -e "\n${CYAN}═══ ${1} ═══${NC}" } # Récupérer l'IP de l'hôte HOST_IP=$(hostname -I | awk '{print $1}') # Afficher l'en-tête echo -e "${MAGENTA}╔══════════════════════════════════════════════════════╗" echo -e "║ Stack ADS-B Linux-25 — Vérification complète ║" echo -e "║ $(date "+%a %d/%m/%Y %H:%M:%S") ║" echo -e "╚══════════════════════════════════════════════════════╝" print_status "$YELLOW" " → IP détectée : $HOST_IP" # ============================================= # 1. Vérification des conteneurs Docker # ============================================= print_section "1. Conteneurs Docker" DOCKER_CONTAINERS=("adsb-readsb" "adsb-tar1090" "adsb-adsb2pg" "adsb-webapp" "wordpress-postgres") for container in "${DOCKER_CONTAINERS[@]}"; do if docker ps | grep -q "$container"; then STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "none") if [ "$STATUS" = "healthy" ]; then print_status "$GREEN" " ✓ $container [healthy]" else print_status "$GREEN" " ✓ $container" fi else print_status "$RED" " ✗ $container — non démarré" fi done # ============================================= # 2. Vérification du dongle RTL-SDR # ============================================= print_section "2. Dongle RTL-SDR" if docker logs adsb-readsb 2>&1 | grep -q "rtlsdr: using device #0: Generic RTL2832U OEM (AIRNAV, ADSB_1090, SN 00000010)"; then print_status "$GREEN" " ✓ AirNav FlightStick SN:00000010 détecté" GAIN=$(docker logs adsb-readsb 2>&1 | grep -oP "tuner gain set to \K[0-9.]+ dB" | tail -1) print_status "$GREEN" " → Gain actuel : $GAIN" else print_status "$RED" " ✗ Dongle RTL-SDR non détecté" fi # Vérifier le symlink /dev/adsb_dongle if [ -L "/dev/adsb_dongle" ]; then print_status "$GREEN" " ✓ Symlink /dev/adsb_dongle présent" else print_status "$YELLOW" " ⚠ Symlink /dev/adsb_dongle introuvable" fi # ============================================= # 3. Vérification des données ADS-B # ============================================= print_section "3. Données ADS-B" # Vérifier tar1090 if curl -s --max-time 5 http://127.0.0.1:8090 >/dev/null; then TAR1090_STATS=$(curl -s --max-time 5 http://127.0.0.1:8090/data/stats.json 2>/dev/null) if [ -n "$TAR1090_STATS" ]; then MESSAGES=$(echo "$TAR1090_STATS" | jq -r '.totalMessages // "N/A"') print_status "$GREEN" " ✓ tar1090 actif — $MESSAGES messages décodés" else print_status "$YELLOW" " ⚠ Impossible de récupérer les stats de tar1090" fi AIRCRAFT_DATA=$(curl -s --max-time 5 http://127.0.0.1:8090/data/aircraft.json 2>/dev/null) if [ -n "$AIRCRAFT_DATA" ]; then AIRCRAFT_COUNT=$(echo "$AIRCRAFT_DATA" | jq '. | length // 0') AIRCRAFT_WITH_POS=$(echo "$AIRCRAFT_DATA" | jq '[.[] | select(.lat != null and .lon != null)] | length // 0') print_status "$GREEN" " ✓ $AIRCRAFT_COUNT avion(s) en vue dont $AIRCRAFT_WITH_POS avec position GPS" else print_status "$YELLOW" " ⚠ Impossible de récupérer les données des avions" fi else print_status "$RED" " ✗ tar1090 non accessible" fi # Vérifier le volume readsb-run if docker exec adsb-readsb ls /run/readsb/aircraft.pb >/dev/null 2>&1; then print_status "$GREEN" " ✓ Volume readsb-run : aircraft.pb présent" else print_status "$YELLOW" " ⚠ Volume readsb-run : aircraft.pb introuvable" fi # ============================================= # 4. Vérification des ports réseau (avec adresses IP) # ============================================= print_section "4. Ports réseau" # Fonction pour obtenir l'adresse IP associée à un port get_ip_for_port() { local port=$1 ss -tulnp | grep ":$port " | awk '{print $5}' | cut -d: -f1 | head -1 } PORTS=("8080:webapp PHP:127.0.0.1" "8090:tar1090 nginx:127.0.0.1" "30005:Beast TCP readsb:0.0.0.0" "5432:PostgreSQL:127.0.0.1" "30002:RAW TCP:127.0.0.1" "30003:SBS TCP:127.0.0.1") for port_info in "${PORTS[@]}"; do PORT=${port_info%%:*} SERVICE=${port_info#*:} SERVICE=${SERVICE%:*} EXPECTED_IP=${port_info##*:} # Obtenir l'IP réelle ACTUAL_IP=$(get_ip_for_port "$PORT" || echo "inconnu") if timeout 2 nc -z "$EXPECTED_IP" "$PORT" 2>/dev/null; then print_status "$GREEN" " ✓ Port $PORT ($SERVICE) — IP: $ACTUAL_IP (attendu: $EXPECTED_IP)" else print_status "$RED" " ✗ Port $PORT ($SERVICE) — IP: $ACTUAL_IP (attendu: $EXPECTED_IP)" fi done # Vérifier la connectivité Beast TCP via la gateway if timeout 2 nc -z 172.20.0.1 30005 2>/dev/null; then print_status "$GREEN" " ✓ readsb attaché à adsb-net : 172.20.0.2 (gateway: 172.20.0.1)" else print_status "$RED" " ✗ Problème de connectivité avec adsb-net (172.20.0.1:30005)" fi # ============================================= # 5. Vérification de PostgreSQL et du schéma adsb # ============================================= print_section "5. PostgreSQL — schéma adsb" # Vérifier l'accès à PostgreSQL if docker exec wordpress-postgres pg_isready -U pgz_admin -d wpz_postgres 2>/dev/null | grep -q "accepting connections"; then print_status "$GREEN" " ✓ PostgreSQL accessible" PG_VERSION=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT version();" 2>/dev/null | head -1 | tr -d ' ') print_status "$GREEN" " → $PG_VERSION" else print_status "$RED" " ✗ PostgreSQL non accessible" fi # Vérifier les partitions PARTITIONS_POSITIONS=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT COUNT(*) FROM pg_tables WHERE schemaname = 'adsb' AND tablename LIKE 'positions_%';" 2>/dev/null | tr -d ' ') PARTITIONS_HISTORY=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT COUNT(*) FROM pg_tables WHERE schemaname = 'adsb' AND tablename LIKE 'aircraft_history_%';" 2>/dev/null | tr -d ' ') print_status "$GREEN" " ✓ $PARTITIONS_POSITIONS sous-partitions adsb.positions" print_status "$GREEN" " ✓ $PARTITIONS_HISTORY sous-partitions adsb.aircraft_history" # Vérifier les insertions récentes POSITIONS_5MIN=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT COUNT(*) FROM adsb.positions WHERE ts >= NOW() - INTERVAL '5 minutes';" 2>/dev/null | tr -d ' ') print_status "$GREEN" " ✓ $POSITIONS_5MIN positions insérées dans les 5 dernières minutes" # Vérifier le remplissage de aircraft_desc DESC_FILL=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT ROUND(COUNT(aircraft_desc)*100.0/COUNT(*),1) FROM adsb.positions WHERE ts >= NOW() - INTERVAL '30 minutes' AND lat IS NOT NULL;" 2>/dev/null | tr -d ' ') print_status "$GREEN" " ✓ aircraft_desc rempli à ${DESC_FILL:-0}% (30 dernières min)" # Taille du schéma adsb SCHEMA_SIZE=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT pg_size_pretty(pg_total_relation_size('adsb'));" 2>/dev/null | tr -d ' ') print_status "$GREEN" " → Taille totale schéma adsb : ${SCHEMA_SIZE:-inconnu}" # ============================================= # 6. Vérification de adsb2pg (collecteur) # ============================================= print_section "6. adsb2pg — collecteur" if docker ps | grep -q "adsb-adsb2pg"; then ADSB2PG_LOGS=$(docker logs adsb-adsb2pg 2>&1 | tail -1) if echo "$ADSB2PG_LOGS" | grep -q "positions insérées"; then print_status "$GREEN" " ✓ adsb2pg actif : $ADSB2PG_LOGS" else print_status "$YELLOW" " ⚠ adsb2pg actif mais aucun log récent" fi # Vérifier la dernière insertion (en secondes) LAST_INSERT_SEC=$(docker exec wordpress-postgres psql -U pgz_admin -d wpz_postgres -t -c "SELECT EXTRACT(EPOCH FROM (NOW() - MAX(inserted_at))) FROM adsb.positions WHERE inserted_at >= NOW() - INTERVAL '10 minutes';" 2>/dev/null | tr -d ' ') if [ -n "$LAST_INSERT_SEC" ]; then LAST_INSERT_SEC_INT=${LAST_INSERT_SEC%.*} # Supprimer la partie décimale if [ "$LAST_INSERT_SEC_INT" -le 10 ] 2>/dev/null; then print_status "$GREEN" " ✓ Dernière insertion il y a ${LAST_INSERT_SEC_INT}s (cycle 5s actif)" else print_status "$RED" " ✗ Dernière insertion trop ancienne (${LAST_INSERT_SEC_INT}s)" fi else print_status "$RED" " ✗ Impossible de vérifier la dernière insertion" fi else print_status "$RED" " ✗ adsb2pg non démarré" fi # ============================================= # 7. Vérification de la webapp # ============================================= print_section "7. Webapp — interface utilisateur" # Vérifier les endpoints API API_ENDPOINTS=("action=live" "action=kpi" "action=trajectories") for endpoint in "${API_ENDPOINTS[@]}"; do if curl -s --max-time 5 "http://127.0.0.1:8080/api.php?$endpoint" >/dev/null; then print_status "$GREEN" " ✓ api.php?$endpoint : OK (IP: 127.0.0.1)" else print_status "$RED" " ✗ api.php?$endpoint : KO (IP: 127.0.0.1)" fi done # Vérifier le nombre d'onglets dans index.php ONGETS=$(curl -s --max-time 5 http://127.0.0.1:8080/index.php | grep -o "
  • " | wc -l) print_status "$GREEN" " ✓ $ONGETS onglet(s) dans index.php (IP: 127.0.0.1)" # Vérifier la taille de app.js APP_JS_SIZE=$(curl -s --max-time 5 http://127.0.0.1:8080/app.js | wc -c) print_status "$GREEN" " → app.js : $APP_JS_SIZE octets (IP: 127.0.0.1)" # Vérifier l'accès LAN if curl -s --max-time 5 "http://$HOST_IP:8080" >/dev/null; then print_status "$GREEN" " ✓ Accès LAN http://$HOST_IP:8080 : HTTP 200 (IP: $HOST_IP)" else print_status "$RED" " ✗ Accès LAN http://$HOST_IP:8080 : KO (IP: $HOST_IP)" fi # ============================================= # 8. Vérification de l'autogain # ============================================= print_section "8. Autogain" GAIN_STATUS=$(docker logs adsb-readsb 2>&1 | grep -oP "Gain: \K[0-9.]+ dB" | tail -1) if [ -z "$GAIN_STATUS" ]; then GAIN_STATUS="inconnu" fi print_status "$GREEN" " ✓ Gain courant : $GAIN_STATUS" # Vérifier les cycles avec messages insuffisants INSUFFICIENT_CYCLES=$(docker logs adsb-readsb 2>&1 | grep -c "messages insuffisants" || echo "0") if [ "$INSUFFICIENT_CYCLES" -gt 0 ] 2>/dev/null; then print_status "$YELLOW" " ⚠ $INSUFFICIENT_CYCLES cycle(s) avec messages insuffisants (antenne/portée ?)" else print_status "$GREEN" " ✓ Aucun cycle avec messages insuffisants" fi # ============================================= # 9. Vérification des statistiques readsb # ============================================= print_section "9. Statistiques readsb" # Essayer d'abord via l'IP du conteneur dans adsb-net STATS=$(curl -s --max-time 5 http://172.20.0.2:30003/readsb/stats.json 2>/dev/null) if [ -n "$STATS" ]; then TOTAL_MSG=$(echo "$STATS" | jq -r '.totalMessages // "N/A"') MSG_PER_SEC=$(echo "$STATS" | jq -r '.messagesPerSecond // "N/A"') print_status "$GREEN" " ✓ Statistiques readsb accessibles (IP: 172.20.0.2:30003) :" print_status "$GREEN" " - Messages totaux : $TOTAL_MSG" print_status "$GREEN" " - Messages/seconde : $MSG_PER_SEC" else # Essayer via docker exec STATS=$(docker exec adsb-readsb curl -s http://localhost:30003/readsb/stats.json 2>/dev/null) if [ -n "$STATS" ]; then TOTAL_MSG=$(echo "$STATS" | jq -r '.totalMessages // "N/A"') MSG_PER_SEC=$(echo "$STATS" | jq -r '.messagesPerSecond // "N/A"') print_status "$GREEN" " ✓ Statistiques readsb accessibles (via docker exec, IP: localhost:30003) :" print_status "$GREEN" " - Messages totaux : $TOTAL_MSG" print_status "$GREEN" " - Messages/seconde : $MSG_PER_SEC" else print_status "$RED" " ✗ Impossible de récupérer les statistiques de readsb (IP: 172.20.0.2 ou localhost:30003)" fi fi # ============================================= # Résumé final # ============================================= print_title "RÉSUMÉ" # Compter les erreurs et avertissements dans le script actuel ERRORS=0 WARNINGS=0 SCRIPT_OUTPUT=$(./check_adsb_with_ips.sh 2>&1) while IFS= read -r line; do if [[ "$line" == *"$RED✗"* ]]; then ((ERRORS++)) elif [[ "$line" == *"$YELLOW⚠"* ]]; then ((WARNINGS++)) fi done <<< "$SCRIPT_OUTPUT" if [ "$ERRORS" -eq 0 ] && [ "$WARNINGS" -eq 0 ]; then print_status "$GREEN" " ✓ Stack opérationnel — Aucun problème détecté" elif [ "$ERRORS" -eq 0 ]; then print_status "$YELLOW" " ⚠ Stack opérationnel — $WARNINGS avertissement(s)" else print_status "$RED" " ✗ Stack en erreur — $ERRORS erreur(s), $WARNINGS avertissement(s)" fi print_status "$BLUE" " Dashboard : http://$HOST_IP:8080" print_status "$BLUE" " tar1090 : http://$HOST_IP:8090"