129 lines
3.8 KiB
Bash
129 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
# ============================================================
|
|
# entrypoint.sh - Avvia dashboard web + multiple sync (o singola)
|
|
# ============================================================
|
|
# Supporta due modalità:
|
|
# 1. Singola sync: (compatibilità) lancia un solo sync.sh
|
|
# 2. Multiple sync: parse SYNC_CONFIGS JSON e lancia più istanze
|
|
# ============================================================
|
|
|
|
set -euo pipefail
|
|
|
|
mkdir -p /data/state /data/local
|
|
|
|
WEB_PORT="${WEB_PORT:-8080}"
|
|
SYNC_CONFIGS="${SYNC_CONFIGS:-}"
|
|
|
|
echo "[ENTRYPOINT] Avvio dashboard web su porta ${WEB_PORT}..."
|
|
python3 -u /app/web/app.py &
|
|
WEB_PID=$!
|
|
echo "[ENTRYPOINT] Dashboard avviata (PID: ${WEB_PID})"
|
|
|
|
# --- Funzione cleanup ---
|
|
cleanup() {
|
|
echo "[ENTRYPOINT] Arresto in corso..."
|
|
kill "${WEB_PID}" 2>/dev/null || true
|
|
# Termina tutti gli sync in background
|
|
jobs -p | xargs -r kill 2>/dev/null || true
|
|
wait 2>/dev/null || true
|
|
echo "[ENTRYPOINT] Arresto completato."
|
|
}
|
|
trap cleanup SIGTERM SIGINT
|
|
|
|
# --- Determina se usare single sync o multi-sync ---
|
|
if [ -z "${SYNC_CONFIGS}" ]; then
|
|
# Modalità SINGOLA: lancia un sync.sh come prima
|
|
echo "[ENTRYPOINT] Avvio sincronizzazione (singola)..."
|
|
/usr/local/bin/sync.sh &
|
|
SYNC_PID=$!
|
|
wait -n "${WEB_PID}" "${SYNC_PID}" 2>/dev/null || true
|
|
else
|
|
# Modalità MULTI: parse JSON e lancia multiple istanze
|
|
echo "[ENTRYPOINT] Rilevate multiple sync, parsing configurazione..."
|
|
|
|
# Parse JSON e lancia sync per ogni configurazione
|
|
python3 << 'PYTHON_EOF'
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import time
|
|
|
|
sync_configs_json = os.environ.get('SYNC_CONFIGS', '[]')
|
|
try:
|
|
configs = json.loads(sync_configs_json)
|
|
except json.JSONDecodeError:
|
|
print("[ERROR] SYNC_CONFIGS non è JSON valido")
|
|
exit(1)
|
|
|
|
if not configs or len(configs) == 0:
|
|
print("[ERROR] SYNC_CONFIGS è vuoto")
|
|
exit(1)
|
|
|
|
print(f"[ENTRYPOINT] Avvio {len(configs)} sync...")
|
|
|
|
processes = []
|
|
for i, cfg in enumerate(configs):
|
|
sync_id = cfg.get('id', f'sync{i+1}')
|
|
bucket = cfg.get('bucket')
|
|
local_path = cfg.get('local_path') or cfg.get('path') or f'/data/local{i+1}'
|
|
interval = str(cfg.get('interval', os.environ.get('SYNC_INTERVAL', '300')))
|
|
prefix = cfg.get('prefix', os.environ.get('S3_PATH_PREFIX', ''))
|
|
schedule = cfg.get('schedule', os.environ.get('SYNC_SCHEDULE', ''))
|
|
|
|
if not bucket:
|
|
print(f"[ERROR] Config sync '{sync_id}' senza campo 'bucket'")
|
|
exit(1)
|
|
|
|
state_dir = f"/data/state/{sync_id}"
|
|
|
|
print(f"[ENTRYPOINT] Avvio sync {i+1}/{len(configs)}: {sync_id} (bucket: {bucket}, local: {local_path})")
|
|
|
|
# Crea directory di stato
|
|
os.makedirs(state_dir, exist_ok=True)
|
|
os.makedirs(local_path, exist_ok=True)
|
|
|
|
# Lancia sync.sh in background con STATE_DIR specifico
|
|
env = os.environ.copy()
|
|
env['STATE_DIR'] = state_dir
|
|
env['S3_BUCKET'] = bucket
|
|
env['LOCAL_PATH'] = local_path
|
|
env['SYNC_INTERVAL'] = interval
|
|
env['S3_PATH_PREFIX'] = prefix
|
|
env['SYNC_SCHEDULE'] = schedule
|
|
|
|
proc = subprocess.Popen(
|
|
['/usr/local/bin/sync.sh'],
|
|
env=env
|
|
)
|
|
processes.append((sync_id, proc))
|
|
|
|
print(f"[ENTRYPOINT] Tutte le sync avviate.")
|
|
|
|
# Attendi che uno dei processi termini
|
|
try:
|
|
while True:
|
|
for sync_id, proc in processes:
|
|
ret = proc.poll()
|
|
if ret is not None:
|
|
print(f"[ENTRYPOINT] Sync {sync_id} è terminata con codice {ret}")
|
|
raise KeyboardInterrupt()
|
|
time.sleep(1)
|
|
except KeyboardInterrupt:
|
|
print("[ENTRYPOINT] Terminazione in corso...")
|
|
for sync_id, proc in processes:
|
|
try:
|
|
proc.terminate()
|
|
except:
|
|
pass
|
|
for sync_id, proc in processes:
|
|
try:
|
|
proc.wait(timeout=5)
|
|
except:
|
|
proc.kill()
|
|
|
|
PYTHON_EOF
|
|
fi
|
|
|
|
cleanup
|
|
|