348 lines
15 KiB
Bash
Executable File
348 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# =============================================
|
|
# Script de vérification complète de la stack ADS-B
|
|
# Version : 7.0 (Avec port/IP PostgreSQL et corrections jq)
|
|
# 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')
|
|
# Correction : utiliser `select` pour éviter l'erreur jq
|
|
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 et le port d'écoute
|
|
get_listening_info() {
|
|
local port=$1
|
|
# Essayer avec ss d'abord
|
|
if command -v ss &> /dev/null; then
|
|
ss -tulnp | grep ":$port " | awk '{print $5}' | head -1
|
|
else
|
|
# Fallback sur netstat
|
|
netstat -tulnp 2>/dev/null | grep ":$port " | awk '{print $4}' | head -1
|
|
fi
|
|
}
|
|
|
|
# Liste des ports à vérifier : format "port:service:ip_attendue"
|
|
PORTS=(
|
|
"8080:webapp PHP:127.0.0.1"
|
|
"8090:tar1090 nginx:0.0.0.0"
|
|
"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 et le port réel
|
|
LISTENING_INFO=$(get_listening_info "$PORT" || echo "inconnu")
|
|
ACTUAL_IP=$(echo "$LISTENING_INFO" | cut -d: -f1)
|
|
ACTUAL_PORT=$(echo "$LISTENING_INFO" | cut -d: -f2)
|
|
|
|
if timeout 2 nc -z "$EXPECTED_IP" "$PORT" 2>/dev/null; then
|
|
print_status "$GREEN" " ✓ Port $PORT ($SERVICE) — IP: ${ACTUAL_IP:-inconnu}:${ACTUAL_PORT:-$PORT} (attendu: $EXPECTED_IP:$PORT)"
|
|
else
|
|
print_status "$RED" " ✗ Port $PORT ($SERVICE) — IP: ${ACTUAL_IP:-inconnu}:${ACTUAL_PORT:-$PORT} (attendu: $EXPECTED_IP:$PORT)"
|
|
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"
|
|
|
|
# Obtenir le port et l'IP d'écoute de PostgreSQL
|
|
PG_LISTEN_INFO=$(docker exec wordpress-postgres ss -tulnp 2>/dev/null | grep "5432" | awk '{print $5}' | head -1 || echo "inconnu")
|
|
PG_ACTUAL_IP=$(echo "$PG_LISTEN_INFO" | cut -d: -f1)
|
|
PG_ACTUAL_PORT=$(echo "$PG_LISTEN_INFO" | cut -d: -f2)
|
|
print_status "$GREEN" " → Écoute sur : ${PG_ACTUAL_IP:-127.0.0.1}:${PG_ACTUAL_PORT:-5432}"
|
|
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:8080)"
|
|
else
|
|
print_status "$RED" " ✗ api.php?$endpoint : KO (IP: 127.0.0.1:8080)"
|
|
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 "<li>" | wc -l)
|
|
print_status "$GREEN" " ✓ $ONGETS onglet(s) dans index.php (IP: 127.0.0.1:8080)"
|
|
|
|
# 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:8080)"
|
|
|
|
# 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:8080)"
|
|
else
|
|
print_status "$RED" " ✗ Accès LAN http://$HOST_IP:8080 : KO (IP: $HOST_IP:8080)"
|
|
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_complete_final.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"
|
|
|
|
|