mirror of
https://github.com/ManfredAabye/opensimMULTITOOLS-II.git
synced 2026-07-29 18:29:45 +00:00
010420262055 first
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# **opensimMULTITOOL II V25.5**
|
||||
# **opensimMULTITOOL II V26.4**
|
||||
|
||||
Ein Bash-Skript zum Verwalten von OpenSim-Grids (Starten, Stoppen, Bereinigen, Installation).
|
||||
|
||||
@@ -30,6 +30,100 @@ Ein Bash-Skript zum Verwalten von OpenSim-Grids (Starten, Stoppen, Bereinigen, I
|
||||
|
||||
---
|
||||
|
||||
## **Neu: Modulare Struktur (osmtool_backup_*)**
|
||||
|
||||
Fuer die Aufteilung in einzelne Aufgaben gibt es jetzt eine modulare Basis:
|
||||
|
||||
- `osmtool_main.sh` (zentraler Starter, CLI + UI)
|
||||
- `modular/osmtool_install.sh` (Installation)
|
||||
- `modular/osmtool_startstop.sh` (Start/Stop/Restart)
|
||||
- `modular/osmtool_cleanup.sh` (Bereinigungen + Reboot)
|
||||
- `modular/osmtool_data.sh` (DB/OAR Backups)
|
||||
- `modular/osmtool_core.sh` (gemeinsame Funktionen)
|
||||
|
||||
### Empfehlung UI: whiptail oder dialog?
|
||||
|
||||
- Empfehlung: **whiptail als Default**, weil es auf Ubuntu meist schon vorhanden ist und weniger Abhaengigkeiten hat.
|
||||
- Fallback: **dialog**, falls whiptail nicht installiert ist.
|
||||
- Beide Wege sind im Starter beruecksichtigt: `whiptail -> dialog -> CLI`.
|
||||
|
||||
### Beispiele
|
||||
|
||||
```bash
|
||||
# CLI: zentrale Server-Vorbereitung als Pflichtschritt
|
||||
bash osmtool_main.sh --module install --action bootstrap-server --workdir /opt --profile grid-sim
|
||||
|
||||
# CLI: Ubuntu vorbereiten
|
||||
bash osmtool_main.sh --module install --action prepare-ubuntu
|
||||
|
||||
# CLI: OpenSim klonen, Zusatzmodule einbinden und bauen
|
||||
bash osmtool_main.sh --module install --action install-opensim --workdir /opt --profile grid-sim
|
||||
|
||||
# CLI: OpenSim Runtime-INI aus Beispieldateien erzeugen
|
||||
bash osmtool_main.sh --module install --action configure-opensim --workdir /opt --profile grid-sim
|
||||
|
||||
# CLI: MariaDB Datenbanken/Benutzer/Rechte fuer robust/sim* anlegen
|
||||
bash osmtool_main.sh --module install --action configure-database --workdir /opt --profile grid-sim --db-user opensim --db-pass 'OpenSim#2026'
|
||||
|
||||
# CLI: OpenSim bauen ohne Verteilung in Laufzeitordner
|
||||
bash osmtool_main.sh --module install --action install-opensim --workdir /opt --profile grid-sim --deploy-binaries false
|
||||
|
||||
# CLI: komplettes Grid neustarten
|
||||
bash osmtool_main.sh --module startstop --target grid --action restart --workdir /opt
|
||||
|
||||
# CLI: Janus Gateway neustarten
|
||||
bash osmtool_main.sh --module startstop --target janus --action restart --workdir /opt
|
||||
|
||||
# CLI: Janus zuerst kompilieren
|
||||
bash osmtool_main.sh --module install --action compile-janus --workdir /opt --profile grid-sim
|
||||
|
||||
# CLI: Janus danach konfigurieren
|
||||
bash osmtool_main.sh --module install --action configure-janus --workdir /opt --profile grid-sim --public-host 127.0.0.1
|
||||
|
||||
# CLI: Janus kompiliert + konfiguriert in einem Lauf
|
||||
bash osmtool_main.sh --module install --action install-janus --workdir /opt --profile grid-sim --public-host 127.0.0.1
|
||||
|
||||
# CLI: Robust DB sichern
|
||||
bash osmtool_main.sh --module backup --action db-backup --db-user root --db-pass secret --db-name opensim --workdir /opt
|
||||
|
||||
# CLI: OAR Export in laufende sim1 Session senden
|
||||
bash osmtool_main.sh --module backup --action oar-backup --workdir /opt --region sim1 --session sim1
|
||||
|
||||
# CLI: Full Backup (MariaDB + OAR Command) mit gzip-Kompression
|
||||
bash osmtool_main.sh --module backup --action full-backup --workdir /opt --db-user root --db-pass secret --db-name opensim --region sim1 --session sim1 --compress true
|
||||
|
||||
# CLI: OSMTool Cronjobs installieren
|
||||
bash osmtool_main.sh --module cron --action install --workdir /opt --db-user root --db-name opensim --region sim1 --session sim1
|
||||
|
||||
# CLI: OSMTool Cronjobs anzeigen/entfernen
|
||||
bash osmtool_main.sh --module cron --action list --workdir /opt
|
||||
bash osmtool_main.sh --module cron --action remove --workdir /opt
|
||||
|
||||
# UI Modus
|
||||
bash osmtool_main.sh --mode ui
|
||||
```
|
||||
|
||||
Hinweis Janus:
|
||||
|
||||
- `bootstrap-server` ist Pflicht vor `install-opensim`, `compile-janus`, `configure-janus` und `install-janus`.
|
||||
- `configure-opensim` erzeugt fehlende Runtime-INI aus den Beispielvorlagen.
|
||||
- `configure-database` erzeugt MariaDB Datenbanken fuer `robust` und gefundene `sim*` Verzeichnisse sowie Benutzer/Grants.
|
||||
- Datenbankbasis ist MariaDB; `server-check` prueft `mysqldump` als Pflichttool fuer Backups.
|
||||
- `install-opensim` klont oder aktualisiert `opensim`, `opensim-tsassets`, `opensimcurrencyserver-dotnet` und `os-data-backup`, fuehrt `runprebuild.sh` aus und baut `OpenSim.sln`.
|
||||
- Wenn `robust/bin`, `standalone/bin` oder `sim*/bin` existieren, verteilt `install-opensim` die gebauten Binaries dorthin, sofern `--deploy-binaries` nicht auf `false` gesetzt ist.
|
||||
- Janus muss vor Start/Restart zuerst kompiliert und konfiguriert sein.
|
||||
- `startstop --target janus` prueft Binary und Konfiguration und blockiert sonst mit klarer Fehlermeldung.
|
||||
|
||||
### Sinnvolle weitere Skripte
|
||||
|
||||
- `osmtool_backup_health.sh` (Healthcheck fuer screen sessions, ports, DB)
|
||||
- `osmtool_backup_restore.sh` (SQL Restore + OAR Restore mit Dry-Run)
|
||||
- `osmtool_backup_update.sh` (OpenSim/Janus Update-Workflow mit Rollback)
|
||||
- `osmtool_backup_cron.sh` (Cronjobs validieren und automatisch setzen)
|
||||
- `osmtool_backup_config.sh` (INI/JSON Validierung und Patchen)
|
||||
|
||||
---
|
||||
|
||||
## **📋 Inhaltsverzeichnis**
|
||||
|
||||
1. [OpenSim starten/stoppen](#-opensim-starten-stoppen-und-neustarten)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
APP_TITLE=OSMTool Backup
|
||||
MENU_CHOOSE_MODULE=Modul waehlen
|
||||
MENU_INSTALL=Installation
|
||||
MENU_STARTSTOP=Start/Stop/Neustart
|
||||
MENU_CLEANUP=Bereinigung und Reboot
|
||||
MENU_HEALTH=Healthcheck
|
||||
MENU_BACKUP=Sicherung DB/OAR
|
||||
MENU_RESTORE=Wiederherstellung DB/OAR
|
||||
MENU_UPDATE=Aktualisierung mit Ruecksetzpunkt
|
||||
MENU_CONFIG=Konfigurationspruefung
|
||||
MENU_REPORT=Tagesreport
|
||||
MENU_SMOKE=Schnelltest
|
||||
MENU_CRON=Cronjobs
|
||||
MENU_CHOOSE_ACTION=Aktion waehlen
|
||||
MENU_CHOOSE_TARGET=Ziel waehlen
|
||||
MENU_CHOOSE_PROFILE=Profil waehlen
|
||||
ACTION_START=Starten
|
||||
ACTION_STOP=Stoppen
|
||||
ACTION_RESTART=Neustarten
|
||||
ACTION_CACHE_CLEAN=Cache-Ordner loeschen
|
||||
ACTION_LOG_CLEAN=Logs loeschen
|
||||
ACTION_TMP_CLEAN=Temp-Dateien loeschen
|
||||
ACTION_REBOOT=Server neu starten
|
||||
ACTION_HEALTH_RUN=System-Healthcheck ausfuehren
|
||||
ACTION_DB_BACKUP=Robust Datenbank sichern
|
||||
ACTION_OAR_BACKUP=Region als OAR sichern
|
||||
ACTION_FULL_BACKUP=Datenbank und optional OAR sichern
|
||||
ACTION_RESTORE_LIST=Verfuegbare Backups anzeigen
|
||||
ACTION_RESTORE_DB=Datenbank wiederherstellen
|
||||
ACTION_RESTORE_OAR=Region aus OAR wiederherstellen
|
||||
ACTION_RESTORE_FULL=Datenbank und optional OAR wiederherstellen
|
||||
ACTION_UPDATE_ROLLBACK=Ruecksetzpunkt erstellen
|
||||
ACTION_UPDATE_LIST=Ruecksetzpunkte anzeigen
|
||||
ACTION_UPDATE_OPENSIM=OpenSim aktualisieren
|
||||
ACTION_UPDATE_JANUS=Janus aktualisieren
|
||||
ACTION_UPDATE_FULL=OpenSim und Janus aktualisieren
|
||||
ACTION_CONFIG_FILE=Einzelne Config-Datei pruefen
|
||||
ACTION_CONFIG_RUNTIME=Runtime-Configs pruefen
|
||||
ACTION_REPORT_GENERATE=Tagesreport erzeugen
|
||||
ACTION_SMOKE_RUN=Start/Neustart/Stop Schnelltest ausfuehren
|
||||
ACTION_CRON_INSTALL=Cron-Jobs installieren/aktualisieren
|
||||
ACTION_CRON_LIST=Cron-Jobs anzeigen
|
||||
ACTION_CRON_REMOVE=Cron-Jobs entfernen
|
||||
TARGET_GRID=Komplettes Grid
|
||||
TARGET_ROBUST=Nur Robust
|
||||
TARGET_SIM1=Nur Primaerregion
|
||||
TARGET_STANDALONE=Standalone Instanz
|
||||
TARGET_JANUS=Janus Gateway Server
|
||||
PROFILE_GRID_SIM=Grid Simulatoren
|
||||
PROFILE_ROBUST=Robust Dienst
|
||||
PROFILE_STANDALONE=Standalone Betrieb
|
||||
ERR_UNKNOWN_MODULE=Unbekanntes Modul
|
||||
ERR_UNKNOWN_UI_MODULE=Unbekanntes UI-Modul
|
||||
ERR_MISSING_MODULE=Fehlendes --module im CLI Modus
|
||||
ERR_INVALID_PROFILE=Ungueltiges Profil
|
||||
ERR_ACTION_NOT_ALLOWED=Aktion fuer dieses Profil nicht erlaubt
|
||||
ERR_TARGET_NOT_ALLOWED=Ziel fuer dieses Profil nicht erlaubt
|
||||
ERR_NO_UI_BACKEND=Kein UI Backend gefunden. Installiere whiptail oder dialog oder nutze CLI Parameter.
|
||||
HELP_LANG=Sprache (de|en|fr|es), Standard: de
|
||||
HELP_PROFILE=Profil (grid-sim|robust|standalone), Standard: grid-sim
|
||||
@@ -0,0 +1,60 @@
|
||||
APP_TITLE=OSMTool Backup
|
||||
MENU_CHOOSE_MODULE=Choose module
|
||||
MENU_INSTALL=Installation
|
||||
MENU_STARTSTOP=Start/stop/restart
|
||||
MENU_CLEANUP=Cleanup and reboot
|
||||
MENU_HEALTH=Health check
|
||||
MENU_BACKUP=Backup DB/OAR
|
||||
MENU_RESTORE=Restore DB/OAR
|
||||
MENU_UPDATE=Update with rollback
|
||||
MENU_CONFIG=Config validation
|
||||
MENU_REPORT=Daily report
|
||||
MENU_SMOKE=Smoke test
|
||||
MENU_CRON=Cron jobs
|
||||
MENU_CHOOSE_ACTION=Choose action
|
||||
MENU_CHOOSE_TARGET=Choose target
|
||||
MENU_CHOOSE_PROFILE=Choose profile
|
||||
ACTION_START=Start
|
||||
ACTION_STOP=Stop
|
||||
ACTION_RESTART=Restart
|
||||
ACTION_CACHE_CLEAN=Delete cache folders
|
||||
ACTION_LOG_CLEAN=Delete logs
|
||||
ACTION_TMP_CLEAN=Delete temp files
|
||||
ACTION_REBOOT=Reboot server
|
||||
ACTION_HEALTH_RUN=Run system health check
|
||||
ACTION_DB_BACKUP=Backup robust database
|
||||
ACTION_OAR_BACKUP=Backup region as OAR
|
||||
ACTION_FULL_BACKUP=Backup database and optional OAR
|
||||
ACTION_RESTORE_LIST=List available backups
|
||||
ACTION_RESTORE_DB=Restore database
|
||||
ACTION_RESTORE_OAR=Restore region from OAR
|
||||
ACTION_RESTORE_FULL=Restore database and optional OAR
|
||||
ACTION_UPDATE_ROLLBACK=Create rollback point
|
||||
ACTION_UPDATE_LIST=List rollback points
|
||||
ACTION_UPDATE_OPENSIM=Update OpenSim
|
||||
ACTION_UPDATE_JANUS=Update Janus
|
||||
ACTION_UPDATE_FULL=Update OpenSim and Janus
|
||||
ACTION_CONFIG_FILE=Validate single config file
|
||||
ACTION_CONFIG_RUNTIME=Validate runtime configs
|
||||
ACTION_REPORT_GENERATE=Generate daily report
|
||||
ACTION_SMOKE_RUN=Run start/restart/stop smoke test
|
||||
ACTION_CRON_INSTALL=Install/update cron jobs
|
||||
ACTION_CRON_LIST=List cron jobs
|
||||
ACTION_CRON_REMOVE=Remove cron jobs
|
||||
TARGET_GRID=Whole grid
|
||||
TARGET_ROBUST=Robust only
|
||||
TARGET_SIM1=Primary region only
|
||||
TARGET_STANDALONE=Standalone instance
|
||||
TARGET_JANUS=Janus gateway server
|
||||
PROFILE_GRID_SIM=Grid simulators
|
||||
PROFILE_ROBUST=Robust service
|
||||
PROFILE_STANDALONE=Standalone mode
|
||||
ERR_UNKNOWN_MODULE=Unknown module
|
||||
ERR_UNKNOWN_UI_MODULE=Unknown UI module
|
||||
ERR_MISSING_MODULE=Missing --module in CLI mode
|
||||
ERR_INVALID_PROFILE=Invalid profile
|
||||
ERR_ACTION_NOT_ALLOWED=Action not allowed for this profile
|
||||
ERR_TARGET_NOT_ALLOWED=Target not allowed for this profile
|
||||
ERR_NO_UI_BACKEND=No UI backend found. Install whiptail or dialog, or use CLI parameters.
|
||||
HELP_LANG=Language (de|en|fr|es), default: de
|
||||
HELP_PROFILE=Profile (grid-sim|robust|standalone), default: grid-sim
|
||||
@@ -0,0 +1,60 @@
|
||||
APP_TITLE=OSMTool Backup
|
||||
MENU_CHOOSE_MODULE=Elegir modulo
|
||||
MENU_INSTALL=Instalacion
|
||||
MENU_STARTSTOP=Iniciar/detener/reiniciar
|
||||
MENU_CLEANUP=Limpieza y reinicio
|
||||
MENU_HEALTH=Comprobacion de salud
|
||||
MENU_BACKUP=Copia BD/OAR
|
||||
MENU_RESTORE=Restauracion BD/OAR
|
||||
MENU_UPDATE=Actualizacion con punto de restauracion
|
||||
MENU_CONFIG=Validacion de configuracion
|
||||
MENU_REPORT=Reporte diario
|
||||
MENU_SMOKE=Prueba rapida
|
||||
MENU_CRON=Tareas cron
|
||||
MENU_CHOOSE_ACTION=Elegir accion
|
||||
MENU_CHOOSE_TARGET=Elegir destino
|
||||
MENU_CHOOSE_PROFILE=Elegir perfil
|
||||
ACTION_START=Iniciar
|
||||
ACTION_STOP=Detener
|
||||
ACTION_RESTART=Reiniciar
|
||||
ACTION_CACHE_CLEAN=Eliminar carpetas de cache
|
||||
ACTION_LOG_CLEAN=Eliminar logs
|
||||
ACTION_TMP_CLEAN=Eliminar archivos temporales
|
||||
ACTION_REBOOT=Reiniciar servidor
|
||||
ACTION_HEALTH_RUN=Ejecutar comprobacion de salud
|
||||
ACTION_DB_BACKUP=Copia de base Robust
|
||||
ACTION_OAR_BACKUP=Copia de region en OAR
|
||||
ACTION_FULL_BACKUP=Copia de base y OAR opcional
|
||||
ACTION_RESTORE_LIST=Listar copias disponibles
|
||||
ACTION_RESTORE_DB=Restaurar base de datos
|
||||
ACTION_RESTORE_OAR=Restaurar region desde OAR
|
||||
ACTION_RESTORE_FULL=Restaurar base y OAR opcional
|
||||
ACTION_UPDATE_ROLLBACK=Crear punto de restauracion
|
||||
ACTION_UPDATE_LIST=Listar puntos de rollback
|
||||
ACTION_UPDATE_OPENSIM=Actualizar OpenSim
|
||||
ACTION_UPDATE_JANUS=Actualizar Janus
|
||||
ACTION_UPDATE_FULL=Actualizar OpenSim y Janus
|
||||
ACTION_CONFIG_FILE=Validar un archivo de configuracion
|
||||
ACTION_CONFIG_RUNTIME=Validar configuraciones runtime
|
||||
ACTION_REPORT_GENERATE=Generar reporte diario
|
||||
ACTION_SMOKE_RUN=Ejecutar prueba rapida iniciar/reiniciar/detener
|
||||
ACTION_CRON_INSTALL=Instalar/actualizar tareas cron
|
||||
ACTION_CRON_LIST=Listar tareas cron
|
||||
ACTION_CRON_REMOVE=Eliminar tareas cron
|
||||
TARGET_GRID=Grid completo
|
||||
TARGET_ROBUST=Solo Robust
|
||||
TARGET_SIM1=Solo region primaria
|
||||
TARGET_STANDALONE=Instancia standalone
|
||||
TARGET_JANUS=Servidor pasarela Janus
|
||||
PROFILE_GRID_SIM=Simuladores de grid
|
||||
PROFILE_ROBUST=Servicio Robust
|
||||
PROFILE_STANDALONE=Modo standalone
|
||||
ERR_UNKNOWN_MODULE=Modulo desconocido
|
||||
ERR_UNKNOWN_UI_MODULE=Modulo UI desconocido
|
||||
ERR_MISSING_MODULE=Falta --module en modo CLI
|
||||
ERR_INVALID_PROFILE=Perfil invalido
|
||||
ERR_ACTION_NOT_ALLOWED=Accion no permitida para este perfil
|
||||
ERR_TARGET_NOT_ALLOWED=Destino no permitido para este perfil
|
||||
ERR_NO_UI_BACKEND=No se encontro backend UI. Instala whiptail o dialog, o usa parametros CLI.
|
||||
HELP_LANG=Idioma (de|en|fr|es), por defecto: de
|
||||
HELP_PROFILE=Perfil (grid-sim|robust|standalone), por defecto: grid-sim
|
||||
@@ -0,0 +1,60 @@
|
||||
APP_TITLE=OSMTool Backup
|
||||
MENU_CHOOSE_MODULE=Choisir un module
|
||||
MENU_INSTALL=Installation
|
||||
MENU_STARTSTOP=Demarrer/arreter/redemarrer
|
||||
MENU_CLEANUP=Nettoyage et redemarrage
|
||||
MENU_HEALTH=Verification de sante
|
||||
MENU_BACKUP=Sauvegarde BD/OAR
|
||||
MENU_RESTORE=Restauration BD/OAR
|
||||
MENU_UPDATE=Mise a jour avec retour arriere
|
||||
MENU_CONFIG=Validation de configuration
|
||||
MENU_REPORT=Rapport quotidien
|
||||
MENU_SMOKE=Test de fumee
|
||||
MENU_CRON=Taches cron
|
||||
MENU_CHOOSE_ACTION=Choisir une action
|
||||
MENU_CHOOSE_TARGET=Choisir une cible
|
||||
MENU_CHOOSE_PROFILE=Choisir un profil
|
||||
ACTION_START=Demarrer
|
||||
ACTION_STOP=Arreter
|
||||
ACTION_RESTART=Redemarrer
|
||||
ACTION_CACHE_CLEAN=Supprimer les dossiers de cache
|
||||
ACTION_LOG_CLEAN=Supprimer les journaux
|
||||
ACTION_TMP_CLEAN=Supprimer les fichiers temporaires
|
||||
ACTION_REBOOT=Redemarrer le serveur
|
||||
ACTION_HEALTH_RUN=Executer la verification de sante
|
||||
ACTION_DB_BACKUP=Sauvegarder la base Robust
|
||||
ACTION_OAR_BACKUP=Sauvegarder la region en OAR
|
||||
ACTION_FULL_BACKUP=Sauvegarder la base et OAR optionnel
|
||||
ACTION_RESTORE_LIST=Afficher les sauvegardes disponibles
|
||||
ACTION_RESTORE_DB=Restaurer la base de donnees
|
||||
ACTION_RESTORE_OAR=Restaurer la region depuis OAR
|
||||
ACTION_RESTORE_FULL=Restaurer la base et OAR optionnel
|
||||
ACTION_UPDATE_ROLLBACK=Creer un point de retour arriere
|
||||
ACTION_UPDATE_LIST=Afficher les points de rollback
|
||||
ACTION_UPDATE_OPENSIM=Mettre a jour OpenSim
|
||||
ACTION_UPDATE_JANUS=Mettre a jour Janus
|
||||
ACTION_UPDATE_FULL=Mettre a jour OpenSim et Janus
|
||||
ACTION_CONFIG_FILE=Valider un fichier de configuration
|
||||
ACTION_CONFIG_RUNTIME=Valider les configurations runtime
|
||||
ACTION_REPORT_GENERATE=Generer le rapport quotidien
|
||||
ACTION_SMOKE_RUN=Executer le test de fumee demarrer/redemarrer/arreter
|
||||
ACTION_CRON_INSTALL=Installer/mettre a jour les taches cron
|
||||
ACTION_CRON_LIST=Afficher les taches cron
|
||||
ACTION_CRON_REMOVE=Supprimer les taches cron
|
||||
TARGET_GRID=Grille complete
|
||||
TARGET_ROBUST=Robust uniquement
|
||||
TARGET_SIM1=Region primaire uniquement
|
||||
TARGET_STANDALONE=Instance standalone
|
||||
TARGET_JANUS=Serveur passerelle Janus
|
||||
PROFILE_GRID_SIM=Simulateurs de grille
|
||||
PROFILE_ROBUST=Service Robust
|
||||
PROFILE_STANDALONE=Mode standalone
|
||||
ERR_UNKNOWN_MODULE=Module inconnu
|
||||
ERR_UNKNOWN_UI_MODULE=Module UI inconnu
|
||||
ERR_MISSING_MODULE=Option --module manquante en mode CLI
|
||||
ERR_INVALID_PROFILE=Profil invalide
|
||||
ERR_ACTION_NOT_ALLOWED=Action non autorisee pour ce profil
|
||||
ERR_TARGET_NOT_ALLOWED=Cible non autorisee pour ce profil
|
||||
ERR_NO_UI_BACKEND=Aucun backend UI trouve. Installez whiptail ou dialog, ou utilisez les parametres CLI.
|
||||
HELP_LANG=Langue (de|en|fr|es), defaut: de
|
||||
HELP_PROFILE=Profil (grid-sim|robust|standalone), defaut: grid-sim
|
||||
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_cleanup.sh [--workdir <path>] --action <cache-clean|log-clean|tmp-clean|reboot> [--dry-run <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_cleanup.sh --action log-clean --workdir /opt --dry-run true
|
||||
osmtool_cleanup.sh --action cache-clean --workdir /opt/opensim
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
realpath_safe() {
|
||||
local p="$1"
|
||||
python3 -c 'import os,sys; print(os.path.realpath(sys.argv[1]))' "$p" 2>/dev/null || echo "$p"
|
||||
}
|
||||
|
||||
assert_safe_workdir() {
|
||||
local rp
|
||||
rp="$(realpath_safe "$WORKDIR")"
|
||||
|
||||
[[ -n "$rp" ]] || die "Invalid workdir"
|
||||
[[ "$rp" != "/" ]] || die "Refusing cleanup on root directory"
|
||||
[[ "$rp" != "/opt" ]] || die "Refusing cleanup on /opt root; choose a dedicated OpenSim workdir"
|
||||
[[ -d "$rp" ]] || die "Workdir not found: $rp"
|
||||
|
||||
WORKDIR="$rp"
|
||||
}
|
||||
|
||||
run_delete() {
|
||||
local path="$1"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
log INFO "[DRY-RUN] Would remove: $path"
|
||||
else
|
||||
rm -rf "$path"
|
||||
log INFO "Removed: $path"
|
||||
fi
|
||||
}
|
||||
|
||||
run_delete_file() {
|
||||
local path="$1"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
log INFO "[DRY-RUN] Would delete file: $path"
|
||||
else
|
||||
rm -f "$path"
|
||||
log INFO "Deleted file: $path"
|
||||
fi
|
||||
}
|
||||
|
||||
cache_clean() {
|
||||
log INFO "Cleaning map tiles and cache under $WORKDIR"
|
||||
local d
|
||||
while IFS= read -r d; do
|
||||
[[ -n "$d" ]] || continue
|
||||
run_delete "$d"
|
||||
done < <(find "$WORKDIR" -mindepth 2 -type d \( -name "assetcache" -o -name "MapTiles" -o -name "cache" \))
|
||||
}
|
||||
|
||||
log_clean() {
|
||||
log INFO "Cleaning log files under $WORKDIR"
|
||||
local f
|
||||
while IFS= read -r f; do
|
||||
[[ -n "$f" ]] || continue
|
||||
run_delete_file "$f"
|
||||
done < <(find "$WORKDIR" -type f \( -name "*.log" -o -name "OpenSim.log" -o -name "ProblemRestarts.log" \))
|
||||
}
|
||||
|
||||
tmp_clean() {
|
||||
log INFO "Cleaning temporary files under $WORKDIR"
|
||||
local f
|
||||
while IFS= read -r f; do
|
||||
[[ -n "$f" ]] || continue
|
||||
run_delete_file "$f"
|
||||
done < <(find "$WORKDIR" -type f \( -name "*.tmp" -o -name "*.temp" \))
|
||||
}
|
||||
|
||||
safe_reboot() {
|
||||
if confirm "Reboot" "Reboot server now?"; then
|
||||
log INFO "Reboot requested"
|
||||
sudo reboot
|
||||
else
|
||||
log INFO "Reboot canceled"
|
||||
fi
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
DRY_RUN="false"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--dry-run) DRY_RUN="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed cleanup "$PROFILE" "$ACTION"
|
||||
case "$DRY_RUN" in true|false) ;; *) die "--dry-run must be true or false" ;; esac
|
||||
assert_safe_workdir
|
||||
log INFO "Using profile: $PROFILE"
|
||||
log INFO "Dry-run mode: $DRY_RUN"
|
||||
|
||||
case "$ACTION" in
|
||||
cache-clean) cache_clean ;;
|
||||
log-clean) log_clean ;;
|
||||
tmp-clean) tmp_clean ;;
|
||||
reboot) safe_reboot ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_config.sh [--workdir <path>] --action <validate-file|validate-runtime>
|
||||
[--file <path>] [--strict <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_config.sh --action validate-file --file /opt/sim1/bin/OpenSim.ini
|
||||
osmtool_config.sh --action validate-runtime --profile grid-sim --workdir /opt
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
trim() {
|
||||
local value="$1"
|
||||
value="${value#"${value%%[![:space:]]*}"}"
|
||||
value="${value%"${value##*[![:space:]]}"}"
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
check_runtime_file() {
|
||||
local file="$1"
|
||||
local errors_before="$VALIDATION_ERRORS"
|
||||
|
||||
if [[ ! -f "$file" ]]; then
|
||||
log ERROR "Missing config file: $file"
|
||||
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
|
||||
return 1
|
||||
fi
|
||||
|
||||
validate_file "$file"
|
||||
if [[ "$VALIDATION_ERRORS" -gt "$errors_before" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
validate_ini_file() {
|
||||
local file="$1"
|
||||
local line_number=0
|
||||
local line trimmed seen_section=false
|
||||
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
line_number=$((line_number + 1))
|
||||
trimmed="$(trim "$line")"
|
||||
|
||||
[[ -z "$trimmed" ]] && continue
|
||||
case "$trimmed" in
|
||||
';'*|'#'*) continue ;;
|
||||
'['*']')
|
||||
seen_section=true
|
||||
continue
|
||||
;;
|
||||
*=*)
|
||||
continue
|
||||
;;
|
||||
.include*)
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
log ERROR "Invalid INI syntax in $file:$line_number -> $line"
|
||||
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
|
||||
;;
|
||||
esac
|
||||
done < "$file"
|
||||
|
||||
if [[ "$STRICT" == "true" && "$seen_section" == "false" ]]; then
|
||||
log ERROR "INI file has no section headers: $file"
|
||||
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
validate_json_file() {
|
||||
local file="$1"
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
if ! jq empty "$file" >/dev/null 2>&1; then
|
||||
log ERROR "Invalid JSON syntax: $file"
|
||||
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
if ! python3 -m json.tool "$file" >/dev/null 2>&1; then
|
||||
log ERROR "Invalid JSON syntax: $file"
|
||||
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
die "validate-json requires jq or python3"
|
||||
}
|
||||
|
||||
validate_file() {
|
||||
local file="$1"
|
||||
|
||||
[[ -f "$file" ]] || die "Config file not found: $file"
|
||||
|
||||
case "$file" in
|
||||
*.ini|*.INI)
|
||||
log INFO "Validating INI file: $file"
|
||||
validate_ini_file "$file"
|
||||
;;
|
||||
*.json|*.JSON)
|
||||
log INFO "Validating JSON file: $file"
|
||||
validate_json_file "$file"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported config file type: $file"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
validate_grid_runtime() {
|
||||
local sim_ini
|
||||
local sim_count=0
|
||||
|
||||
check_runtime_file "$WORKDIR/robust/bin/Robust.ini"
|
||||
|
||||
shopt -s nullglob
|
||||
for sim_ini in "$WORKDIR"/sim*/bin/OpenSim.ini; do
|
||||
sim_count=$((sim_count + 1))
|
||||
check_runtime_file "$sim_ini"
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
if [[ "$sim_count" -eq 0 ]]; then
|
||||
log ERROR "No region runtime configs found under $WORKDIR/sim*/bin/OpenSim.ini"
|
||||
VALIDATION_ERRORS=$((VALIDATION_ERRORS + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
validate_robust_runtime() {
|
||||
check_runtime_file "$WORKDIR/robust/bin/Robust.ini"
|
||||
}
|
||||
|
||||
validate_standalone_runtime() {
|
||||
check_runtime_file "$WORKDIR/standalone/bin/OpenSim.ini"
|
||||
}
|
||||
|
||||
validate_runtime() {
|
||||
case "$PROFILE" in
|
||||
grid-sim) validate_grid_runtime ;;
|
||||
robust) validate_robust_runtime ;;
|
||||
standalone) validate_standalone_runtime ;;
|
||||
esac
|
||||
|
||||
if [[ "$VALIDATION_ERRORS" -gt 0 ]]; then
|
||||
die "Configuration validation failed with $VALIDATION_ERRORS issue(s)"
|
||||
fi
|
||||
|
||||
log INFO "Configuration validation passed"
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
FILE=""
|
||||
STRICT="false"
|
||||
VALIDATION_ERRORS=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--file) FILE="$2"; shift 2 ;;
|
||||
--strict) STRICT="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed config "$PROFILE" "$ACTION"
|
||||
|
||||
case "$STRICT" in
|
||||
true|false) ;;
|
||||
*) die "--strict must be true or false" ;;
|
||||
esac
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
validate-file)
|
||||
[[ -n "$FILE" ]] || die "validate-file requires --file"
|
||||
validate_file "$FILE"
|
||||
if [[ "$VALIDATION_ERRORS" -gt 0 ]]; then
|
||||
die "Configuration validation failed with $VALIDATION_ERRORS issue(s)"
|
||||
fi
|
||||
log INFO "Configuration validation passed"
|
||||
;;
|
||||
validate-runtime)
|
||||
validate_runtime
|
||||
;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
export DEFAULT_WORKDIR="/opt"
|
||||
LANG_DIR="$ROOT_DIR/lang"
|
||||
APP_LANG="${OSM_LANG:-de}"
|
||||
|
||||
LOG_FILE="${LOG_FILE:-$ROOT_DIR/osmtool_backup.log}"
|
||||
|
||||
declare -A I18N_CURRENT=()
|
||||
declare -A I18N_EN=()
|
||||
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
printf '[%s] [%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$level" "$*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
die() {
|
||||
log ERROR "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1"
|
||||
}
|
||||
|
||||
normalize_lang() {
|
||||
case "$1" in
|
||||
de|en|fr|es) echo "$1" ;;
|
||||
*) echo "de" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
validate_profile() {
|
||||
case "$1" in
|
||||
grid-sim|robust|standalone) return 0 ;;
|
||||
*) die "$(msg ERR_INVALID_PROFILE): $1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
profile_action_allowed() {
|
||||
local module="$1"
|
||||
local profile="$2"
|
||||
local action="$3"
|
||||
|
||||
case "$module:$profile" in
|
||||
install:grid-sim|install:robust|install:standalone)
|
||||
case "$action" in bootstrap-server|server-check|prepare-ubuntu|install-opensim-deps|install-dotnet8|install-opensim|configure-opensim|configure-database|compile-janus|configure-janus|install-janus) return 0 ;; esac
|
||||
;;
|
||||
startstop:grid-sim|startstop:robust|startstop:standalone)
|
||||
case "$action" in start|stop|restart) return 0 ;; esac
|
||||
;;
|
||||
cleanup:grid-sim|cleanup:robust|cleanup:standalone)
|
||||
case "$action" in cache-clean|log-clean|tmp-clean|reboot) return 0 ;; esac
|
||||
;;
|
||||
health:grid-sim|health:robust|health:standalone)
|
||||
case "$action" in run) return 0 ;; esac
|
||||
;;
|
||||
backup:grid-sim)
|
||||
case "$action" in db-backup|oar-backup|full-backup) return 0 ;; esac
|
||||
;;
|
||||
backup:robust)
|
||||
case "$action" in db-backup|full-backup) return 0 ;; esac
|
||||
;;
|
||||
backup:standalone)
|
||||
case "$action" in oar-backup|full-backup) return 0 ;; esac
|
||||
;;
|
||||
cron:grid-sim|cron:robust|cron:standalone)
|
||||
case "$action" in install|list|remove) return 0 ;; esac
|
||||
;;
|
||||
restore:grid-sim)
|
||||
case "$action" in db-restore|oar-restore|full-restore|list-backups) return 0 ;; esac
|
||||
;;
|
||||
restore:robust)
|
||||
case "$action" in db-restore|full-restore|list-backups) return 0 ;; esac
|
||||
;;
|
||||
restore:standalone)
|
||||
case "$action" in oar-restore|full-restore|list-backups) return 0 ;; esac
|
||||
;;
|
||||
update:grid-sim|update:robust|update:standalone)
|
||||
case "$action" in create-rollback|list-rollbacks|update-opensim|update-janus|full-update) return 0 ;; esac
|
||||
;;
|
||||
config:grid-sim|config:robust|config:standalone)
|
||||
case "$action" in validate-file|validate-runtime) return 0 ;; esac
|
||||
;;
|
||||
report:grid-sim|report:robust|report:standalone)
|
||||
case "$action" in generate) return 0 ;; esac
|
||||
;;
|
||||
smoke:grid-sim|smoke:robust|smoke:standalone)
|
||||
case "$action" in run) return 0 ;; esac
|
||||
;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_profile_action_allowed() {
|
||||
local module="$1"
|
||||
local profile="$2"
|
||||
local action="$3"
|
||||
|
||||
if ! profile_action_allowed "$module" "$profile" "$action"; then
|
||||
die "$(msg ERR_ACTION_NOT_ALLOWED): module=$module profile=$profile action=$action"
|
||||
fi
|
||||
}
|
||||
|
||||
profile_target_allowed() {
|
||||
local profile="$1"
|
||||
local target="$2"
|
||||
|
||||
case "$profile" in
|
||||
grid-sim)
|
||||
case "$target" in grid|robust|sim1|region|janus) return 0 ;; esac
|
||||
;;
|
||||
robust)
|
||||
case "$target" in robust|janus) return 0 ;; esac
|
||||
;;
|
||||
standalone)
|
||||
case "$target" in standalone|janus) return 0 ;; esac
|
||||
;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_profile_target_allowed() {
|
||||
local profile="$1"
|
||||
local target="$2"
|
||||
|
||||
if ! profile_target_allowed "$profile" "$target"; then
|
||||
die "$(msg ERR_TARGET_NOT_ALLOWED): profile=$profile target=$target"
|
||||
fi
|
||||
}
|
||||
|
||||
load_lang_file() {
|
||||
local lang_file="$1"
|
||||
local target_array_name="$2"
|
||||
local line key value
|
||||
|
||||
[[ -f "$lang_file" ]] || return 1
|
||||
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
[[ -z "$line" || "${line:0:1}" == "#" ]] && continue
|
||||
[[ "$line" == *=* ]] || continue
|
||||
key="${line%%=*}"
|
||||
value="${line#*=}"
|
||||
if [[ "$target_array_name" == "I18N_EN" ]]; then
|
||||
I18N_EN["$key"]="$value"
|
||||
else
|
||||
I18N_CURRENT["$key"]="$value"
|
||||
fi
|
||||
done < "$lang_file"
|
||||
return 0
|
||||
}
|
||||
|
||||
init_i18n() {
|
||||
APP_LANG="$(normalize_lang "$APP_LANG")"
|
||||
|
||||
I18N_CURRENT=()
|
||||
I18N_EN=()
|
||||
|
||||
load_lang_file "$LANG_DIR/en.lang" I18N_EN || true
|
||||
load_lang_file "$LANG_DIR/${APP_LANG}.lang" I18N_CURRENT || true
|
||||
}
|
||||
|
||||
set_language() {
|
||||
APP_LANG="$(normalize_lang "$1")"
|
||||
export OSM_LANG="$APP_LANG"
|
||||
init_i18n
|
||||
}
|
||||
|
||||
msg() {
|
||||
local key="$1"
|
||||
if [[ -n "${I18N_CURRENT[$key]:-}" ]]; then
|
||||
printf '%s' "${I18N_CURRENT[$key]}"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "${I18N_EN[$key]:-}" ]]; then
|
||||
printf '%s' "${I18N_EN[$key]}"
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s' "$key"
|
||||
}
|
||||
|
||||
ui_backend() {
|
||||
if command -v whiptail >/dev/null 2>&1; then
|
||||
echo "whiptail"
|
||||
return
|
||||
fi
|
||||
|
||||
if command -v dialog >/dev/null 2>&1; then
|
||||
echo "dialog"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "none"
|
||||
}
|
||||
|
||||
show_menu() {
|
||||
local title="$1"
|
||||
local text="$2"
|
||||
shift 2
|
||||
local backend
|
||||
backend="$(ui_backend)"
|
||||
|
||||
case "$backend" in
|
||||
whiptail)
|
||||
whiptail --title "$title" --menu "$text" 20 80 12 "$@" 3>&1 1>&2 2>&3
|
||||
;;
|
||||
dialog)
|
||||
dialog --clear --stdout --title "$title" --menu "$text" 20 80 12 "$@"
|
||||
;;
|
||||
none)
|
||||
die "$(msg ERR_NO_UI_BACKEND)"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
confirm() {
|
||||
local title="$1"
|
||||
local text="$2"
|
||||
local backend
|
||||
backend="$(ui_backend)"
|
||||
|
||||
case "$backend" in
|
||||
whiptail)
|
||||
whiptail --title "$title" --yesno "$text" 10 70
|
||||
;;
|
||||
dialog)
|
||||
dialog --clear --title "$title" --yesno "$text" 10 70
|
||||
;;
|
||||
none)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
print_usage_common() {
|
||||
cat <<'EOF'
|
||||
Global options:
|
||||
--workdir <path> Base path (default: /opt)
|
||||
--mode <cli|ui> Run in CLI mode (default) or menu mode
|
||||
--lang <de|en|fr|es> Language selection
|
||||
--profile <name> Runtime profile (grid-sim|robust|standalone)
|
||||
--help Show help
|
||||
EOF
|
||||
}
|
||||
|
||||
# Ensure translations are available in every script that sources this core.
|
||||
init_i18n
|
||||
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_cron.sh [--workdir <path>] --action <install|list|remove>
|
||||
[--backup-schedule "<cron>"] [--restart-schedule "<cron>"] [--check-schedule "<cron>"] [--report-schedule "<cron>"] [--smoke-schedule "<cron>"]
|
||||
[--db-user <user>] [--db-pass <pass>] [--db-name <name>]
|
||||
[--region <name>] [--session <screen-name>] [--compress <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_cron.sh --action list
|
||||
osmtool_cron.sh --action install --backup-schedule "0 3 * * *" --db-user root --db-pass secret --db-name opensim --region sim1
|
||||
osmtool_cron.sh --action remove
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
need_crontab() {
|
||||
need_cmd crontab
|
||||
}
|
||||
|
||||
quote_sq() {
|
||||
local s="$1"
|
||||
s="${s//\'/\'\"\'\"\'}"
|
||||
printf "'%s'" "$s"
|
||||
}
|
||||
|
||||
build_backup_cmd() {
|
||||
local cmd
|
||||
cmd="bash $ROOT_DIR/osmtool_main.sh --module backup --profile $PROFILE --workdir $WORKDIR --action full-backup --db-user $DB_USER --db-name $DB_NAME --region $REGION --session $SESSION_NAME --compress $COMPRESS"
|
||||
|
||||
if [[ -n "$DB_PASS" ]]; then
|
||||
cmd+=" --db-pass $DB_PASS"
|
||||
fi
|
||||
|
||||
printf '%s' "$cmd"
|
||||
}
|
||||
|
||||
build_restart_cmd() {
|
||||
printf '%s' "bash $ROOT_DIR/osmtool_main.sh --module startstop --profile $PROFILE --workdir $WORKDIR --target grid --action restart"
|
||||
}
|
||||
|
||||
build_check_cmd() {
|
||||
printf '%s' "bash $ROOT_DIR/osmtool_main.sh --module install --profile $PROFILE --workdir $WORKDIR --action server-check"
|
||||
}
|
||||
|
||||
build_report_cmd() {
|
||||
local cmd
|
||||
cmd="bash $ROOT_DIR/osmtool_main.sh --module report --profile $PROFILE --workdir $WORKDIR --action generate --db-user $DB_USER --db-name $DB_NAME"
|
||||
|
||||
if [[ -n "$DB_PASS" ]]; then
|
||||
cmd+=" --db-pass $DB_PASS"
|
||||
fi
|
||||
|
||||
printf '%s' "$cmd"
|
||||
}
|
||||
|
||||
build_smoke_cmd() {
|
||||
printf '%s' "bash $ROOT_DIR/osmtool_main.sh --module smoke --profile $PROFILE --workdir $WORKDIR --action run"
|
||||
}
|
||||
|
||||
cron_block_start="# OSMTOOL_CRON_BEGIN"
|
||||
cron_block_end="# OSMTOOL_CRON_END"
|
||||
|
||||
emit_cron_block() {
|
||||
local backup_cmd restart_cmd check_cmd report_cmd smoke_cmd
|
||||
backup_cmd="$(build_backup_cmd)"
|
||||
restart_cmd="$(build_restart_cmd)"
|
||||
check_cmd="$(build_check_cmd)"
|
||||
report_cmd="$(build_report_cmd)"
|
||||
smoke_cmd="$(build_smoke_cmd)"
|
||||
|
||||
echo "$cron_block_start"
|
||||
echo "SHELL=/bin/bash"
|
||||
echo "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
echo "$BACKUP_SCHEDULE $backup_cmd >> $ROOT_DIR/osmtool_backup.log 2>&1"
|
||||
echo "$RESTART_SCHEDULE $restart_cmd >> $ROOT_DIR/osmtool_backup.log 2>&1"
|
||||
echo "$CHECK_SCHEDULE $check_cmd >> $ROOT_DIR/osmtool_backup.log 2>&1"
|
||||
echo "$REPORT_SCHEDULE $report_cmd >> $ROOT_DIR/osmtool_backup.log 2>&1"
|
||||
echo "$SMOKE_SCHEDULE $smoke_cmd >> $ROOT_DIR/osmtool_backup.log 2>&1"
|
||||
echo "$cron_block_end"
|
||||
}
|
||||
|
||||
existing_crontab() {
|
||||
crontab -l 2>/dev/null || true
|
||||
}
|
||||
|
||||
strip_osmtool_block() {
|
||||
awk -v start="$cron_block_start" -v end="$cron_block_end" '
|
||||
$0 == start {inblock=1; next}
|
||||
$0 == end {inblock=0; next}
|
||||
!inblock {print}
|
||||
'
|
||||
}
|
||||
|
||||
install_cron() {
|
||||
local current tmp
|
||||
[[ -n "$DB_USER" && -n "$DB_NAME" ]] || die "install cron requires --db-user and --db-name"
|
||||
|
||||
current="$(existing_crontab)"
|
||||
tmp="$(mktemp)"
|
||||
|
||||
printf '%s\n' "$current" | strip_osmtool_block > "$tmp"
|
||||
if [[ -s "$tmp" ]]; then
|
||||
echo >> "$tmp"
|
||||
fi
|
||||
emit_cron_block >> "$tmp"
|
||||
|
||||
crontab "$tmp"
|
||||
rm -f "$tmp"
|
||||
log INFO "OSMTool cron jobs installed/updated"
|
||||
}
|
||||
|
||||
list_cron() {
|
||||
local current
|
||||
current="$(existing_crontab)"
|
||||
|
||||
if printf '%s\n' "$current" | grep -q "^$cron_block_start$"; then
|
||||
printf '%s\n' "$current" | awk -v start="$cron_block_start" -v end="$cron_block_end" '
|
||||
$0 == start {inblock=1; print; next}
|
||||
$0 == end {print; inblock=0; next}
|
||||
inblock {print}
|
||||
'
|
||||
else
|
||||
log INFO "No OSMTool cron block configured"
|
||||
fi
|
||||
}
|
||||
|
||||
remove_cron() {
|
||||
local current tmp
|
||||
current="$(existing_crontab)"
|
||||
tmp="$(mktemp)"
|
||||
|
||||
printf '%s\n' "$current" | strip_osmtool_block > "$tmp"
|
||||
crontab "$tmp"
|
||||
rm -f "$tmp"
|
||||
log INFO "OSMTool cron block removed"
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
|
||||
BACKUP_SCHEDULE="0 3 * * *"
|
||||
RESTART_SCHEDULE="0 5 * * 1"
|
||||
CHECK_SCHEDULE="*/15 * * * *"
|
||||
REPORT_SCHEDULE="30 6 * * *"
|
||||
SMOKE_SCHEDULE="45 6 * * *"
|
||||
|
||||
DB_USER="root"
|
||||
DB_PASS=""
|
||||
DB_NAME="opensim"
|
||||
REGION="sim1"
|
||||
SESSION_NAME="sim1"
|
||||
COMPRESS="true"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--backup-schedule) BACKUP_SCHEDULE="$2"; shift 2 ;;
|
||||
--restart-schedule) RESTART_SCHEDULE="$2"; shift 2 ;;
|
||||
--check-schedule) CHECK_SCHEDULE="$2"; shift 2 ;;
|
||||
--report-schedule) REPORT_SCHEDULE="$2"; shift 2 ;;
|
||||
--smoke-schedule) SMOKE_SCHEDULE="$2"; shift 2 ;;
|
||||
--db-user) DB_USER="$2"; shift 2 ;;
|
||||
--db-pass) DB_PASS="$2"; shift 2 ;;
|
||||
--db-name) DB_NAME="$2"; shift 2 ;;
|
||||
--region) REGION="$2"; shift 2 ;;
|
||||
--session) SESSION_NAME="$2"; shift 2 ;;
|
||||
--compress) COMPRESS="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
need_crontab
|
||||
|
||||
case "$ACTION" in
|
||||
install|list|remove) ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
|
||||
case "$COMPRESS" in
|
||||
true|false) ;;
|
||||
*) die "--compress must be true or false" ;;
|
||||
esac
|
||||
|
||||
case "$ACTION" in
|
||||
install) install_cron ;;
|
||||
list) list_cron ;;
|
||||
remove) remove_cron ;;
|
||||
esac
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_data.sh [--workdir <path>] --action <db-backup|oar-backup|full-backup>
|
||||
[--db-user <user>] [--db-pass <pass>] [--db-name <name>]
|
||||
[--region <name>] [--session <screen-name>] [--compress <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_data.sh --action db-backup --db-user opensim --db-pass secret --db-name robust
|
||||
osmtool_data.sh --action oar-backup --region sim1 --session sim1 --workdir /opt
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
timestamp() {
|
||||
date '+%Y%m%d_%H%M%S'
|
||||
}
|
||||
|
||||
backup_dir() {
|
||||
printf '%s' "$WORKDIR/backup"
|
||||
}
|
||||
|
||||
ensure_backup_dir() {
|
||||
local dir
|
||||
dir="$(backup_dir)"
|
||||
|
||||
if mkdir -p "$dir" 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$dir"
|
||||
sudo chown "$(id -u):$(id -g)" "$dir"
|
||||
}
|
||||
|
||||
compress_if_enabled() {
|
||||
local file_path="$1"
|
||||
|
||||
if [[ "$COMPRESS" != "true" ]]; then
|
||||
printf '%s' "$file_path"
|
||||
return 0
|
||||
fi
|
||||
|
||||
need_cmd gzip
|
||||
gzip -f "$file_path"
|
||||
printf '%s.gz' "$file_path"
|
||||
}
|
||||
|
||||
resolve_default_session() {
|
||||
if [[ -n "$SESSION_NAME" ]]; then
|
||||
printf '%s' "$SESSION_NAME"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "$REGION" ]]; then
|
||||
printf '%s' "$REGION"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf 'sim1'
|
||||
}
|
||||
|
||||
screen_session_exists() {
|
||||
local name="$1"
|
||||
screen -list 2>/dev/null | grep -qE "\\.${name}[[:space:]]"
|
||||
}
|
||||
|
||||
send_to_screen() {
|
||||
local session_name="$1"
|
||||
local command_text="$2"
|
||||
|
||||
screen -S "$session_name" -p 0 -X stuff "${command_text}^M"
|
||||
}
|
||||
|
||||
db_backup_mysql() {
|
||||
local out
|
||||
need_cmd mysqldump
|
||||
[[ -n "$DB_USER" && -n "$DB_PASS" && -n "$DB_NAME" ]] || die "db-backup(mysql) requires --db-user --db-pass --db-name"
|
||||
|
||||
ensure_backup_dir
|
||||
out="$(backup_dir)/robust_${DB_NAME}_$(timestamp).sql"
|
||||
log INFO "Creating MySQL backup: $out"
|
||||
mysqldump -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$out"
|
||||
out="$(compress_if_enabled "$out")"
|
||||
log INFO "DB backup created: $out"
|
||||
}
|
||||
|
||||
db_backup() {
|
||||
db_backup_mysql
|
||||
}
|
||||
|
||||
oar_backup() {
|
||||
local session_name out command_text
|
||||
|
||||
[[ -n "$REGION" ]] || die "oar-backup requires --region"
|
||||
session_name="$(resolve_default_session)"
|
||||
|
||||
ensure_backup_dir
|
||||
out="$(backup_dir)/${REGION}_$(timestamp).oar"
|
||||
|
||||
if ! screen_session_exists "$session_name"; then
|
||||
die "Screen session not running: $session_name"
|
||||
fi
|
||||
|
||||
# OpenSim console command to export current region as OAR.
|
||||
command_text="save oar $out"
|
||||
log INFO "Sending OAR export command to screen session '$session_name': $command_text"
|
||||
send_to_screen "$session_name" "$command_text"
|
||||
|
||||
log INFO "OAR export command sent. Validate completion in the session log/output."
|
||||
}
|
||||
|
||||
full_backup() {
|
||||
db_backup
|
||||
if [[ -n "$REGION" ]]; then
|
||||
oar_backup
|
||||
else
|
||||
log INFO "No --region provided. DB backup only in full-backup mode."
|
||||
fi
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
DB_USER=""
|
||||
DB_PASS=""
|
||||
DB_NAME=""
|
||||
REGION=""
|
||||
SESSION_NAME=""
|
||||
COMPRESS="false"
|
||||
PROFILE="grid-sim"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--db-user) DB_USER="$2"; shift 2 ;;
|
||||
--db-pass) DB_PASS="$2"; shift 2 ;;
|
||||
--db-name) DB_NAME="$2"; shift 2 ;;
|
||||
--region) REGION="$2"; shift 2 ;;
|
||||
--session) SESSION_NAME="$2"; shift 2 ;;
|
||||
--compress) COMPRESS="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed backup "$PROFILE" "$ACTION"
|
||||
|
||||
case "$COMPRESS" in
|
||||
true|false) ;;
|
||||
*) die "--compress must be true or false" ;;
|
||||
esac
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
db-backup) db_backup ;;
|
||||
oar-backup) oar_backup ;;
|
||||
full-backup) full_backup ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
@@ -0,0 +1,268 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_health.sh [--workdir <path>] --action <run>
|
||||
[--expected-screens <csv|none>] [--ports <csv|none>] [--db-user <user>] [--db-pass <pass>] [--db-name <name>]
|
||||
[--log-file <path>] [--warning-threshold <n>]
|
||||
|
||||
Examples:
|
||||
osmtool_health.sh --action run --workdir /opt
|
||||
osmtool_health.sh --action run --workdir /opt --expected-screens robustserver,sim1 --ports 9000,8002,8088
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
split_csv() {
|
||||
local csv="$1"
|
||||
local token
|
||||
local IFS=','
|
||||
read -r -a _TOKENS <<< "$csv"
|
||||
for token in "${_TOKENS[@]}"; do
|
||||
token="${token## }"
|
||||
token="${token%% }"
|
||||
[[ -n "$token" ]] && printf '%s\n' "$token"
|
||||
done
|
||||
}
|
||||
|
||||
report_ok() {
|
||||
log INFO "[OK] $1"
|
||||
}
|
||||
|
||||
report_warn() {
|
||||
log INFO "[WARN] $1"
|
||||
}
|
||||
|
||||
report_err() {
|
||||
log ERROR "[FAIL] $1"
|
||||
}
|
||||
|
||||
check_screens() {
|
||||
local fail_count=0
|
||||
local screen_name
|
||||
|
||||
if [[ -z "$EXPECTED_SCREENS" ]]; then
|
||||
report_warn "Screen check skipped (no expected screens configured)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r screen_name; do
|
||||
[[ -n "$screen_name" ]] || continue
|
||||
if screen -list 2>/dev/null | grep -qE "\\.${screen_name}[[:space:]]"; then
|
||||
report_ok "Screen session running: $screen_name"
|
||||
else
|
||||
report_err "Screen session missing: $screen_name"
|
||||
fail_count=$((fail_count + 1))
|
||||
fi
|
||||
done < <(split_csv "$EXPECTED_SCREENS")
|
||||
|
||||
return "$fail_count"
|
||||
}
|
||||
|
||||
check_ports() {
|
||||
local fail_count=0
|
||||
local port
|
||||
local cmd_ss=0
|
||||
|
||||
if [[ -z "$PORTS" ]]; then
|
||||
report_warn "Port check skipped (no ports configured)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
cmd_ss=1
|
||||
elif ! command -v netstat >/dev/null 2>&1; then
|
||||
report_warn "Port check skipped (neither ss nor netstat available)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r port; do
|
||||
[[ -n "$port" ]] || continue
|
||||
if [[ "$cmd_ss" -eq 1 ]]; then
|
||||
if ss -ltnH | awk '{print $4}' | grep -qE "[:.]${port}$"; then
|
||||
report_ok "Port listening: $port"
|
||||
else
|
||||
report_err "Port not listening: $port"
|
||||
fail_count=$((fail_count + 1))
|
||||
fi
|
||||
else
|
||||
if netstat -ltn 2>/dev/null | awk '{print $4}' | grep -qE "[:.]${port}$"; then
|
||||
report_ok "Port listening: $port"
|
||||
else
|
||||
report_err "Port not listening: $port"
|
||||
fail_count=$((fail_count + 1))
|
||||
fi
|
||||
fi
|
||||
done < <(split_csv "$PORTS")
|
||||
|
||||
return "$fail_count"
|
||||
}
|
||||
|
||||
check_database() {
|
||||
local fail_count=0
|
||||
|
||||
if [[ -z "$DB_USER" || -z "$DB_NAME" ]]; then
|
||||
report_warn "Database check skipped (missing --db-user/--db-name)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! command -v mariadb >/dev/null 2>&1; then
|
||||
report_err "Database check failed: mariadb client missing"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -n "$DB_PASS" ]]; then
|
||||
if mariadb -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SELECT 1" >/dev/null 2>&1; then
|
||||
report_ok "Database reachable: $DB_NAME"
|
||||
else
|
||||
report_err "Database not reachable: $DB_NAME"
|
||||
fail_count=$((fail_count + 1))
|
||||
fi
|
||||
else
|
||||
if mariadb -u"$DB_USER" "$DB_NAME" -e "SELECT 1" >/dev/null 2>&1; then
|
||||
report_ok "Database reachable: $DB_NAME"
|
||||
else
|
||||
report_err "Database not reachable: $DB_NAME"
|
||||
fail_count=$((fail_count + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
return "$fail_count"
|
||||
}
|
||||
|
||||
count_log_warnings() {
|
||||
local file="$1"
|
||||
grep -Eic 'error|warn|exception|fatal' "$file" 2>/dev/null || true
|
||||
}
|
||||
|
||||
check_logs() {
|
||||
local warn_count total=0
|
||||
local default_logs=()
|
||||
|
||||
if [[ -n "$LOG_FILE_PATH" ]]; then
|
||||
default_logs+=("$LOG_FILE_PATH")
|
||||
else
|
||||
default_logs+=("$ROOT_DIR/osmtool_backup.log")
|
||||
default_logs+=("$WORKDIR/robust/bin/OpenSim.log")
|
||||
fi
|
||||
|
||||
for logf in "${default_logs[@]}"; do
|
||||
if [[ -f "$logf" ]]; then
|
||||
warn_count="$(count_log_warnings "$logf")"
|
||||
report_ok "Log scan: $logf -> $warn_count matches"
|
||||
total=$((total + warn_count))
|
||||
else
|
||||
report_warn "Log file not found, skipped: $logf"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$total" -gt "$WARNING_THRESHOLD" ]]; then
|
||||
report_err "Log warning threshold exceeded: $total > $WARNING_THRESHOLD"
|
||||
return 1
|
||||
fi
|
||||
|
||||
report_ok "Log warning threshold OK: $total <= $WARNING_THRESHOLD"
|
||||
return 0
|
||||
}
|
||||
|
||||
default_screens_for_profile() {
|
||||
case "$1" in
|
||||
grid-sim) echo "robustserver,sim1" ;;
|
||||
robust) echo "robustserver" ;;
|
||||
standalone) echo "standalone" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
default_ports_for_profile() {
|
||||
case "$1" in
|
||||
grid-sim) echo "8002,9000,9001,8088" ;;
|
||||
robust) echo "8002,9000,9001" ;;
|
||||
standalone) echo "9000" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
run_health() {
|
||||
local fails=0
|
||||
|
||||
log INFO "Running health checks for profile: $PROFILE"
|
||||
log INFO "Using workdir: $WORKDIR"
|
||||
|
||||
if ! check_screens; then
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
|
||||
if ! check_ports; then
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
|
||||
if ! check_database; then
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
|
||||
if ! check_logs; then
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
|
||||
if [[ "$fails" -eq 0 ]]; then
|
||||
report_ok "Healthcheck PASSED"
|
||||
return 0
|
||||
fi
|
||||
|
||||
report_err "Healthcheck FAILED with $fails failing check group(s)"
|
||||
return 1
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
EXPECTED_SCREENS=""
|
||||
PORTS=""
|
||||
DB_USER=""
|
||||
DB_PASS=""
|
||||
DB_NAME=""
|
||||
LOG_FILE_PATH=""
|
||||
WARNING_THRESHOLD=50
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--expected-screens) EXPECTED_SCREENS="$2"; shift 2 ;;
|
||||
--ports) PORTS="$2"; shift 2 ;;
|
||||
--db-user) DB_USER="$2"; shift 2 ;;
|
||||
--db-pass) DB_PASS="$2"; shift 2 ;;
|
||||
--db-name) DB_NAME="$2"; shift 2 ;;
|
||||
--log-file) LOG_FILE_PATH="$2"; shift 2 ;;
|
||||
--warning-threshold) WARNING_THRESHOLD="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed health "$PROFILE" "$ACTION"
|
||||
|
||||
if [[ -z "$EXPECTED_SCREENS" ]]; then
|
||||
EXPECTED_SCREENS="$(default_screens_for_profile "$PROFILE")"
|
||||
elif [[ "$EXPECTED_SCREENS" == "none" ]]; then
|
||||
EXPECTED_SCREENS=""
|
||||
fi
|
||||
if [[ -z "$PORTS" ]]; then
|
||||
PORTS="$(default_ports_for_profile "$PROFILE")"
|
||||
elif [[ "$PORTS" == "none" ]]; then
|
||||
PORTS=""
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
run) run_health ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,293 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_report.sh [--workdir <path>] --action <generate>
|
||||
[--output <file>] [--expected-screens <csv|none>] [--ports <csv|none>]
|
||||
[--db-user <user>] [--db-pass <pass>] [--db-name <name>] [--log-file <path>]
|
||||
|
||||
Examples:
|
||||
osmtool_report.sh --action generate --workdir /opt --db-user opensim --db-pass secret --db-name robust
|
||||
osmtool_report.sh --action generate --workdir /opt --output /opt/reports/manual_report.txt
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
timestamp_compact() {
|
||||
date '+%Y%m%d_%H%M%S'
|
||||
}
|
||||
|
||||
timestamp_iso() {
|
||||
date '+%Y-%m-%d %H:%M:%S'
|
||||
}
|
||||
|
||||
split_csv() {
|
||||
local csv="$1"
|
||||
local token
|
||||
local IFS=','
|
||||
read -r -a _TOKENS <<< "$csv"
|
||||
for token in "${_TOKENS[@]}"; do
|
||||
token="${token## }"
|
||||
token="${token%% }"
|
||||
[[ -n "$token" ]] && printf '%s\n' "$token"
|
||||
done
|
||||
}
|
||||
|
||||
reports_dir() {
|
||||
printf '%s' "$WORKDIR/reports"
|
||||
}
|
||||
|
||||
ensure_reports_dir() {
|
||||
local dir
|
||||
dir="$(reports_dir)"
|
||||
|
||||
if mkdir -p "$dir" 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$dir"
|
||||
sudo chown "$(id -u):$(id -g)" "$dir"
|
||||
}
|
||||
|
||||
latest_file() {
|
||||
local dir="$1"
|
||||
local pattern="$2"
|
||||
|
||||
[[ -d "$dir" ]] || return 0
|
||||
find "$dir" -maxdepth 1 -type f -name "$pattern" -printf '%T@ %p\n' 2>/dev/null | \
|
||||
sort -rn | head -1 | cut -d' ' -f2-
|
||||
}
|
||||
|
||||
format_file_age_hours() {
|
||||
local path="$1"
|
||||
local now ts age
|
||||
|
||||
[[ -f "$path" ]] || {
|
||||
printf 'n/a'
|
||||
return 0
|
||||
}
|
||||
|
||||
now="$(date +%s)"
|
||||
ts="$(stat -c %Y "$path" 2>/dev/null || echo 0)"
|
||||
if [[ "$ts" -le 0 ]]; then
|
||||
printf 'n/a'
|
||||
return 0
|
||||
fi
|
||||
|
||||
age=$(( (now - ts) / 3600 ))
|
||||
printf '%sh' "$age"
|
||||
}
|
||||
|
||||
screen_status_lines() {
|
||||
local screen_name
|
||||
|
||||
if [[ -z "$EXPECTED_SCREENS" ]]; then
|
||||
printf 'screen: skipped\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r screen_name; do
|
||||
[[ -n "$screen_name" ]] || continue
|
||||
if screen -list 2>/dev/null | grep -qE "\\.${screen_name}[[:space:]]"; then
|
||||
printf 'screen:%s=up\n' "$screen_name"
|
||||
else
|
||||
printf 'screen:%s=down\n' "$screen_name"
|
||||
fi
|
||||
done < <(split_csv "$EXPECTED_SCREENS")
|
||||
}
|
||||
|
||||
port_status_lines() {
|
||||
local port
|
||||
local use_ss=0
|
||||
|
||||
if [[ -z "$PORTS" ]]; then
|
||||
printf 'port: skipped\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
use_ss=1
|
||||
elif ! command -v netstat >/dev/null 2>&1; then
|
||||
printf 'port: unavailable (no ss/netstat)\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r port; do
|
||||
[[ -n "$port" ]] || continue
|
||||
if [[ "$use_ss" -eq 1 ]]; then
|
||||
if ss -ltnH | awk '{print $4}' | grep -qE "[:.]${port}$"; then
|
||||
printf 'port:%s=listen\n' "$port"
|
||||
else
|
||||
printf 'port:%s=closed\n' "$port"
|
||||
fi
|
||||
else
|
||||
if netstat -ltn 2>/dev/null | awk '{print $4}' | grep -qE "[:.]${port}$"; then
|
||||
printf 'port:%s=listen\n' "$port"
|
||||
else
|
||||
printf 'port:%s=closed\n' "$port"
|
||||
fi
|
||||
fi
|
||||
done < <(split_csv "$PORTS")
|
||||
}
|
||||
|
||||
database_status() {
|
||||
if [[ -z "$DB_USER" || -z "$DB_NAME" ]]; then
|
||||
printf 'db: skipped\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! command -v mariadb >/dev/null 2>&1; then
|
||||
printf 'db:%s=client-missing\n' "$DB_NAME"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "$DB_PASS" ]]; then
|
||||
if mariadb -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SELECT 1" >/dev/null 2>&1; then
|
||||
printf 'db:%s=ok\n' "$DB_NAME"
|
||||
else
|
||||
printf 'db:%s=fail\n' "$DB_NAME"
|
||||
fi
|
||||
else
|
||||
if mariadb -u"$DB_USER" "$DB_NAME" -e "SELECT 1" >/dev/null 2>&1; then
|
||||
printf 'db:%s=ok\n' "$DB_NAME"
|
||||
else
|
||||
printf 'db:%s=fail\n' "$DB_NAME"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
log_warning_count() {
|
||||
local file="$1"
|
||||
[[ -f "$file" ]] || {
|
||||
printf 'n/a'
|
||||
return 0
|
||||
}
|
||||
|
||||
grep -Eic 'error|warn|exception|fatal' "$file" 2>/dev/null || printf '0'
|
||||
}
|
||||
|
||||
default_screens_for_profile() {
|
||||
case "$1" in
|
||||
grid-sim) echo "robustserver,sim1" ;;
|
||||
robust) echo "robustserver" ;;
|
||||
standalone) echo "standalone" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
default_ports_for_profile() {
|
||||
case "$1" in
|
||||
grid-sim) echo "8002,9000,9001,8088" ;;
|
||||
robust) echo "8002,9000,9001" ;;
|
||||
standalone) echo "9000" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
generate_report() {
|
||||
local out report_title log_target
|
||||
local newest_sql newest_oar newest_rollback
|
||||
|
||||
ensure_reports_dir
|
||||
|
||||
if [[ -n "$OUTPUT_FILE" ]]; then
|
||||
out="$OUTPUT_FILE"
|
||||
else
|
||||
out="$(reports_dir)/osm_report_$(timestamp_compact).txt"
|
||||
fi
|
||||
|
||||
newest_sql="$(latest_file "$WORKDIR/backup" 'robust_*.sql*')"
|
||||
newest_oar="$(latest_file "$WORKDIR/backup" '*.oar')"
|
||||
newest_rollback="$(latest_file "$WORKDIR/rollback" '*.manifest')"
|
||||
log_target="$LOG_FILE_PATH"
|
||||
if [[ -z "$log_target" ]]; then
|
||||
log_target="$ROOT_DIR/osmtool_backup.log"
|
||||
fi
|
||||
|
||||
report_title="OSMTool Daily Status Report"
|
||||
|
||||
{
|
||||
printf '%s\n' "$report_title"
|
||||
printf 'generated_at: %s\n' "$(timestamp_iso)"
|
||||
printf 'profile: %s\n' "$PROFILE"
|
||||
printf 'workdir: %s\n' "$WORKDIR"
|
||||
printf '\n'
|
||||
printf '[runtime]\n'
|
||||
screen_status_lines
|
||||
port_status_lines
|
||||
database_status
|
||||
printf '\n'
|
||||
printf '[backup]\n'
|
||||
printf 'sql_latest: %s\n' "${newest_sql:-none}"
|
||||
printf 'sql_age: %s\n' "$(format_file_age_hours "${newest_sql:-}")"
|
||||
printf 'oar_latest: %s\n' "${newest_oar:-none}"
|
||||
printf 'oar_age: %s\n' "$(format_file_age_hours "${newest_oar:-}")"
|
||||
printf '\n'
|
||||
printf '[rollback]\n'
|
||||
printf 'latest_manifest: %s\n' "${newest_rollback:-none}"
|
||||
printf 'manifest_age: %s\n' "$(format_file_age_hours "${newest_rollback:-}")"
|
||||
printf '\n'
|
||||
printf '[logs]\n'
|
||||
printf 'file: %s\n' "$log_target"
|
||||
printf 'warning_matches: %s\n' "$(log_warning_count "$log_target")"
|
||||
} > "$out"
|
||||
|
||||
log INFO "Report generated: $out"
|
||||
cat "$out"
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
OUTPUT_FILE=""
|
||||
EXPECTED_SCREENS=""
|
||||
PORTS=""
|
||||
DB_USER=""
|
||||
DB_PASS=""
|
||||
DB_NAME=""
|
||||
LOG_FILE_PATH=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--output) OUTPUT_FILE="$2"; shift 2 ;;
|
||||
--expected-screens) EXPECTED_SCREENS="$2"; shift 2 ;;
|
||||
--ports) PORTS="$2"; shift 2 ;;
|
||||
--db-user) DB_USER="$2"; shift 2 ;;
|
||||
--db-pass) DB_PASS="$2"; shift 2 ;;
|
||||
--db-name) DB_NAME="$2"; shift 2 ;;
|
||||
--log-file) LOG_FILE_PATH="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed report "$PROFILE" "$ACTION"
|
||||
|
||||
if [[ -z "$EXPECTED_SCREENS" ]]; then
|
||||
EXPECTED_SCREENS="$(default_screens_for_profile "$PROFILE")"
|
||||
elif [[ "$EXPECTED_SCREENS" == "none" ]]; then
|
||||
EXPECTED_SCREENS=""
|
||||
fi
|
||||
|
||||
if [[ -z "$PORTS" ]]; then
|
||||
PORTS="$(default_ports_for_profile "$PROFILE")"
|
||||
elif [[ "$PORTS" == "none" ]]; then
|
||||
PORTS=""
|
||||
fi
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
generate) generate_report ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_restore.sh [--workdir <path>] --action <db-restore|oar-restore|full-restore|list-backups>
|
||||
[--db-user <user>] [--db-pass <pass>] [--db-name <name>]
|
||||
[--region <name>] [--session <screen-name>] [--file <backup-file>]
|
||||
[--dry-run <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_restore.sh --action list-backups --workdir /opt
|
||||
osmtool_restore.sh --action db-restore --db-user opensim --db-pass secret --db-name robust --file /opt/backup/robust_robust_20260401_120000.sql
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
backup_dir() {
|
||||
printf '%s' "$WORKDIR/backup"
|
||||
}
|
||||
|
||||
ensure_backup_dir() {
|
||||
local dir
|
||||
dir="$(backup_dir)"
|
||||
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
die "Backup directory does not exist: $dir"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
list_backups() {
|
||||
local dir
|
||||
dir="$(backup_dir)"
|
||||
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
log INFO "No backup directory found: $dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "SQL Backups:"
|
||||
find "$dir" -maxdepth 1 -name "robust_*.sql*" -type f -printf '%T@ %p\n' 2>/dev/null | \
|
||||
sort -rn | cut -d' ' -f2- | head -5 || true
|
||||
|
||||
log INFO "OAR Backups:"
|
||||
find "$dir" -maxdepth 1 -name "*.oar" -type f -printf '%T@ %p\n' 2>/dev/null | \
|
||||
sort -rn | cut -d' ' -f2- | head -5 || true
|
||||
}
|
||||
|
||||
resolve_default_session() {
|
||||
if [[ -n "$SESSION_NAME" ]]; then
|
||||
printf '%s' "$SESSION_NAME"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "$REGION" ]]; then
|
||||
printf '%s' "$REGION"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf 'sim1'
|
||||
}
|
||||
|
||||
screen_session_exists() {
|
||||
local name="$1"
|
||||
screen -list 2>/dev/null | grep -qE "\\.${name}[[:space:]]"
|
||||
}
|
||||
|
||||
send_to_screen() {
|
||||
local session_name="$1"
|
||||
local command_text="$2"
|
||||
|
||||
screen -S "$session_name" -p 0 -X stuff "${command_text}^M"
|
||||
}
|
||||
|
||||
validate_sql_file() {
|
||||
local file="$1"
|
||||
|
||||
if [[ ! -f "$file" ]]; then
|
||||
die "SQL backup file not found: $file"
|
||||
fi
|
||||
|
||||
# Check for gzip compression
|
||||
if [[ "$file" =~ \.gz$ ]]; then
|
||||
need_cmd zcat
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
validate_oar_file() {
|
||||
local file="$1"
|
||||
|
||||
if [[ ! -f "$file" ]]; then
|
||||
die "OAR backup file not found: $file"
|
||||
fi
|
||||
|
||||
if [[ ! "$file" =~ \.oar$ ]]; then
|
||||
die "File does not appear to be an OAR backup: $file"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
db_restore_mysql() {
|
||||
local file sql_cmd
|
||||
|
||||
[[ -n "$DB_USER" && -n "$DB_PASS" && -n "$DB_NAME" ]] || die "db-restore requires --db-user --db-pass --db-name"
|
||||
[[ -n "$FILE" ]] || die "db-restore requires --file"
|
||||
|
||||
file="$FILE"
|
||||
validate_sql_file "$file"
|
||||
|
||||
need_cmd mysql
|
||||
|
||||
if [[ "$file" =~ \.gz$ ]]; then
|
||||
sql_cmd="zcat '$file' | mysql -u'$DB_USER' -p'$DB_PASS' '$DB_NAME'"
|
||||
else
|
||||
sql_cmd="mysql -u'$DB_USER' -p'$DB_PASS' '$DB_NAME' < '$file'"
|
||||
fi
|
||||
|
||||
log INFO "Database restore command:"
|
||||
log INFO "$sql_cmd"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
log INFO "[DRY-RUN] Not executing database restore"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Restoring database from: $file"
|
||||
if [[ "$file" =~ \.gz$ ]]; then
|
||||
zcat "$file" | mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" || die "Database restore failed"
|
||||
else
|
||||
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$file" || die "Database restore failed"
|
||||
fi
|
||||
|
||||
log INFO "Database restore completed successfully from: $file"
|
||||
}
|
||||
|
||||
db_restore() {
|
||||
db_restore_mysql
|
||||
}
|
||||
|
||||
oar_restore() {
|
||||
local session_name file cmd
|
||||
|
||||
[[ -n "$REGION" ]] || die "oar-restore requires --region"
|
||||
[[ -n "$FILE" ]] || die "oar-restore requires --file"
|
||||
|
||||
file="$FILE"
|
||||
validate_oar_file "$file"
|
||||
|
||||
session_name="$(resolve_default_session)"
|
||||
|
||||
if ! screen_session_exists "$session_name"; then
|
||||
die "Screen session not running: $session_name"
|
||||
fi
|
||||
|
||||
cmd="load oar $file"
|
||||
log INFO "OAR restore command:"
|
||||
log INFO "$cmd"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
log INFO "[DRY-RUN] Not executing OAR restore"
|
||||
log INFO "To complete restore, region '$session_name' must be running and responsive"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Sending OAR restore command to screen session '$session_name'"
|
||||
send_to_screen "$session_name" "$cmd"
|
||||
log INFO "OAR restore command sent. Region import may take some time. Check session output for completion."
|
||||
}
|
||||
|
||||
full_restore() {
|
||||
local has_sql has_oar
|
||||
|
||||
has_sql=false
|
||||
has_oar=false
|
||||
|
||||
# Try to detect which restores to perform based on parameters
|
||||
if [[ -n "$FILE" ]] && [[ "$FILE" =~ \.(sql|gz)$ ]]; then
|
||||
has_sql=true
|
||||
fi
|
||||
|
||||
if [[ -n "$FILE" ]] && [[ "$FILE" =~ \.oar$ ]]; then
|
||||
has_oar=true
|
||||
fi
|
||||
|
||||
if [[ "$has_sql" == "true" ]]; then
|
||||
log INFO "Detected SQL backup file, proceeding with database restore..."
|
||||
db_restore
|
||||
fi
|
||||
|
||||
if [[ "$has_oar" == "true" ]]; then
|
||||
log INFO "Detected OAR backup file, proceeding with OAR restore..."
|
||||
if [[ -n "$REGION" ]]; then
|
||||
oar_restore
|
||||
else
|
||||
log WARN "OAR file provided but no --region specified. Skipping OAR restore."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$has_sql" == "false" && "$has_oar" == "false" ]]; then
|
||||
die "full-restore requires --file with .sql/.sql.gz or .oar extension"
|
||||
fi
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
DB_USER=""
|
||||
DB_PASS=""
|
||||
DB_NAME=""
|
||||
REGION=""
|
||||
SESSION_NAME=""
|
||||
FILE=""
|
||||
DRY_RUN="false"
|
||||
PROFILE="grid-sim"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--db-user) DB_USER="$2"; shift 2 ;;
|
||||
--db-pass) DB_PASS="$2"; shift 2 ;;
|
||||
--db-name) DB_NAME="$2"; shift 2 ;;
|
||||
--region) REGION="$2"; shift 2 ;;
|
||||
--session) SESSION_NAME="$2"; shift 2 ;;
|
||||
--file) FILE="$2"; shift 2 ;;
|
||||
--dry-run) DRY_RUN="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed restore "$PROFILE" "$ACTION"
|
||||
|
||||
case "$DRY_RUN" in
|
||||
true|false) ;;
|
||||
*) die "--dry-run must be true or false" ;;
|
||||
esac
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
db-restore) db_restore ;;
|
||||
oar-restore) oar_restore ;;
|
||||
full-restore) full_restore ;;
|
||||
list-backups) ensure_backup_dir; list_backups ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_smoke.sh [--workdir <path>] --action <run>
|
||||
[--target <grid|robust|sim1|standalone|janus|region>] [--name <region-screen-name>]
|
||||
[--expected-screens <csv>] [--wait-after-start <sec>] [--wait-after-stop <sec>]
|
||||
[--janus-prefix <path>]
|
||||
|
||||
Examples:
|
||||
osmtool_smoke.sh --action run --profile grid-sim --workdir /opt
|
||||
osmtool_smoke.sh --action run --profile robust --workdir /opt --expected-screens robustserver
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
split_csv() {
|
||||
local csv="$1"
|
||||
local token
|
||||
local IFS=','
|
||||
read -r -a _TOKENS <<< "$csv"
|
||||
for token in "${_TOKENS[@]}"; do
|
||||
token="${token## }"
|
||||
token="${token%% }"
|
||||
[[ -n "$token" ]] && printf '%s\n' "$token"
|
||||
done
|
||||
}
|
||||
|
||||
default_target_for_profile() {
|
||||
case "$1" in
|
||||
grid-sim) echo "grid" ;;
|
||||
robust) echo "robust" ;;
|
||||
standalone) echo "standalone" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
default_expected_screens_for_target() {
|
||||
case "$1" in
|
||||
grid) echo "robustserver,sim1" ;;
|
||||
robust) echo "robustserver" ;;
|
||||
sim1) echo "sim1" ;;
|
||||
standalone) echo "standalone" ;;
|
||||
janus) echo "janus_gateway" ;;
|
||||
region) [[ -n "$NAME" ]] && echo "$NAME" || echo "" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
screen_session_exists() {
|
||||
local name="$1"
|
||||
screen -list 2>/dev/null | grep -qE "\\.${name}[[:space:]]"
|
||||
}
|
||||
|
||||
verify_screens_up() {
|
||||
local name failed=0
|
||||
|
||||
[[ -n "$EXPECTED_SCREENS" ]] || {
|
||||
log INFO "No expected screens configured; skipping UP verification"
|
||||
return 0
|
||||
}
|
||||
|
||||
while IFS= read -r name; do
|
||||
[[ -n "$name" ]] || continue
|
||||
if screen_session_exists "$name"; then
|
||||
log INFO "[SMOKE][OK] screen up: $name"
|
||||
else
|
||||
log ERROR "[SMOKE][FAIL] screen not running: $name"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
done < <(split_csv "$EXPECTED_SCREENS")
|
||||
|
||||
return "$failed"
|
||||
}
|
||||
|
||||
verify_screens_down() {
|
||||
local name failed=0
|
||||
|
||||
[[ -n "$EXPECTED_SCREENS" ]] || {
|
||||
log INFO "No expected screens configured; skipping DOWN verification"
|
||||
return 0
|
||||
}
|
||||
|
||||
while IFS= read -r name; do
|
||||
[[ -n "$name" ]] || continue
|
||||
if screen_session_exists "$name"; then
|
||||
log ERROR "[SMOKE][FAIL] screen still running: $name"
|
||||
failed=$((failed + 1))
|
||||
else
|
||||
log INFO "[SMOKE][OK] screen down: $name"
|
||||
fi
|
||||
done < <(split_csv "$EXPECTED_SCREENS")
|
||||
|
||||
return "$failed"
|
||||
}
|
||||
|
||||
run_startstop() {
|
||||
local action="$1"
|
||||
local -a cmd
|
||||
|
||||
cmd=(bash "$ROOT_DIR/osmtool_main.sh" --module startstop --profile "$PROFILE" --workdir "$WORKDIR" --target "$TARGET" --action "$action")
|
||||
if [[ "$TARGET" == "region" && -n "$NAME" ]]; then
|
||||
cmd+=(--name "$NAME")
|
||||
fi
|
||||
if [[ -n "$JANUS_PREFIX" ]]; then
|
||||
cmd+=(--janus-prefix "$JANUS_PREFIX")
|
||||
fi
|
||||
|
||||
"${cmd[@]}"
|
||||
}
|
||||
|
||||
run_smoke() {
|
||||
local failures=0
|
||||
|
||||
log INFO "[SMOKE] profile=$PROFILE target=$TARGET workdir=$WORKDIR"
|
||||
log INFO "[SMOKE] expected_screens=$EXPECTED_SCREENS"
|
||||
|
||||
run_startstop start || failures=$((failures + 1))
|
||||
sleep "$WAIT_AFTER_START"
|
||||
verify_screens_up || failures=$((failures + 1))
|
||||
|
||||
run_startstop restart || failures=$((failures + 1))
|
||||
sleep "$WAIT_AFTER_START"
|
||||
verify_screens_up || failures=$((failures + 1))
|
||||
|
||||
run_startstop stop || failures=$((failures + 1))
|
||||
sleep "$WAIT_AFTER_STOP"
|
||||
verify_screens_down || failures=$((failures + 1))
|
||||
|
||||
if [[ "$failures" -eq 0 ]]; then
|
||||
log INFO "[SMOKE][PASS] Start/Restart/Stop smoke test successful"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log ERROR "[SMOKE][FAIL] Smoke test failed with $failures issue group(s)"
|
||||
return 1
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
TARGET=""
|
||||
NAME=""
|
||||
EXPECTED_SCREENS=""
|
||||
WAIT_AFTER_START="3"
|
||||
WAIT_AFTER_STOP="8"
|
||||
JANUS_PREFIX="${JANUS_PREFIX:-/opt/janus}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--target) TARGET="$2"; shift 2 ;;
|
||||
--name) NAME="$2"; shift 2 ;;
|
||||
--expected-screens) EXPECTED_SCREENS="$2"; shift 2 ;;
|
||||
--wait-after-start) WAIT_AFTER_START="$2"; shift 2 ;;
|
||||
--wait-after-stop) WAIT_AFTER_STOP="$2"; shift 2 ;;
|
||||
--janus-prefix) JANUS_PREFIX="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed smoke "$PROFILE" "$ACTION"
|
||||
|
||||
if [[ -z "$TARGET" ]]; then
|
||||
TARGET="$(default_target_for_profile "$PROFILE")"
|
||||
fi
|
||||
ensure_profile_target_allowed "$PROFILE" "$TARGET"
|
||||
|
||||
if [[ "$TARGET" == "region" && -z "$NAME" ]]; then
|
||||
die "--name is required for --target region"
|
||||
fi
|
||||
|
||||
if [[ -z "$EXPECTED_SCREENS" ]]; then
|
||||
EXPECTED_SCREENS="$(default_expected_screens_for_target "$TARGET")"
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
run) run_smoke ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
@@ -0,0 +1,316 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_startstop.sh [--workdir <path>] [--profile <grid-sim|robust|standalone>] --target <grid|robust|sim1|standalone|janus|region> --action <start|stop|restart> [--name <region-screen-name>]
|
||||
[--janus-prefix <path>]
|
||||
|
||||
Examples:
|
||||
osmtool_startstop.sh --profile grid-sim --target grid --action start --workdir /opt
|
||||
osmtool_startstop.sh --profile robust --target robust --action restart --workdir /opt
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
run_screen_cmd() {
|
||||
local screen_name="$1"
|
||||
local command_text="$2"
|
||||
screen -S "$screen_name" -p 0 -X stuff "${command_text}^M"
|
||||
}
|
||||
|
||||
screen_session_exists() {
|
||||
local screen_name="$1"
|
||||
screen -list 2>/dev/null | grep -qE "\\.${screen_name}[[:space:]]"
|
||||
}
|
||||
|
||||
stop_screen_session() {
|
||||
local screen_name="$1"
|
||||
local grace_seconds="${2:-6}"
|
||||
|
||||
if ! screen_session_exists "$screen_name"; then
|
||||
log INFO "$screen_name is not running"
|
||||
return 0
|
||||
fi
|
||||
|
||||
run_screen_cmd "$screen_name" "shutdown"
|
||||
log INFO "Sent shutdown to $screen_name"
|
||||
sleep "$grace_seconds"
|
||||
|
||||
if screen_session_exists "$screen_name"; then
|
||||
log INFO "Session '$screen_name' still running after shutdown; forcing screen quit"
|
||||
screen -S "$screen_name" -X quit || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if screen_session_exists "$screen_name"; then
|
||||
log ERROR "Failed to stop screen session: $screen_name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log INFO "Screen session '$screen_name' stopped"
|
||||
return 0
|
||||
}
|
||||
|
||||
ensure_janus_ready() {
|
||||
local marker="$JANUS_PREFIX/.osmtool_janus_ready"
|
||||
local core_cfg="$JANUS_PREFIX/etc/janus/janus.jcfg"
|
||||
local core_cfg_legacy="$JANUS_PREFIX/etc/janus/janus.cfg"
|
||||
local http_cfg="$JANUS_PREFIX/etc/janus/janus.transport.http.jcfg"
|
||||
local http_cfg_legacy="$JANUS_PREFIX/etc/janus/janus.transport.http.cfg"
|
||||
|
||||
[[ -f "$JANUS_PREFIX/bin/janus" ]] || die "Janus binary missing: $JANUS_PREFIX/bin/janus. Run install module action compile-janus/install-janus first."
|
||||
|
||||
if [[ ! -f "$core_cfg" && ! -f "$core_cfg_legacy" ]]; then
|
||||
die "Janus core config missing in $JANUS_PREFIX/etc/janus. Run configure-janus/install-janus first."
|
||||
fi
|
||||
|
||||
if [[ ! -f "$http_cfg" && ! -f "$http_cfg_legacy" ]]; then
|
||||
die "Janus HTTP config missing in $JANUS_PREFIX/etc/janus. Run configure-janus/install-janus first."
|
||||
fi
|
||||
|
||||
[[ -f "$marker" ]] || log INFO "Janus ready marker not found ($marker). Continuing because binary/config files exist."
|
||||
}
|
||||
|
||||
janus_service_action() {
|
||||
local action="$1"
|
||||
local janus_bin janus_cfg
|
||||
|
||||
janus_bin="$JANUS_PREFIX/bin/janus"
|
||||
janus_cfg="$JANUS_PREFIX/etc/janus/janus.jcfg"
|
||||
[[ -f "$janus_cfg" ]] || janus_cfg="$JANUS_PREFIX/etc/janus/janus.cfg"
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
if systemctl list-unit-files 2>/dev/null | grep -q '^janus\.service'; then
|
||||
sudo systemctl "$action" janus
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v service >/dev/null 2>&1; then
|
||||
if service --status-all 2>/dev/null | grep -q janus; then
|
||||
sudo service janus "$action"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -x "$WORKDIR/janus.sh" ]]; then
|
||||
"$WORKDIR/janus.sh" "${action}_janus" || "$WORKDIR/janus.sh" "$action"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -x "$WORKDIR/janus/janus.sh" ]]; then
|
||||
"$WORKDIR/janus/janus.sh" "${action}_janus" || "$WORKDIR/janus/janus.sh" "$action"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Fallback: control Janus directly from installed binary.
|
||||
if [[ -x "$janus_bin" ]]; then
|
||||
case "$action" in
|
||||
start)
|
||||
if pgrep -f "$janus_bin" >/dev/null 2>&1; then
|
||||
log INFO "Janus already running"
|
||||
return 0
|
||||
fi
|
||||
if command -v screen >/dev/null 2>&1; then
|
||||
screen -fa -S janus_gateway -d -U -m "$janus_bin" -C "$janus_cfg"
|
||||
else
|
||||
nohup "$janus_bin" -C "$janus_cfg" >/tmp/janus.log 2>&1 &
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
stop)
|
||||
pkill -f "$janus_bin" >/dev/null 2>&1 || true
|
||||
if command -v screen >/dev/null 2>&1; then
|
||||
if screen -list | grep -q "janus_gateway"; then
|
||||
screen -S janus_gateway -X quit || true
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
restart)
|
||||
pkill -f "$janus_bin" >/dev/null 2>&1 || true
|
||||
sleep 1
|
||||
if command -v screen >/dev/null 2>&1; then
|
||||
screen -fa -S janus_gateway -d -U -m "$janus_bin" -C "$janus_cfg"
|
||||
else
|
||||
nohup "$janus_bin" -C "$janus_cfg" >/tmp/janus.log 2>&1 &
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
die "Janus control not configured. Expected system service or janus.sh helper."
|
||||
}
|
||||
|
||||
require_ini() {
|
||||
local bin_dir="$1"
|
||||
local ini_file="$2"
|
||||
local label="$3"
|
||||
|
||||
if [[ ! -f "$bin_dir/$ini_file" ]]; then
|
||||
die "$label cannot start: missing $bin_dir/$ini_file — run the config action first"
|
||||
fi
|
||||
}
|
||||
|
||||
screen_start() {
|
||||
local screen_name="$1"
|
||||
local bin_dir="$2"
|
||||
local dll="$3"
|
||||
local pat="\\.${screen_name}[[:space:]]"
|
||||
|
||||
if screen -list 2>/dev/null | grep -qE "$pat"; then
|
||||
log INFO "Screen session '$screen_name' already running — skipping start"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Starting $screen_name from $bin_dir"
|
||||
(cd "$bin_dir" && screen -fa -S "$screen_name" -d -U -m dotnet "$dll")
|
||||
sleep 0.5
|
||||
|
||||
if screen -list 2>/dev/null | grep -qE "$pat"; then
|
||||
log INFO "Screen session '$screen_name' started successfully"
|
||||
else
|
||||
log ERROR "Screen session '$screen_name' did not stay alive — check logs or missing config"
|
||||
fi
|
||||
}
|
||||
|
||||
start_grid() {
|
||||
log INFO "Starting grid from $WORKDIR"
|
||||
|
||||
if [[ -d "$WORKDIR/robust/bin" ]]; then
|
||||
require_ini "$WORKDIR/robust/bin" "Robust.ini" "RobustServer"
|
||||
screen_start "robustserver" "$WORKDIR/robust/bin" "Robust.dll"
|
||||
fi
|
||||
|
||||
if [[ -f "$WORKDIR/robust/bin/MoneyServer.dll" && -f "$WORKDIR/robust/bin/MoneyServer.ini" ]]; then
|
||||
screen_start "moneyserver" "$WORKDIR/robust/bin" "MoneyServer.dll"
|
||||
fi
|
||||
|
||||
if [[ -d "$WORKDIR/sim1/bin" ]]; then
|
||||
require_ini "$WORKDIR/sim1/bin" "OpenSim.ini" "sim1"
|
||||
screen_start "sim1" "$WORKDIR/sim1/bin" "OpenSim.dll"
|
||||
fi
|
||||
}
|
||||
|
||||
stop_grid() {
|
||||
log INFO "Stopping grid"
|
||||
stop_screen_session "sim1" || true
|
||||
stop_screen_session "moneyserver" || true
|
||||
stop_screen_session "robustserver" || true
|
||||
}
|
||||
|
||||
restart_grid() {
|
||||
stop_grid
|
||||
sleep 5
|
||||
start_grid
|
||||
}
|
||||
|
||||
start_single() {
|
||||
local target="$1"
|
||||
case "$target" in
|
||||
robust)
|
||||
require_ini "$WORKDIR/robust/bin" "Robust.ini" "RobustServer"
|
||||
screen_start "robustserver" "$WORKDIR/robust/bin" "Robust.dll"
|
||||
;;
|
||||
sim1)
|
||||
require_ini "$WORKDIR/sim1/bin" "OpenSim.ini" "sim1"
|
||||
screen_start "sim1" "$WORKDIR/sim1/bin" "OpenSim.dll"
|
||||
;;
|
||||
standalone)
|
||||
require_ini "$WORKDIR/standalone/bin" "OpenSim.ini" "standalone"
|
||||
screen_start "standalone" "$WORKDIR/standalone/bin" "OpenSim.dll"
|
||||
;;
|
||||
janus)
|
||||
ensure_janus_ready
|
||||
janus_service_action start
|
||||
;;
|
||||
region)
|
||||
[[ -n "$NAME" ]] || die "--name is required for --target region"
|
||||
require_ini "$WORKDIR/${NAME}/bin" "OpenSim.ini" "$NAME"
|
||||
screen_start "$NAME" "$WORKDIR/${NAME}/bin" "OpenSim.dll"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported start target: $target"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
stop_single() {
|
||||
local target="$1"
|
||||
case "$target" in
|
||||
robust)
|
||||
stop_screen_session "robustserver"
|
||||
;;
|
||||
sim1)
|
||||
stop_screen_session "sim1"
|
||||
;;
|
||||
standalone)
|
||||
stop_screen_session "standalone"
|
||||
;;
|
||||
janus) janus_service_action stop ;;
|
||||
region)
|
||||
[[ -n "$NAME" ]] || die "--name is required for --target region"
|
||||
stop_screen_session "$NAME"
|
||||
;;
|
||||
*) die "Unsupported stop target: $target" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
TARGET=""
|
||||
ACTION=""
|
||||
NAME=""
|
||||
PROFILE="grid-sim"
|
||||
JANUS_PREFIX="${JANUS_PREFIX:-/opt/janus}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--janus-prefix) JANUS_PREFIX="$2"; shift 2 ;;
|
||||
--target) TARGET="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--name) NAME="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$TARGET" ]] || die "Missing --target"
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed startstop "$PROFILE" "$ACTION"
|
||||
ensure_profile_target_allowed "$PROFILE" "$TARGET"
|
||||
|
||||
if [[ "$TARGET" == "janus" && "$ACTION" != "stop" ]]; then
|
||||
ensure_janus_ready
|
||||
fi
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
if [[ "$TARGET" == "grid" ]]; then
|
||||
case "$ACTION" in
|
||||
start) start_grid ;;
|
||||
stop) stop_grid ;;
|
||||
restart) restart_grid ;;
|
||||
*) die "Unsupported action for grid: $ACTION" ;;
|
||||
esac
|
||||
else
|
||||
case "$ACTION" in
|
||||
start) start_single "$TARGET" ;;
|
||||
stop) stop_single "$TARGET" ;;
|
||||
restart)
|
||||
stop_single "$TARGET"
|
||||
sleep 3
|
||||
start_single "$TARGET"
|
||||
;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
fi
|
||||
@@ -0,0 +1,262 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./osmtool_core.sh
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_update.sh [--workdir <path>] --action <create-rollback|list-rollbacks|update-opensim|update-janus|full-update>
|
||||
[--opensim-dir <path>] [--opensim-repo <url>] [--opensim-branch <name>] [--repo-mode <update|fresh>]
|
||||
[--tsassets-dir <path>] [--currency-dir <path>] [--data-backup-dir <path>]
|
||||
[--deploy-binaries <true|false>] [--legacy-patch-dir <path>]
|
||||
[--janus-prefix <path>] [--janus-src <path>] [--public-host <host>] [--http-port <port>]
|
||||
[--admin-port <port>] [--rtp-range <from-to>] [--enable-admin <true|false>]
|
||||
[--api-secret <value>] [--admin-secret <value>] [--label <name>] [--dry-run <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_update.sh --action create-rollback --workdir /opt --label pre_update
|
||||
osmtool_update.sh --action update-opensim --workdir /opt --dry-run true
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
timestamp() {
|
||||
date '+%Y%m%d_%H%M%S'
|
||||
}
|
||||
|
||||
rollback_dir() {
|
||||
printf '%s' "$WORKDIR/rollback"
|
||||
}
|
||||
|
||||
ensure_rollback_dir() {
|
||||
local dir
|
||||
dir="$(rollback_dir)"
|
||||
|
||||
if mkdir -p "$dir" 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$dir"
|
||||
sudo chown "$(id -u):$(id -g)" "$dir"
|
||||
}
|
||||
|
||||
path_relative_to_root() {
|
||||
local path="$1"
|
||||
printf '%s' "${path#/}"
|
||||
}
|
||||
|
||||
append_snapshot_path() {
|
||||
local path="$1"
|
||||
|
||||
[[ -e "$path" ]] || return 0
|
||||
SNAPSHOT_PATHS+=("$(path_relative_to_root "$path")")
|
||||
}
|
||||
|
||||
build_opensim_snapshot_paths() {
|
||||
local sim_dir
|
||||
|
||||
SNAPSHOT_PATHS=()
|
||||
append_snapshot_path "$OPENSIM_DIR"
|
||||
append_snapshot_path "$WORKDIR/robust/bin"
|
||||
append_snapshot_path "$WORKDIR/standalone/bin"
|
||||
|
||||
shopt -s nullglob
|
||||
for sim_dir in "$WORKDIR"/sim*; do
|
||||
append_snapshot_path "$sim_dir/bin"
|
||||
done
|
||||
shopt -u nullglob
|
||||
}
|
||||
|
||||
build_janus_snapshot_paths() {
|
||||
SNAPSHOT_PATHS=()
|
||||
append_snapshot_path "$JANUS_PREFIX"
|
||||
append_snapshot_path "$JANUS_SRC"
|
||||
}
|
||||
|
||||
create_snapshot_archive() {
|
||||
local scope="$1"
|
||||
shift
|
||||
local archive_name archive_path manifest_path
|
||||
local -a paths=("$@")
|
||||
|
||||
ensure_rollback_dir
|
||||
|
||||
if [[ ${#paths[@]} -eq 0 ]]; then
|
||||
log WARN "No existing paths found for rollback scope: $scope"
|
||||
return 0
|
||||
fi
|
||||
|
||||
archive_name="${scope}_$(timestamp)"
|
||||
if [[ -n "$LABEL" ]]; then
|
||||
archive_name="${archive_name}_${LABEL}"
|
||||
fi
|
||||
|
||||
archive_path="$(rollback_dir)/${archive_name}.tar.gz"
|
||||
manifest_path="$(rollback_dir)/${archive_name}.manifest"
|
||||
|
||||
log INFO "Creating rollback archive: $archive_path"
|
||||
printf '%s\n' "${paths[@]}" > "$manifest_path"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
log INFO "[DRY-RUN] Would archive paths listed in: $manifest_path"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tar -czf "$archive_path" -C / "${paths[@]}"
|
||||
log INFO "Rollback archive created: $archive_path"
|
||||
log INFO "Rollback manifest created: $manifest_path"
|
||||
}
|
||||
|
||||
run_install_action() {
|
||||
local install_action="$1"
|
||||
local -a cmd
|
||||
|
||||
cmd=("$SCRIPT_DIR/osmtool_install.sh" --profile "$PROFILE" --workdir "$WORKDIR" --action "$install_action")
|
||||
|
||||
[[ -n "$OPENSIM_DIR" ]] && cmd+=(--opensim-dir "$OPENSIM_DIR")
|
||||
[[ -n "$OPENSIM_REPO" ]] && cmd+=(--opensim-repo "$OPENSIM_REPO")
|
||||
[[ -n "$OPENSIM_BRANCH" ]] && cmd+=(--opensim-branch "$OPENSIM_BRANCH")
|
||||
[[ -n "$REPO_MODE" ]] && cmd+=(--repo-mode "$REPO_MODE")
|
||||
[[ -n "$TSASSETS_DIR" ]] && cmd+=(--tsassets-dir "$TSASSETS_DIR")
|
||||
[[ -n "$CURRENCY_DIR" ]] && cmd+=(--currency-dir "$CURRENCY_DIR")
|
||||
[[ -n "$DATA_BACKUP_DIR" ]] && cmd+=(--data-backup-dir "$DATA_BACKUP_DIR")
|
||||
[[ -n "$DEPLOY_BINARIES" ]] && cmd+=(--deploy-binaries "$DEPLOY_BINARIES")
|
||||
[[ -n "$LEGACY_PATCH_DIR" ]] && cmd+=(--legacy-patch-dir "$LEGACY_PATCH_DIR")
|
||||
[[ -n "$JANUS_PREFIX" ]] && cmd+=(--janus-prefix "$JANUS_PREFIX")
|
||||
[[ -n "$JANUS_SRC" ]] && cmd+=(--janus-src "$JANUS_SRC")
|
||||
[[ -n "$PUBLIC_HOST" ]] && cmd+=(--public-host "$PUBLIC_HOST")
|
||||
[[ -n "$HTTP_PORT" ]] && cmd+=(--http-port "$HTTP_PORT")
|
||||
[[ -n "$ADMIN_PORT" ]] && cmd+=(--admin-port "$ADMIN_PORT")
|
||||
[[ -n "$RTP_RANGE" ]] && cmd+=(--rtp-range "$RTP_RANGE")
|
||||
[[ -n "$ENABLE_ADMIN" ]] && cmd+=(--enable-admin "$ENABLE_ADMIN")
|
||||
[[ -n "$API_SECRET" ]] && cmd+=(--api-secret "$API_SECRET")
|
||||
[[ -n "$ADMIN_SECRET" ]] && cmd+=(--admin-secret "$ADMIN_SECRET")
|
||||
|
||||
log INFO "Delegating update to install action: $install_action"
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
printf -v rendered '%q ' "${cmd[@]}"
|
||||
log INFO "[DRY-RUN] $rendered"
|
||||
return 0
|
||||
fi
|
||||
|
||||
"${cmd[@]}"
|
||||
}
|
||||
|
||||
create_rollback() {
|
||||
build_opensim_snapshot_paths
|
||||
create_snapshot_archive opensim "${SNAPSHOT_PATHS[@]}"
|
||||
build_janus_snapshot_paths
|
||||
create_snapshot_archive janus "${SNAPSHOT_PATHS[@]}"
|
||||
}
|
||||
|
||||
list_rollbacks() {
|
||||
local dir
|
||||
dir="$(rollback_dir)"
|
||||
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
log INFO "No rollback directory found: $dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
find "$dir" -maxdepth 1 -type f \( -name '*.tar.gz' -o -name '*.manifest' \) -printf '%T@ %p\n' 2>/dev/null | \
|
||||
sort -rn | cut -d' ' -f2-
|
||||
}
|
||||
|
||||
update_opensim() {
|
||||
build_opensim_snapshot_paths
|
||||
create_snapshot_archive opensim "${SNAPSHOT_PATHS[@]}"
|
||||
run_install_action install-opensim
|
||||
}
|
||||
|
||||
update_janus() {
|
||||
build_janus_snapshot_paths
|
||||
create_snapshot_archive janus "${SNAPSHOT_PATHS[@]}"
|
||||
run_install_action install-janus
|
||||
}
|
||||
|
||||
full_update() {
|
||||
update_opensim
|
||||
update_janus
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
ACTION=""
|
||||
PROFILE="grid-sim"
|
||||
OPENSIM_DIR=""
|
||||
OPENSIM_REPO=""
|
||||
OPENSIM_BRANCH=""
|
||||
REPO_MODE="update"
|
||||
TSASSETS_DIR=""
|
||||
CURRENCY_DIR=""
|
||||
DATA_BACKUP_DIR=""
|
||||
DEPLOY_BINARIES="true"
|
||||
LEGACY_PATCH_DIR=""
|
||||
JANUS_PREFIX=""
|
||||
JANUS_SRC=""
|
||||
PUBLIC_HOST=""
|
||||
HTTP_PORT=""
|
||||
ADMIN_PORT=""
|
||||
RTP_RANGE=""
|
||||
ENABLE_ADMIN=""
|
||||
API_SECRET=""
|
||||
ADMIN_SECRET=""
|
||||
LABEL=""
|
||||
DRY_RUN="false"
|
||||
SNAPSHOT_PATHS=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--workdir) WORKDIR="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--action) ACTION="$2"; shift 2 ;;
|
||||
--opensim-dir) OPENSIM_DIR="$2"; shift 2 ;;
|
||||
--opensim-repo) OPENSIM_REPO="$2"; shift 2 ;;
|
||||
--opensim-branch) OPENSIM_BRANCH="$2"; shift 2 ;;
|
||||
--repo-mode) REPO_MODE="$2"; shift 2 ;;
|
||||
--tsassets-dir) TSASSETS_DIR="$2"; shift 2 ;;
|
||||
--currency-dir) CURRENCY_DIR="$2"; shift 2 ;;
|
||||
--data-backup-dir) DATA_BACKUP_DIR="$2"; shift 2 ;;
|
||||
--deploy-binaries) DEPLOY_BINARIES="$2"; shift 2 ;;
|
||||
--legacy-patch-dir) LEGACY_PATCH_DIR="$2"; shift 2 ;;
|
||||
--janus-prefix) JANUS_PREFIX="$2"; shift 2 ;;
|
||||
--janus-src) JANUS_SRC="$2"; shift 2 ;;
|
||||
--public-host) PUBLIC_HOST="$2"; shift 2 ;;
|
||||
--http-port) HTTP_PORT="$2"; shift 2 ;;
|
||||
--admin-port) ADMIN_PORT="$2"; shift 2 ;;
|
||||
--rtp-range) RTP_RANGE="$2"; shift 2 ;;
|
||||
--enable-admin) ENABLE_ADMIN="$2"; shift 2 ;;
|
||||
--api-secret) API_SECRET="$2"; shift 2 ;;
|
||||
--admin-secret) ADMIN_SECRET="$2"; shift 2 ;;
|
||||
--label) LABEL="$2"; shift 2 ;;
|
||||
--dry-run) DRY_RUN="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$ACTION" ]] || die "Missing --action"
|
||||
validate_profile "$PROFILE"
|
||||
ensure_profile_action_allowed update "$PROFILE" "$ACTION"
|
||||
|
||||
case "$DRY_RUN" in
|
||||
true|false) ;;
|
||||
*) die "--dry-run must be true or false" ;;
|
||||
esac
|
||||
|
||||
OPENSIM_DIR="${OPENSIM_DIR:-$WORKDIR/opensim}"
|
||||
JANUS_PREFIX="${JANUS_PREFIX:-/opt/janus}"
|
||||
JANUS_SRC="${JANUS_SRC:-$WORKDIR/janus-gateway}"
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
create-rollback) create_rollback ;;
|
||||
list-rollbacks) list_rollbacks ;;
|
||||
update-opensim) update_opensim ;;
|
||||
update-janus) update_janus ;;
|
||||
full-update) full_update ;;
|
||||
*) die "Unsupported action: $ACTION" ;;
|
||||
esac
|
||||
+6700
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,632 @@
|
||||
[2026-04-01 10:10:40] [ERROR] ERR_TARGET_NOT_ALLOWED: profile=robust target=sim1
|
||||
[2026-04-01 10:10:40] [ERROR] ERR_TARGET_NOT_ALLOWED: profile=standalone target=grid
|
||||
[2026-04-01 10:10:40] [ERROR] ERR_ACTION_NOT_ALLOWED: module=backup profile=robust action=oar-backup
|
||||
[2026-04-01 10:11:16] [ERROR] Target not allowed for this profile␍: profile=robust target=sim1
|
||||
[2026-04-01 10:12:25] [ERROR] Janus binary missing: /opt/janus/bin/janus. Run install module action compile-janus/install-janus first.
|
||||
[2026-04-01 10:13:33] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:13:33] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:13:33] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:13:33] [INFO] Installing Janus build dependencies
|
||||
[2026-04-01 10:14:42] [INFO] Cloning Janus source to /opt/janus-gateway
|
||||
[2026-04-01 10:15:05] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:15:05] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:15:05] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:15:05] [INFO] Installing Janus build dependencies
|
||||
[2026-04-01 10:15:49] [INFO] Cloning Janus source to /home/manni/janus-gateway
|
||||
[2026-04-01 10:15:54] [INFO] Building Janus
|
||||
[2026-04-01 10:16:20] [INFO] Janus compiled and installed to /opt/janus
|
||||
[2026-04-01 10:17:02] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:17:02] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:17:02] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:17:41] [INFO] Using workdir: /home/manni
|
||||
[2026-04-01 10:17:41] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:17:41] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:18:19] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:18:19] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:18:19] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:18:29] [INFO] Janus configured. Marker created: /opt/janus/.osmtool_janus_ready
|
||||
[2026-04-01 10:18:39] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:18:39] [ERROR] Janus control not configured. Expected system service or janus.sh helper.
|
||||
[2026-04-01 10:18:40] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:18:40] [ERROR] Janus control not configured. Expected system service or janus.sh helper.
|
||||
[2026-04-01 10:19:10] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:19:10] [INFO] Janus already running
|
||||
[2026-04-01 10:19:11] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:19:18] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:19:43] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:19:43] [INFO] Janus already running
|
||||
[2026-04-01 10:19:43] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:19:55] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:19:55] [INFO] Janus already running
|
||||
[2026-04-01 10:19:55] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:20:05] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:20:41] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:24:45] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:24:45] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:24:45] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:24:45] [INFO] Running server readiness check
|
||||
[2026-04-01 10:24:45] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 10:24:45] [INFO] sudo available but password will be required
|
||||
[2026-04-01 10:24:45] [INFO] apt-get available
|
||||
[2026-04-01 10:24:45] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 10:24:45] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 10:24:45] [INFO] All required Janus build packages are installed
|
||||
[2026-04-01 10:24:45] [INFO] dotnet not found (required later for OpenSim runtime)
|
||||
[2026-04-01 10:24:45] [INFO] Server readiness check PASSED
|
||||
[2026-04-01 10:29:20] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:29:20] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:29:20] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:29:20] [INFO] Running server readiness check
|
||||
[2026-04-01 10:29:20] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 10:29:20] [INFO] sudo available but password will be required
|
||||
[2026-04-01 10:29:20] [INFO] apt-get available
|
||||
[2026-04-01 10:29:20] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 10:29:20] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 10:29:20] [INFO] All required Janus build packages are installed
|
||||
[2026-04-01 10:29:20] [ERROR] dotnet SDK 8.x missing (required for OpenSim build/runtime)
|
||||
[2026-04-01 10:29:20] [ERROR] Server readiness check FAILED
|
||||
[2026-04-01 10:38:11] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:38:11] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:38:11] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:38:11] [INFO] Running server readiness check
|
||||
[2026-04-01 10:38:11] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 10:38:11] [INFO] sudo available but password will be required
|
||||
[2026-04-01 10:38:11] [INFO] apt-get available
|
||||
[2026-04-01 10:38:12] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 10:38:12] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 10:38:12] [ERROR] Missing packages: zip screen libgdiplus
|
||||
[2026-04-01 10:38:12] [INFO] Run: sudo apt-get update && sudo apt-get install -y zip screen libgdiplus
|
||||
[2026-04-01 10:38:12] [ERROR] dotnet SDK 8.x missing (required for OpenSim build/runtime)
|
||||
[2026-04-01 10:38:12] [ERROR] Server readiness check FAILED
|
||||
[2026-04-01 10:39:56] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:39:56] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:39:56] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:39:56] [ERROR] No installable package found for token: zip
|
||||
[2026-04-01 10:40:15] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:40:15] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:40:15] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:40:15] [INFO] Installing OpenSim dependencies: zip screen libgdiplus libssl3 liblttng-ust1
|
||||
[2026-04-01 10:40:59] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:40:59] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:40:59] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:40:59] [INFO] Installing .NET SDK 8.0
|
||||
[2026-04-01 10:41:47] [INFO] Adding Microsoft package repository for Ubuntu 24.04
|
||||
[2026-04-01 10:42:05] [INFO] dotnet SDK 8.x installed successfully
|
||||
[2026-04-01 10:42:11] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:42:11] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:42:11] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:42:11] [INFO] Running server readiness check
|
||||
[2026-04-01 10:42:11] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 10:42:11] [INFO] sudo available but password will be required
|
||||
[2026-04-01 10:42:11] [INFO] apt-get available
|
||||
[2026-04-01 10:42:11] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 10:42:11] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 10:42:11] [INFO] All required Janus/OpenSim dependency packages are installed
|
||||
[2026-04-01 10:42:11] [INFO] dotnet SDK 8.x found
|
||||
[2026-04-01 10:42:11] [INFO] Server readiness check PASSED
|
||||
[2026-04-01 10:50:47] [ERROR] Server preinstallation missing. Run install action bootstrap-server first.
|
||||
[2026-04-01 10:50:47] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:50:47] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:50:47] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:50:47] [INFO] Starting central server bootstrap
|
||||
[2026-04-01 10:50:47] [INFO] Preparing Ubuntu server
|
||||
[2026-04-01 10:51:13] [INFO] Ubuntu base packages installed
|
||||
[2026-04-01 10:51:13] [INFO] Installing OpenSim dependencies: libssl3 liblttng-ust1
|
||||
[2026-04-01 10:51:14] [INFO] dotnet SDK 8.x already installed
|
||||
[2026-04-01 10:51:14] [INFO] Running server readiness check
|
||||
[2026-04-01 10:51:14] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 10:51:14] [INFO] sudo non-interactive check: OK
|
||||
[2026-04-01 10:51:14] [INFO] apt-get available
|
||||
[2026-04-01 10:51:14] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 10:51:14] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 10:51:15] [INFO] All required Janus/OpenSim dependency packages are installed
|
||||
[2026-04-01 10:51:15] [INFO] dotnet SDK 8.x found
|
||||
[2026-04-01 10:51:15] [INFO] Server readiness check PASSED
|
||||
[2026-04-01 10:51:15] [INFO] Server bootstrap marker created: /opt/.osmtool_server_prepared
|
||||
[2026-04-01 10:51:15] [INFO] Central server bootstrap completed
|
||||
[2026-04-01 10:57:07] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:57:07] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:57:07] [INFO] Repo mode: update
|
||||
[2026-04-01 10:57:07] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 10:57:07] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:57:07] [INFO] Starting OpenSim install/build flow
|
||||
[2026-04-01 10:57:07] [INFO] OpenSim repository: https://github.com/opensim/opensim.git
|
||||
[2026-04-01 10:57:07] [INFO] OpenSim branch: master
|
||||
[2026-04-01 10:57:07] [INFO] OpenSim directory: /opt/opensim
|
||||
[2026-04-01 10:57:07] [INFO] Cloning repository https://github.com/opensim/opensim.git -> /opt/opensim
|
||||
[2026-04-01 10:57:30] [INFO] Using workdir: /opt
|
||||
[2026-04-01 10:57:30] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 10:57:30] [INFO] Repo mode: update
|
||||
[2026-04-01 10:57:30] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 10:57:30] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 10:57:30] [INFO] Starting OpenSim install/build flow
|
||||
[2026-04-01 10:57:30] [INFO] OpenSim repository: https://github.com/opensim/opensim.git
|
||||
[2026-04-01 10:57:31] [INFO] OpenSim branch: master
|
||||
[2026-04-01 10:57:31] [INFO] OpenSim directory: /opt/opensim
|
||||
[2026-04-01 11:08:23] [INFO] Cloning repository https://github.com/opensim/opensim.git -> /opt/opensim
|
||||
[2026-04-01 11:09:12] [INFO] Preparing support repository: opensim-tsassets
|
||||
[2026-04-01 11:09:12] [INFO] Cloning repository https://github.com/ManfredAabye/opensim-tsassets.git -> /opt/opensim-tsassets
|
||||
[2026-04-01 11:09:44] [INFO] Using workdir: /opt
|
||||
[2026-04-01 11:09:44] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 11:09:44] [INFO] Repo mode: update
|
||||
[2026-04-01 11:09:44] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 11:09:44] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 11:09:44] [INFO] Starting OpenSim install/build flow
|
||||
[2026-04-01 11:09:44] [INFO] OpenSim repository: https://github.com/opensim/opensim.git
|
||||
[2026-04-01 11:09:44] [INFO] OpenSim branch: master
|
||||
[2026-04-01 11:09:44] [INFO] OpenSim directory: /opt/opensim
|
||||
[2026-04-01 11:09:44] [INFO] Updating repository: /opt/opensim
|
||||
[2026-04-01 11:09:46] [INFO] Preparing support repository: opensim-tsassets
|
||||
[2026-04-01 11:12:10] [INFO] Cloning repository https://github.com/ManfredAabye/opensim-tsassets.git -> /opt/opensim-tsassets
|
||||
[2026-04-01 11:12:10] [INFO] Preparing support repository: opensimcurrencyserver
|
||||
[2026-04-01 11:12:10] [INFO] Cloning repository https://github.com/ManfredAabye/opensimcurrencyserver-dotnet.git -> /opt/opensimcurrencyserver
|
||||
[2026-04-01 11:12:11] [INFO] Preparing support repository: os-data-backup
|
||||
[2026-04-01 11:12:11] [INFO] Cloning repository https://github.com/ManfredAabye/os-data-backup.git -> /opt/os-data-backup
|
||||
[2026-04-01 11:12:12] [INFO] Copied tsassets bin content: /opt/opensim-tsassets/bin -> /opt/opensim/bin
|
||||
[2026-04-01 11:12:12] [INFO] Copied tsassets OpenSim content: /opt/opensim-tsassets/OpenSim -> /opt/opensim/OpenSim
|
||||
[2026-04-01 11:12:12] [INFO] Copied currency addon modules: /opt/opensimcurrencyserver/addon-modules -> /opt/opensim/addon-modules
|
||||
[2026-04-01 11:12:12] [INFO] Copied currency bin content: /opt/opensimcurrencyserver/bin -> /opt/opensim/bin
|
||||
[2026-04-01 11:12:12] [INFO] Copied os-data-backup content: /opt/os-data-backup -> /opt/opensim/addon-modules/os-data-backup
|
||||
[2026-04-01 11:12:12] [INFO] Running OpenSim prebuild
|
||||
[2026-04-01 11:12:32] [INFO] Binary deployment skipped by configuration
|
||||
[2026-04-01 11:12:32] [INFO] OpenSim install/build flow completed
|
||||
[2026-04-01 11:53:03] [INFO] Using workdir: /opt
|
||||
[2026-04-01 11:53:03] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 11:53:03] [INFO] Repo mode: update
|
||||
[2026-04-01 11:53:03] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 11:53:03] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 11:53:03] [INFO] Starting OpenSim install/build flow
|
||||
[2026-04-01 11:53:03] [INFO] OpenSim repository: https://github.com/opensim/opensim.git
|
||||
[2026-04-01 11:53:03] [INFO] OpenSim branch: master
|
||||
[2026-04-01 11:53:03] [INFO] OpenSim directory: /opt/opensim
|
||||
[2026-04-01 11:53:03] [INFO] Updating repository: /opt/opensim
|
||||
[2026-04-01 11:53:04] [INFO] Preparing support repository: opensim-tsassets
|
||||
[2026-04-01 11:53:04] [INFO] Updating repository: /opt/opensim-tsassets
|
||||
[2026-04-01 11:53:05] [INFO] Preparing support repository: opensimcurrencyserver
|
||||
[2026-04-01 11:53:05] [INFO] Updating repository: /opt/opensimcurrencyserver
|
||||
[2026-04-01 11:53:06] [INFO] Preparing support repository: os-data-backup
|
||||
[2026-04-01 11:53:06] [INFO] Updating repository: /opt/os-data-backup
|
||||
[2026-04-01 11:53:07] [INFO] Copied tsassets bin content: /opt/opensim-tsassets/bin -> /opt/opensim/bin
|
||||
[2026-04-01 11:53:07] [INFO] Copied tsassets OpenSim content: /opt/opensim-tsassets/OpenSim -> /opt/opensim/OpenSim
|
||||
[2026-04-01 11:53:07] [INFO] Copied currency addon modules: /opt/opensimcurrencyserver/addon-modules -> /opt/opensim/addon-modules
|
||||
[2026-04-01 11:53:07] [INFO] Copied currency bin content: /opt/opensimcurrencyserver/bin -> /opt/opensim/bin
|
||||
[2026-04-01 11:55:36] [INFO] Using workdir: /opt
|
||||
[2026-04-01 11:55:36] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 11:55:36] [INFO] Repo mode: update
|
||||
[2026-04-01 11:55:36] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 11:55:36] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 11:55:36] [INFO] Starting OpenSim install/build flow
|
||||
[2026-04-01 11:55:36] [INFO] OpenSim repository: https://github.com/opensim/opensim.git
|
||||
[2026-04-01 11:55:36] [INFO] OpenSim branch: master
|
||||
[2026-04-01 11:55:36] [INFO] OpenSim directory: /opt/opensim
|
||||
[2026-04-01 11:55:36] [INFO] Updating repository: /opt/opensim
|
||||
[2026-04-01 11:55:37] [INFO] Preparing support repository: opensim-tsassets
|
||||
[2026-04-01 11:55:37] [INFO] Updating repository: /opt/opensim-tsassets
|
||||
[2026-04-01 11:55:38] [INFO] Preparing support repository: opensimcurrencyserver
|
||||
[2026-04-01 11:55:38] [INFO] Updating repository: /opt/opensimcurrencyserver
|
||||
[2026-04-01 11:55:38] [INFO] Preparing support repository: os-data-backup
|
||||
[2026-04-01 11:55:38] [INFO] Updating repository: /opt/os-data-backup
|
||||
[2026-04-01 11:55:39] [INFO] Copied tsassets bin content: /opt/opensim-tsassets/bin -> /opt/opensim/bin
|
||||
[2026-04-01 11:55:39] [INFO] Copied tsassets OpenSim content: /opt/opensim-tsassets/OpenSim -> /opt/opensim/OpenSim
|
||||
[2026-04-01 11:55:39] [INFO] Copied currency addon modules: /opt/opensimcurrencyserver/addon-modules -> /opt/opensim/addon-modules
|
||||
[2026-04-01 11:55:39] [INFO] Copied currency bin content: /opt/opensimcurrencyserver/bin -> /opt/opensim/bin
|
||||
[2026-04-01 11:55:39] [INFO] Copied os-data-backup content: /opt/os-data-backup -> /opt/opensim/addon-modules/os-data-backup
|
||||
[2026-04-01 11:55:39] [INFO] Running OpenSim prebuild
|
||||
[2026-04-01 11:55:59] [INFO] Copied robust binaries: /opt/opensim/bin -> /opt/robust/bin
|
||||
[2026-04-01 11:55:59] [INFO] Copied region binaries: /opt/opensim/bin -> /opt/sim1/bin
|
||||
[2026-04-01 11:55:59] [INFO] Copied region binaries: /opt/opensim/bin -> /opt/sim2/bin
|
||||
[2026-04-01 11:55:59] [INFO] OpenSim binaries deployed to available runtime directories
|
||||
[2026-04-01 11:55:59] [INFO] OpenSim install/build flow completed
|
||||
[2026-04-01 12:07:30] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:07:32] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:13:24] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:28:52] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:28:52] [ERROR] RobustServer cannot start: missing /opt/robust/bin/Robust.ini — run the config action first
|
||||
[2026-04-01 12:28:52] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:28:52] [ERROR] sim1 cannot start: missing /opt/sim1/bin/OpenSim.ini — run the config action first
|
||||
[2026-04-01 12:29:05] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:29:05] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 12:29:06] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 12:29:08] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:30:22] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:30:22] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 12:30:22] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 12:30:23] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:30:23] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 12:30:24] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:30:24] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 12:30:24] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:30:24] [ERROR] sim1 cannot start: missing /opt/sim1/bin/OpenSim.ini — run the config action first
|
||||
[2026-04-01 12:49:19] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:49:19] [ERROR] Missing required command: mysqldump
|
||||
[2026-04-01 12:49:31] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:49:31] [INFO] No OSMTool cron block configured
|
||||
[2026-04-01 12:49:32] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 12:49:32] [INFO] OSMTool cron block removed
|
||||
[2026-04-01 12:49:32] [INFO] No OSMTool cron block configured
|
||||
[2026-04-01 12:49:58] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:50:34] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:50:34] [INFO] Sending OAR export command to screen session 'sim1': save oar /opt/backup/sim1_20260401_125034.oar
|
||||
[2026-04-01 12:50:34] [INFO] OAR export command sent. Validate completion in the session log/output.
|
||||
[2026-04-01 12:52:12] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 12:52:13] [INFO] OSMTool cron block removed
|
||||
[2026-04-01 12:52:14] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 12:52:14] [INFO] Sending OAR export command to screen session 'sim1': save oar /opt/backup/sim1_20260401_125214.oar
|
||||
[2026-04-01 12:52:14] [INFO] OAR export command sent. Validate completion in the session log/output.
|
||||
[2026-04-01 13:01:08] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 13:01:08] [INFO] OSMTool cron block removed
|
||||
[2026-04-01 13:01:09] [INFO] Using workdir: /opt
|
||||
[2026-04-01 13:01:09] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 13:01:09] [INFO] Repo mode: update
|
||||
[2026-04-01 13:01:09] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 13:01:09] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 13:01:09] [INFO] Running server readiness check
|
||||
[2026-04-01 13:01:09] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 13:01:09] [INFO] sudo available but password will be required
|
||||
[2026-04-01 13:01:09] [INFO] apt-get available
|
||||
[2026-04-01 13:01:09] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 13:01:09] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 13:01:09] [INFO] All required Janus/OpenSim dependency packages are installed
|
||||
[2026-04-01 13:01:09] [INFO] dotnet SDK 8.x found
|
||||
[2026-04-01 13:01:09] [ERROR] mysqldump missing (MariaDB client tools are required)
|
||||
[2026-04-01 13:01:09] [ERROR] Server readiness check FAILED
|
||||
[2026-04-01 13:01:41] [INFO] Using workdir: /opt
|
||||
[2026-04-01 13:01:41] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 13:01:41] [INFO] Repo mode: update
|
||||
[2026-04-01 13:01:41] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 13:01:41] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 13:01:41] [INFO] Running server readiness check
|
||||
[2026-04-01 13:01:41] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 13:01:41] [INFO] sudo available but password will be required
|
||||
[2026-04-01 13:01:41] [INFO] apt-get available
|
||||
[2026-04-01 13:01:41] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 13:01:41] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 13:01:41] [INFO] All required Janus/OpenSim dependency packages are installed
|
||||
[2026-04-01 13:01:41] [INFO] dotnet SDK 8.x found
|
||||
[2026-04-01 13:01:41] [INFO] mysqldump found (MariaDB backup tooling ready)
|
||||
[2026-04-01 13:01:41] [INFO] Server readiness check PASSED
|
||||
[2026-04-01 13:04:31] [INFO] Using workdir: /opt
|
||||
[2026-04-01 13:04:31] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 13:04:31] [INFO] Repo mode: update
|
||||
[2026-04-01 13:04:31] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 13:04:31] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 13:04:31] [INFO] Configuring OpenSim runtime ini files
|
||||
[2026-04-01 13:04:31] [INFO] Keeping existing config: /opt/robust/bin/Robust.ini
|
||||
[2026-04-01 13:04:31] [INFO] Keeping existing config: /opt/robust/bin/Robust.ini
|
||||
[2026-04-01 13:04:31] [INFO] Created config from template: /opt/robust/bin/MoneyServer.ini
|
||||
[2026-04-01 13:04:31] [INFO] Created config from template: /opt/sim1/bin/OpenSim.ini
|
||||
[2026-04-01 13:04:31] [INFO] Created config from template: /opt/sim2/bin/OpenSim.ini
|
||||
[2026-04-01 13:04:31] [INFO] OpenSim runtime ini configuration completed
|
||||
[2026-04-01 13:04:37] [INFO] Using workdir: /opt
|
||||
[2026-04-01 13:04:37] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 13:04:37] [INFO] Repo mode: update
|
||||
[2026-04-01 13:04:37] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 13:04:37] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 13:04:37] [INFO] Starting central server bootstrap
|
||||
[2026-04-01 13:04:37] [INFO] Preparing Ubuntu server
|
||||
[2026-04-01 13:07:46] [INFO] Using workdir: /opt
|
||||
[2026-04-01 13:07:46] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 13:07:46] [INFO] Repo mode: update
|
||||
[2026-04-01 13:07:46] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 13:07:46] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 13:07:46] [INFO] Starting central server bootstrap
|
||||
[2026-04-01 13:07:46] [INFO] Preparing Ubuntu server
|
||||
[2026-04-01 13:07:50] [INFO] Ubuntu base packages installed
|
||||
[2026-04-01 13:07:51] [INFO] Installing OpenSim dependencies: mariadb-server libssl3 liblttng-ust1
|
||||
[2026-04-01 13:07:59] [INFO] dotnet SDK 8.x already installed
|
||||
[2026-04-01 13:07:59] [INFO] No controllable MariaDB service unit detected; skipping service activation
|
||||
[2026-04-01 13:07:59] [INFO] Running server readiness check
|
||||
[2026-04-01 13:07:59] [INFO] Detected OS: Ubuntu 24.04.4 LTS
|
||||
[2026-04-01 13:07:59] [INFO] sudo non-interactive check: OK
|
||||
[2026-04-01 13:07:59] [INFO] apt-get available
|
||||
[2026-04-01 13:08:00] [INFO] Network check to github.com: OK
|
||||
[2026-04-01 13:08:00] [INFO] Disk space in /opt is sufficient
|
||||
[2026-04-01 13:08:00] [INFO] All required Janus/OpenSim dependency packages are installed
|
||||
[2026-04-01 13:08:00] [INFO] dotnet SDK 8.x found
|
||||
[2026-04-01 13:08:00] [INFO] mysqldump found (MariaDB backup tooling ready)
|
||||
[2026-04-01 13:08:00] [INFO] Server readiness check PASSED
|
||||
[2026-04-01 13:08:00] [INFO] Server bootstrap marker created: /opt/.osmtool_server_prepared
|
||||
[2026-04-01 13:08:00] [INFO] Central server bootstrap completed
|
||||
[2026-04-01 15:41:57] [INFO] Using workdir: /opt
|
||||
[2026-04-01 15:41:57] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 15:41:57] [INFO] Repo mode: update
|
||||
[2026-04-01 15:41:57] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 15:41:57] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 15:41:57] [INFO] No controllable MariaDB service unit detected; skipping service activation
|
||||
[2026-04-01 15:41:57] [INFO] Configuring MariaDB databases and grants
|
||||
[2026-04-01 15:41:57] [INFO] Ensured database: robust
|
||||
[2026-04-01 15:41:57] [INFO] Ensured database: sim1
|
||||
[2026-04-01 15:41:57] [INFO] Ensured database: sim2
|
||||
[2026-04-01 15:41:57] [INFO] Database credentials written: /opt/UserInfo.ini
|
||||
[2026-04-01 15:41:57] [INFO] MariaDB database setup completed
|
||||
[2026-04-01 15:46:48] [INFO] Running health checks for profile: grid-sim
|
||||
[2026-04-01 15:46:48] [INFO] Using workdir: /opt
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Screen session missing: robustserver
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Screen session missing: sim1
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Port not listening: 8002
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Port not listening: 9000
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Port not listening: 9001
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Port not listening: 8088
|
||||
[2026-04-01 15:46:48] [INFO] [OK] Database reachable: robust
|
||||
[2026-04-01 15:46:48] [INFO] [OK] Log scan: /mnt/d/OpenSimBash/opensimMULTITOOLS-II/osmtool_backup.log -> 26 matches
|
||||
[2026-04-01 15:46:48] [INFO] [WARN] Log file not found, skipped: /opt/robust/bin/OpenSim.log
|
||||
[2026-04-01 15:46:48] [INFO] [OK] Log warning threshold OK: 26 <= 200
|
||||
[2026-04-01 15:46:48] [ERROR] [FAIL] Healthcheck FAILED with 2 failing check group(s)
|
||||
[2026-04-01 15:47:31] [INFO] Running health checks for profile: grid-sim
|
||||
[2026-04-01 15:47:31] [INFO] Using workdir: /opt
|
||||
[2026-04-01 15:47:31] [INFO] [WARN] Screen check skipped (no expected screens configured)
|
||||
[2026-04-01 15:47:31] [INFO] [WARN] Port check skipped (no ports configured)
|
||||
[2026-04-01 15:47:31] [INFO] [OK] Database reachable: robust
|
||||
[2026-04-01 15:47:31] [INFO] [OK] Log scan: /mnt/d/OpenSimBash/opensimMULTITOOLS-II/osmtool_backup.log -> 31 matches
|
||||
[2026-04-01 15:47:31] [INFO] [WARN] Log file not found, skipped: /opt/robust/bin/OpenSim.log
|
||||
[2026-04-01 15:47:31] [INFO] [OK] Log warning threshold OK: 31 <= 200
|
||||
[2026-04-01 15:47:31] [INFO] [OK] Healthcheck PASSED
|
||||
[2026-04-01 15:47:56] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 15:47:56] [INFO] Dry-run mode: true
|
||||
[2026-04-01 15:47:56] [INFO] Cleaning log files under /opt/opensim
|
||||
[2026-04-01 15:48:14] [ERROR] Refusing cleanup on /opt root; choose a dedicated OpenSim workdir
|
||||
[2026-04-01 16:31:39] [ERROR] Unknown option: --module
|
||||
[2026-04-01 16:31:45] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:31:45] [INFO] SQL Backups:
|
||||
[2026-04-01 16:31:45] [INFO] OAR Backups:
|
||||
[2026-04-01 16:31:50] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:31:50] [INFO] SQL Backups:
|
||||
[2026-04-01 16:31:50] [INFO] OAR Backups:
|
||||
[2026-04-01 16:31:55] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:31:55] [ERROR] SQL backup file not found: /tmp/test.sql
|
||||
[2026-04-01 16:32:02] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:32:02] [INFO] Database restore command:
|
||||
[2026-04-01 16:32:02] [INFO] mysql -u'root' -p'test' 'robust' < '/tmp/test.sql'
|
||||
[2026-04-01 16:32:02] [INFO] [DRY-RUN] Not executing database restore
|
||||
[2026-04-01 16:32:09] [ERROR] Aktion fuer dieses Profil nicht erlaubt␍: module=restore profile=robust action=oar-restore
|
||||
[2026-04-01 16:57:43] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:57:43] [INFO] Creating rollback archive: /tmp/osm_update_test/rollback/opensim_20260401_165743_smoke.tar.gz
|
||||
[2026-04-01 16:57:43] [INFO] [DRY-RUN] Would archive paths listed in: /tmp/osm_update_test/rollback/opensim_20260401_165743_smoke.manifest
|
||||
[2026-04-01 16:57:43] [INFO] Creating rollback archive: /tmp/osm_update_test/rollback/janus_20260401_165743_smoke.tar.gz
|
||||
[2026-04-01 16:57:43] [INFO] [DRY-RUN] Would archive paths listed in: /tmp/osm_update_test/rollback/janus_20260401_165743_smoke.manifest
|
||||
[2026-04-01 16:57:43] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:57:43] [INFO] Validating INI file: /tmp/osm_update_test/robust/bin/Robust.ini
|
||||
[2026-04-01 16:57:43] [INFO] Validating INI file: /tmp/osm_update_test/sim1/bin/OpenSim.ini
|
||||
[2026-04-01 16:57:43] [INFO] Configuration validation passed
|
||||
[2026-04-01 16:57:53] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:57:53] [INFO] Creating rollback archive: /tmp/osm_update_test/rollback/opensim_20260401_165753_smoke.tar.gz
|
||||
[2026-04-01 16:57:53] [INFO] [DRY-RUN] Would archive paths listed in: /tmp/osm_update_test/rollback/opensim_20260401_165753_smoke.manifest
|
||||
[2026-04-01 16:57:53] [INFO] Delegating update to install action: install-opensim
|
||||
[2026-04-01 16:57:53] [INFO] [DRY-RUN] /mnt/d/OpenSimBash/opensimMULTITOOLS-II/modular/osmtool_install.sh --profile grid-sim --workdir /tmp/osm_update_test --action install-opensim --opensim-dir /tmp/osm_update_test/opensim --repo-mode update --deploy-binaries true --janus-prefix /opt/janus --janus-src /tmp/osm_update_test/janus-gateway
|
||||
[2026-04-01 16:57:54] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:57:54] [INFO] Validating INI file: /tmp/test_invalid.ini
|
||||
[2026-04-01 16:57:54] [ERROR] Invalid INI syntax in /tmp/test_invalid.ini:2 -> this is broken
|
||||
[2026-04-01 16:57:54] [ERROR] Configuration validation failed with 1 issue(s)
|
||||
[2026-04-01 16:58:09] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:58:09] [INFO] Validating JSON file: /tmp/test_valid.json
|
||||
[2026-04-01 16:58:09] [INFO] Configuration validation passed
|
||||
[2026-04-01 16:58:09] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:58:46] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:58:46] [INFO] Validating INI file: /tmp/osm_config_missing/robust/bin/Robust.ini
|
||||
[2026-04-01 16:58:46] [ERROR] No region runtime configs found under /tmp/osm_config_missing/sim*/bin/OpenSim.ini
|
||||
[2026-04-01 16:58:46] [ERROR] Configuration validation failed with 1 issue(s)
|
||||
[2026-04-01 16:58:47] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:58:47] [ERROR] Missing config file: /tmp/osm_update_test/robust/bin/Robust.ini
|
||||
[2026-04-01 16:59:00] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 16:59:00] [INFO] Validating INI file: /tmp/osm_update_test/robust/bin/Robust.ini
|
||||
[2026-04-01 16:59:00] [INFO] Validating INI file: /tmp/osm_update_test/sim1/bin/OpenSim.ini
|
||||
[2026-04-01 16:59:00] [INFO] Configuration validation passed
|
||||
[2026-04-01 17:17:00] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:17:18] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:17:38] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:17:38] [INFO] Validating INI file: /opt/robust/bin/Robust.ini
|
||||
[2026-04-01 17:17:39] [INFO] Validating INI file: /opt/sim1/bin/OpenSim.ini
|
||||
[2026-04-01 17:17:39] [INFO] Validating INI file: /opt/sim2/bin/OpenSim.ini
|
||||
[2026-04-01 17:17:40] [INFO] Configuration validation passed
|
||||
[2026-04-01 17:18:14] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:18:15] [INFO] Creating rollback archive: /opt/rollback/opensim_20260401_171814_realcheck.tar.gz
|
||||
[2026-04-01 17:18:15] [INFO] [DRY-RUN] Would archive paths listed in: /opt/rollback/opensim_20260401_171814_realcheck.manifest
|
||||
[2026-04-01 17:18:15] [INFO] Creating rollback archive: /opt/rollback/janus_20260401_171815_realcheck.tar.gz
|
||||
[2026-04-01 17:18:15] [INFO] [DRY-RUN] Would archive paths listed in: /opt/rollback/janus_20260401_171815_realcheck.manifest
|
||||
[2026-04-01 17:18:15] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:18:15] [INFO] Creating rollback archive: /opt/rollback/opensim_20260401_171815_realcheck.tar.gz
|
||||
[2026-04-01 17:18:15] [INFO] [DRY-RUN] Would archive paths listed in: /opt/rollback/opensim_20260401_171815_realcheck.manifest
|
||||
[2026-04-01 17:18:15] [INFO] Delegating update to install action: install-opensim
|
||||
[2026-04-01 17:18:15] [INFO] [DRY-RUN] /mnt/d/OpenSimBash/opensimMULTITOOLS-II/modular/osmtool_install.sh --profile grid-sim --workdir /opt --action install-opensim --opensim-dir /opt/opensim --repo-mode update --deploy-binaries true --janus-prefix /opt/janus --janus-src /opt/janus-gateway
|
||||
[2026-04-01 17:18:15] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:18:15] [INFO] Creating rollback archive: /opt/rollback/janus_20260401_171815_realcheck.tar.gz
|
||||
[2026-04-01 17:18:15] [INFO] [DRY-RUN] Would archive paths listed in: /opt/rollback/janus_20260401_171815_realcheck.manifest
|
||||
[2026-04-01 17:18:15] [INFO] Delegating update to install action: install-janus
|
||||
[2026-04-01 17:18:15] [INFO] [DRY-RUN] /mnt/d/OpenSimBash/opensimMULTITOOLS-II/modular/osmtool_install.sh --profile grid-sim --workdir /opt --action install-janus --opensim-dir /opt/opensim --repo-mode update --deploy-binaries true --janus-prefix /opt/janus --janus-src /opt/janus-gateway
|
||||
[2026-04-01 17:18:22] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:22:54] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:22:54] [INFO] Report generated: /opt/reports/osm_report_20260401_172254.txt
|
||||
[2026-04-01 17:25:10] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 17:25:10] [INFO] OSMTool cron block removed
|
||||
[2026-04-01 17:25:59] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 17:26:06] [INFO] OSMTool cron block removed
|
||||
[2026-04-01 17:27:28] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:27:28] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:27:28] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:27:28] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:27:28] [INFO] Starting moneyserver from /opt/robust/bin
|
||||
[2026-04-01 17:27:29] [INFO] Screen session 'moneyserver' started successfully
|
||||
[2026-04-01 17:27:29] [INFO] Starting sim1 from /opt/sim1/bin
|
||||
[2026-04-01 17:27:30] [ERROR] Screen session 'sim1' did not stay alive — check logs or missing config
|
||||
[2026-04-01 17:27:32] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:27:32] [INFO] Stopping grid
|
||||
[2026-04-01 17:27:32] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:27:37] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:27:37] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:27:38] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:27:38] [INFO] Starting moneyserver from /opt/robust/bin
|
||||
[2026-04-01 17:27:38] [ERROR] Screen session 'moneyserver' did not stay alive — check logs or missing config
|
||||
[2026-04-01 17:27:38] [INFO] Starting sim1 from /opt/sim1/bin
|
||||
[2026-04-01 17:27:39] [ERROR] Screen session 'sim1' did not stay alive — check logs or missing config
|
||||
[2026-04-01 17:27:41] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:27:41] [INFO] Stopping grid
|
||||
[2026-04-01 17:27:41] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:27:55] [INFO] Using profile: robust
|
||||
[2026-04-01 17:27:55] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:27:56] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:27:58] [INFO] Using profile: robust
|
||||
[2026-04-01 17:27:58] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:28:00] [ERROR] Ziel fuer dieses Profil nicht erlaubt␍: profile=robust target=sim1
|
||||
[2026-04-01 17:28:32] [INFO] Using profile: standalone
|
||||
[2026-04-01 17:28:32] [ERROR] standalone cannot start: missing /opt/standalone/bin/OpenSim.ini — run the config action first
|
||||
[2026-04-01 17:28:32] [INFO] Using profile: standalone
|
||||
[2026-04-01 17:28:32] [INFO] standalone is not running
|
||||
[2026-04-01 17:28:33] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:28:33] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:29:46] [INFO] Using profile: standalone
|
||||
[2026-04-01 17:29:46] [ERROR] standalone cannot start: missing /opt/standalone/bin/OpenSim.ini — run the config action first
|
||||
[2026-04-01 17:29:46] [ERROR] Ziel fuer dieses Profil nicht erlaubt␍: profile=robust target=sim1
|
||||
[2026-04-01 17:30:35] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:30:35] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:30:35] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:30:35] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:30:35] [INFO] Starting moneyserver from /opt/robust/bin
|
||||
[2026-04-01 17:30:36] [INFO] Screen session 'moneyserver' started successfully
|
||||
[2026-04-01 17:30:36] [INFO] Starting sim1 from /opt/sim1/bin
|
||||
[2026-04-01 17:30:36] [ERROR] Screen session 'sim1' did not stay alive — check logs or missing config
|
||||
[2026-04-01 17:31:16] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:31:16] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:31:16] [INFO] Screen session 'robustserver' already running — skipping start
|
||||
[2026-04-01 17:31:16] [INFO] Screen session 'moneyserver' already running — skipping start
|
||||
[2026-04-01 17:31:16] [INFO] Starting sim1 from /opt/sim1/bin
|
||||
[2026-04-01 17:31:16] [INFO] Screen session 'sim1' started successfully
|
||||
[2026-04-01 17:31:20] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:31:20] [INFO] Stopping grid
|
||||
[2026-04-01 17:31:20] [INFO] Sent shutdown to sim1
|
||||
[2026-04-01 17:31:20] [INFO] Sent shutdown to moneyserver
|
||||
[2026-04-01 17:31:20] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:32:50] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:32:50] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:32:50] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:32:50] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:32:50] [INFO] Starting moneyserver from /opt/robust/bin
|
||||
[2026-04-01 17:32:51] [INFO] Screen session 'moneyserver' started successfully
|
||||
[2026-04-01 17:32:51] [INFO] Screen session 'sim1' already running — skipping start
|
||||
[2026-04-01 17:32:54] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:32:54] [INFO] Stopping grid
|
||||
[2026-04-01 17:32:54] [INFO] Sent shutdown to sim1
|
||||
[2026-04-01 17:33:00] [INFO] Session 'sim1' still running after shutdown; forcing screen quit
|
||||
[2026-04-01 17:33:01] [INFO] Screen session 'sim1' stopped
|
||||
[2026-04-01 17:33:01] [INFO] Sent shutdown to moneyserver
|
||||
[2026-04-01 17:33:07] [INFO] Screen session 'moneyserver' stopped
|
||||
[2026-04-01 17:33:07] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:33:13] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:33:28] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:33:28] [INFO] Janus already running
|
||||
[2026-04-01 17:33:30] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:33:40] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:33:40] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:34:46] [INFO] Using workdir: /opt
|
||||
[2026-04-01 17:34:46] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:34:46] [INFO] Repo mode: update
|
||||
[2026-04-01 17:34:46] [INFO] OpenSim dir: /opt/opensim
|
||||
[2026-04-01 17:34:46] [INFO] Janus prefix: /opt/janus
|
||||
[2026-04-01 17:34:46] [INFO] Configuring OpenSim runtime ini files
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/robust/bin/Robust.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/robust/bin/Robust.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/robust/bin/MoneyServer.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/robust/bin/config-include/GridCommon.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/robust/bin/config-include/osslEnable.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/sim1/bin/OpenSim.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/sim1/bin/config-include/GridCommon.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/sim1/bin/config-include/osslEnable.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/sim2/bin/OpenSim.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/sim2/bin/config-include/GridCommon.ini
|
||||
[2026-04-01 17:34:46] [INFO] Keeping existing config: /opt/sim2/bin/config-include/osslEnable.ini
|
||||
[2026-04-01 17:34:47] [INFO] Updated MoneyServer.ini database credentials from configured values
|
||||
[2026-04-01 17:34:47] [INFO] OpenSim runtime ini configuration completed
|
||||
[2026-04-01 17:38:33] [INFO] [SMOKE] profile=grid-sim target=grid workdir=/opt
|
||||
[2026-04-01 17:38:33] [INFO] [SMOKE] expected_screens=robustserver,sim1
|
||||
[2026-04-01 17:38:33] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:38:33] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:38:33] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:38:34] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:38:34] [INFO] Starting moneyserver from /opt/robust/bin
|
||||
[2026-04-01 17:38:34] [INFO] Screen session 'moneyserver' started successfully
|
||||
[2026-04-01 17:38:34] [INFO] Starting sim1 from /opt/sim1/bin
|
||||
[2026-04-01 17:38:35] [INFO] Screen session 'sim1' started successfully
|
||||
[2026-04-01 17:38:38] [INFO] [SMOKE][OK] screen up: robustserver
|
||||
[2026-04-01 17:38:38] [INFO] [SMOKE][OK] screen up: sim1
|
||||
[2026-04-01 17:38:38] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:38:38] [INFO] Stopping grid
|
||||
[2026-04-01 17:38:38] [INFO] Sent shutdown to sim1
|
||||
[2026-04-01 17:38:44] [INFO] Session 'sim1' still running after shutdown; forcing screen quit
|
||||
[2026-04-01 17:38:45] [INFO] Screen session 'sim1' stopped
|
||||
[2026-04-01 17:38:45] [INFO] Sent shutdown to moneyserver
|
||||
[2026-04-01 17:38:51] [INFO] Screen session 'moneyserver' stopped
|
||||
[2026-04-01 17:38:51] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:38:57] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:39:02] [INFO] Starting grid from /opt
|
||||
[2026-04-01 17:39:02] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:39:03] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:39:03] [INFO] Starting moneyserver from /opt/robust/bin
|
||||
[2026-04-01 17:39:03] [INFO] Screen session 'moneyserver' started successfully
|
||||
[2026-04-01 17:39:03] [INFO] Starting sim1 from /opt/sim1/bin
|
||||
[2026-04-01 17:39:04] [INFO] Screen session 'sim1' started successfully
|
||||
[2026-04-01 17:39:07] [INFO] [SMOKE][OK] screen up: robustserver
|
||||
[2026-04-01 17:39:07] [INFO] [SMOKE][OK] screen up: sim1
|
||||
[2026-04-01 17:39:07] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:39:07] [INFO] Stopping grid
|
||||
[2026-04-01 17:39:07] [INFO] Sent shutdown to sim1
|
||||
[2026-04-01 17:39:13] [INFO] Session 'sim1' still running after shutdown; forcing screen quit
|
||||
[2026-04-01 17:39:14] [INFO] Screen session 'sim1' stopped
|
||||
[2026-04-01 17:39:14] [INFO] Sent shutdown to moneyserver
|
||||
[2026-04-01 17:39:20] [INFO] Screen session 'moneyserver' stopped
|
||||
[2026-04-01 17:39:20] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:39:26] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:39:34] [INFO] [SMOKE][OK] screen down: robustserver
|
||||
[2026-04-01 17:39:34] [INFO] [SMOKE][OK] screen down: sim1
|
||||
[2026-04-01 17:39:34] [INFO] [SMOKE][PASS] Start/Restart/Stop smoke test successful
|
||||
[2026-04-01 17:39:35] [INFO] [SMOKE] profile=robust target=robust workdir=/opt
|
||||
[2026-04-01 17:39:35] [INFO] [SMOKE] expected_screens=robustserver
|
||||
[2026-04-01 17:39:35] [INFO] Using profile: robust
|
||||
[2026-04-01 17:39:35] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:39:35] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:39:37] [INFO] [SMOKE][OK] screen up: robustserver
|
||||
[2026-04-01 17:39:37] [INFO] Using profile: robust
|
||||
[2026-04-01 17:39:37] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:39:43] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:39:46] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:39:47] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:39:49] [INFO] [SMOKE][OK] screen up: robustserver
|
||||
[2026-04-01 17:39:49] [INFO] Using profile: robust
|
||||
[2026-04-01 17:39:49] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:39:57] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:40:03] [INFO] [SMOKE][OK] screen down: robustserver
|
||||
[2026-04-01 17:40:03] [INFO] [SMOKE][PASS] Start/Restart/Stop smoke test successful
|
||||
[2026-04-01 17:43:37] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 17:43:37] [INFO] OSMTool cron block removed
|
||||
[2026-04-01 17:47:28] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:47:28] [INFO] [SMOKE] profile=robust target=robust workdir=/opt
|
||||
[2026-04-01 17:47:28] [INFO] [SMOKE] expected_screens=robustserver
|
||||
[2026-04-01 17:47:29] [INFO] Using profile: robust
|
||||
[2026-04-01 17:47:29] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:47:29] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:47:32] [INFO] [SMOKE][OK] screen up: robustserver
|
||||
[2026-04-01 17:47:32] [INFO] Using profile: robust
|
||||
[2026-04-01 17:47:32] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:47:38] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:47:41] [INFO] Starting robustserver from /opt/robust/bin
|
||||
[2026-04-01 17:47:42] [INFO] Screen session 'robustserver' started successfully
|
||||
[2026-04-01 17:47:45] [INFO] [SMOKE][OK] screen up: robustserver
|
||||
[2026-04-01 17:47:45] [INFO] Using profile: robust
|
||||
[2026-04-01 17:47:45] [INFO] Sent shutdown to robustserver
|
||||
[2026-04-01 17:47:51] [INFO] Screen session 'robustserver' stopped
|
||||
[2026-04-01 17:47:59] [INFO] [SMOKE][OK] screen down: robustserver
|
||||
[2026-04-01 17:47:59] [INFO] [SMOKE][PASS] Start/Restart/Stop smoke test successful
|
||||
[2026-04-01 17:47:59] [INFO] Running health checks for profile: grid-sim
|
||||
[2026-04-01 17:47:59] [INFO] Using workdir: /opt
|
||||
[2026-04-01 17:47:59] [INFO] [WARN] Screen check skipped (no expected screens configured)
|
||||
[2026-04-01 17:47:59] [INFO] [WARN] Port check skipped (no ports configured)
|
||||
[2026-04-01 17:47:59] [INFO] [OK] Database reachable: robust
|
||||
[2026-04-01 17:47:59] [INFO] [OK] Log scan: /mnt/d/OpenSimBash/opensimMULTITOOLS-II/osmtool_backup.log -> 52 matches
|
||||
[2026-04-01 17:47:59] [INFO] [WARN] Log file not found, skipped: /opt/robust/bin/OpenSim.log
|
||||
[2026-04-01 17:47:59] [ERROR] [FAIL] Log warning threshold exceeded: 52 > 50
|
||||
[2026-04-01 17:47:59] [ERROR] [FAIL] Healthcheck FAILED with 1 failing check group(s)
|
||||
[2026-04-01 17:47:59] [INFO] Using profile: grid-sim
|
||||
[2026-04-01 17:47:59] [INFO] Validating INI file: /opt/robust/bin/Robust.ini
|
||||
[2026-04-01 17:48:00] [INFO] Validating INI file: /opt/sim1/bin/OpenSim.ini
|
||||
[2026-04-01 17:48:00] [INFO] Validating INI file: /opt/sim2/bin/OpenSim.ini
|
||||
[2026-04-01 17:48:01] [INFO] Configuration validation passed
|
||||
[2026-04-01 17:56:29] [INFO] OSMTool cron jobs installed/updated
|
||||
[2026-04-01 17:56:37] [INFO] OSMTool cron jobs installed/updated
|
||||
@@ -0,0 +1,718 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Backup Version 1.0
|
||||
|
||||
STARTVERZEICHNIS="/opt" # Startverzeichnis
|
||||
ROBUSTVERZEICHNIS="Robust" # Robust Verzeichnis
|
||||
REGIONSDATEI="osmregionlist.ini" # Regionsdatei
|
||||
SIMDATEI="osmsimlist.ini" # Simulationsdatei
|
||||
BACKUPWARTEZEIT=60 # Wartezeit in Sekunden zwischen den Backups
|
||||
|
||||
KOMMANDO=$1
|
||||
|
||||
#──────────────────────────────────────────────────────────────────────────────────────────
|
||||
#* Informationen
|
||||
#──────────────────────────────────────────────────────────────────────────────────────────
|
||||
#
|
||||
|
||||
## * makeverzeichnisliste
|
||||
# Eine Funktion zum Erstellen einer Liste von Verzeichnissen aus einer Datei.
|
||||
#? Verwendung: makeverzeichnisliste
|
||||
# Diese Funktion liest Zeilen aus der angegebenen SIMDATEI im STARTVERZEICHNIS und erstellt eine
|
||||
# Liste von Verzeichnissen. Die Liste wird in der globalen Variable VERZEICHNISSLISTE gespeichert.
|
||||
# Die Anzahl der Einträge in der Liste wird in der globalen Variable ANZAHLVERZEICHNISSLISTE gespeichert.
|
||||
#? Argumente:
|
||||
# STARTVERZEICHNIS - Das Verzeichnis, in dem sich die SIMDATEI befindet.
|
||||
# SIMDATEI - Die Datei, aus der die Verzeichnisse gelesen werden sollen.
|
||||
#? Beispielaufruf
|
||||
# makeverzeichnisliste
|
||||
##
|
||||
function makeverzeichnisliste() {
|
||||
# Letzte Bearbeitung 27.09.2023
|
||||
|
||||
# Initialisieren der Verzeichnisliste
|
||||
VERZEICHNISSLISTE=()
|
||||
|
||||
# Schleife zum Lesen der Zeilen aus der SIMDATEI und Hinzufügen zum Array
|
||||
while IFS= read -r line; do
|
||||
VERZEICHNISSLISTE+=("$line")
|
||||
done </$STARTVERZEICHNIS/$SIMDATEI
|
||||
|
||||
# Anzahl der Einträge in der Verzeichnisliste
|
||||
ANZAHLVERZEICHNISSLISTE=${#VERZEICHNISSLISTE[*]}
|
||||
|
||||
# Erfolgreiche Ausführung
|
||||
return 0
|
||||
}
|
||||
|
||||
## * makeregionsliste
|
||||
# Eine Funktion zum Erstellen einer Liste von Regionen aus einer Datei.
|
||||
#? Verwendung: makeregionsliste
|
||||
# Diese Funktion liest Zeilen aus der angegebenen REGIONSDATEI im STARTVERZEICHNIS und erstellt eine
|
||||
# Liste von Regionen. Die Liste wird in der globalen Variable REGIONSLISTE gespeichert.
|
||||
# Die Anzahl der Einträge in der Liste wird in der globalen Variable ANZAHLREGIONSLISTE gespeichert.
|
||||
#? Argumente:
|
||||
# STARTVERZEICHNIS - Das Verzeichnis, in dem sich die REGIONSDATEI befindet.
|
||||
# REGIONSDATEI - Die Datei, aus der die Regionen gelesen werden sollen.
|
||||
#? Beispiel:
|
||||
# makeregionsliste
|
||||
##
|
||||
function makeregionsliste() {
|
||||
# Letzte Bearbeitung 27.09.2023
|
||||
|
||||
# Initialisieren der Regionenliste
|
||||
REGIONSLISTE=()
|
||||
|
||||
# Schleife zum Lesen der Zeilen aus der REGIONSDATEI und Hinzufügen zum Array
|
||||
while IFS= read -r line; do
|
||||
REGIONSLISTE+=("$line")
|
||||
done </$STARTVERZEICHNIS/$REGIONSDATEI
|
||||
|
||||
# Anzahl der Einträge in der Regionenliste
|
||||
ANZAHLREGIONSLISTE=${#REGIONSLISTE[*]} # Anzahl der Eintraege.
|
||||
|
||||
# Erfolgreiche Ausführung
|
||||
return 0
|
||||
}
|
||||
|
||||
## * regionsiniteilen
|
||||
# Diese Funktion nimmt drei Argumente entgegen: das Verzeichnis, aus dem die Werte gelesen werden sollen ($INIVERZEICHNIS),
|
||||
# den Namen der Region, für die die Werte gespeichert werden sollen ($RTREGIONSNAME), und den Pfad zur Haupt-Regions.ini-Datei
|
||||
# ($INI_FILE). Die Funktion überprüft, ob die Haupt-Regions.ini-Datei vorhanden ist, und wenn nicht, werden die Werte für die
|
||||
# angegebene Region in eine separate INI-Datei geschrieben.
|
||||
#? Parameter:
|
||||
# - $1: Das Verzeichnis, aus dem die Werte gelesen werden sollen.
|
||||
# - $2: Der Name der Region, für die die Werte gespeichert werden sollen.
|
||||
# - $3: Der Pfad zur Haupt-Regions.ini-Datei.
|
||||
#? Rückgabewert:
|
||||
# - 0: Erfolgreiche Ausführung der Funktion
|
||||
#? Verwendungsbeispiel:
|
||||
# regionsiniteilen "MeinVerzeichnis" "MeineRegion" "/MeinVerzeichnis/bin/Regions/Regions.ini"
|
||||
##
|
||||
function regionsiniteilen() {
|
||||
# Letzte Bearbeitung 01.10.2023
|
||||
INIVERZEICHNIS=$1 # Auszulesendes Verzeichnis
|
||||
RTREGIONSNAME=$2 # Auszulesende Region
|
||||
INI_FILE="/$STARTVERZEICHNIS/$INIVERZEICHNIS/bin/Regions/Regions.ini" # Auszulesende Datei
|
||||
|
||||
if [ ! -d "$INI_FILE" ]; then
|
||||
echo info "REGIONSINITEILEN: Schreiben der Werte fuer $RTREGIONSNAME"
|
||||
# Schreiben der einzelnen Punkte nur wenn vorhanden ist.
|
||||
# shellcheck disable=SC2005
|
||||
{
|
||||
echo "[$RTREGIONSNAME]"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "RegionUUID")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "Location")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "SizeX")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "SizeY")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "SizeZ")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "InternalAddress")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "InternalPort")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "AllowAlternatePorts")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "ResolveAddress")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "ExternalHostName")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MaxPrims")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MaxAgents")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "DefaultLanding")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "NonPhysicalPrimMax")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "PhysicalPrimMax")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "ClampPrimSize")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MaxPrimsPerUser")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "ScopeID")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "RegionType")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MaptileStaticUUID")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MaptileStaticFile")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MasterAvatarFirstName")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MasterAvatarLastName")"
|
||||
echo "$(get_value_from_Region_key "${INI_FILE}" "$RTREGIONSNAME" "MasterAvatarSandboxPassword")"
|
||||
} >>"/$STARTVERZEICHNIS/$INIVERZEICHNIS/bin/Regions/$RTREGIONSNAME.ini"
|
||||
else
|
||||
echo error "REGIONSINITEILEN: $INI_FILE wurde nicht gefunden"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
## * autoregionsiniteilen
|
||||
# Diese Funktion ruft zuerst die Funktion `makeverzeichnisliste` auf, um eine Liste von Verzeichnissen zu erstellen,
|
||||
# und iteriert dann über jedes Verzeichnis in der Liste. Für jedes Verzeichnis wird die Regions.ini-Datei in mehrere
|
||||
# separate INI-Dateien aufgeteilt, eine für jede Region, und die einzelnen Regionsdateien werden umbenannt. Falls die
|
||||
# Regions.ini-Datei in einem Verzeichnis nicht vorhanden ist, wird sie nicht umbenannt.
|
||||
#? Parameter:
|
||||
# - Keine
|
||||
#? Rückgabewert:
|
||||
# - 0: Erfolgreiche Ausführung der Funktion
|
||||
#? Verwendungsbeispiel:
|
||||
# autoregionsiniteilen
|
||||
##
|
||||
function autoregionsiniteilen() {
|
||||
# Letzte Bearbeitung 01.10.2023
|
||||
makeverzeichnisliste
|
||||
sleep 1
|
||||
for ((i = 0; i < "$ANZAHLVERZEICHNISSLISTE"; i++)); do
|
||||
echo info "Region.ini ${VERZEICHNISSLISTE[$i]} zerlegen"
|
||||
echo line
|
||||
VERZEICHNIS="${VERZEICHNISSLISTE[$i]}"
|
||||
# Regions.ini teilen:
|
||||
echo "$VERZEICHNIS" # OK geht
|
||||
INI_FILE="/$STARTVERZEICHNIS/$VERZEICHNIS/bin/Regions/Regions.ini" # Auszulesende Datei
|
||||
# shellcheck disable=SC2155
|
||||
declare -a TARGETS="$(get_regionsarray "${INI_FILE}")"
|
||||
# shellcheck disable=SC2068
|
||||
for MeineRegion in ${TARGETS[@]}; do
|
||||
regionsiniteilen "$VERZEICHNIS" "$MeineRegion"
|
||||
sleep 1
|
||||
echo rohtext "regionsiniteilen $VERZEICHNIS $MeineRegion"
|
||||
done
|
||||
# Dann umbenennen:
|
||||
# Pruefung ob Datei vorhanden ist, wenn ja umbenennen.
|
||||
if [ ! -d "$INI_FILE" ]; then
|
||||
mv /$STARTVERZEICHNIS/"$INIVERZEICHNIS"/bin/Regions/Regions.ini /$STARTVERZEICHNIS/"$INIVERZEICHNIS"/bin/Regions/"$DATUM"-Regions.ini.old
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
## * createregionlist
|
||||
# Diese Funktion erstellt eine Liste von Regionsnamen aus den INI-Dateien in den angegebenen Verzeichnissen und speichert
|
||||
# sie in der Datei osmregionlist.ini. Zuvor wird die vorhandene osmregionlist.ini-Datei (falls vorhanden) gesichert und in
|
||||
# osmregionlist.ini.old umbenannt.
|
||||
#? Parameter:
|
||||
# - Keine
|
||||
#? Rückgabewert:
|
||||
# - 0: Erfolgreiche Ausführung der Funktion
|
||||
#? Verwendungsbeispiel:
|
||||
# createregionlist
|
||||
##
|
||||
function createregionlist() {
|
||||
# Letzte Bearbeitung 01.10.2023
|
||||
# Alte osmregionlist.ini sichern und in osmregionlist.ini.old umbenennen.
|
||||
if [ -f "/$STARTVERZEICHNIS/osmregionlist.ini" ]; then
|
||||
if [ -f "/$STARTVERZEICHNIS/osmregionlist.ini.old" ]; then
|
||||
rm -r /$STARTVERZEICHNIS/osmregionlist.ini.old
|
||||
fi
|
||||
mv /$STARTVERZEICHNIS/osmregionlist.ini /$STARTVERZEICHNIS/osmregionlist.ini.old
|
||||
fi
|
||||
# Die mit regionsconfigdateiliste erstellte Datei osmregionlist.ini nach sim Verzeichnis und Regionsnamen in die osmregionlist.ini speichern.
|
||||
declare -A Dateien # Array erstellen
|
||||
makeverzeichnisliste
|
||||
sleep 1
|
||||
for ((i = 0; i < "$ANZAHLVERZEICHNISSLISTE"; i++)); do
|
||||
echo info "Regionnamen ${VERZEICHNISSLISTE[$i]} schreiben"
|
||||
VERZEICHNIS="${VERZEICHNISSLISTE[$i]}"
|
||||
# shellcheck disable=SC2178
|
||||
Dateien=$(find /$STARTVERZEICHNIS/"$VERZEICHNIS"/bin/Regions/ -name "*.ini")
|
||||
for i2 in "${Dateien[@]}"; do # Array abarbeiten
|
||||
echo "$i2" >>osmregionlist.ini
|
||||
done
|
||||
done
|
||||
# Ueberfluessige Zeichen entfernen
|
||||
LOESCHEN=$(sed s/'\/'$STARTVERZEICHNIS'\/'//g /$STARTVERZEICHNIS/osmregionlist.ini)
|
||||
echo "$LOESCHEN" >/$STARTVERZEICHNIS/osmregionlist.ini # Aenderung /$STARTVERZEICHNIS/ speichern.
|
||||
LOESCHEN=$(sed s/'\/bin\/Regions\/'/' "'/g /$STARTVERZEICHNIS/osmregionlist.ini) # /bin/Regions/ entfernen.
|
||||
echo "$LOESCHEN" >/$STARTVERZEICHNIS/osmregionlist.ini # Aenderung /bin/Regions/ speichern.
|
||||
LOESCHEN=$(sed s/'.ini'/'"'/g /$STARTVERZEICHNIS/osmregionlist.ini) # Endung .ini entfernen.
|
||||
echo "$LOESCHEN" >/$STARTVERZEICHNIS/osmregionlist.ini # Aenderung .ini entfernen speichern.
|
||||
|
||||
LOESCHEN=$(sed s/'\"'/''/g /$STARTVERZEICHNIS/osmregionlist.ini) # " entfernen.
|
||||
echo "$LOESCHEN" >/$STARTVERZEICHNIS/osmregionlist.ini # Aenderung " entfernen speichern.
|
||||
|
||||
# Schauen ob da noch Regions.ini bei sind also Regionen mit dem Namen Regions, diese Zeilen loeschen.
|
||||
LOESCHEN=$(sed '/Regions/d' /$STARTVERZEICHNIS/osmregionlist.ini) # Alle Zeilen mit dem Eintrag Regions entfernen .
|
||||
echo "$LOESCHEN" >/$STARTVERZEICHNIS/osmregionlist.ini # Aenderung .ini entfernen speichern.
|
||||
return 0
|
||||
}
|
||||
|
||||
## * regionbackup
|
||||
# Diese Funktion erstellt ein Backup für eine OpenSimulator-Region, indem sie OAR- und Terrain-Daten sowie Konfigurationsdateien speichert.
|
||||
# Die Region wird in den Offline-Modus versetzt, wenn sie nicht bereits offline ist, bevor das Backup erstellt wird.
|
||||
#? Parameter:
|
||||
# 1. BACKUPVERZEICHNISSCREENNAME: Der Name des Bildschirms (Screen) für das Backup.
|
||||
# 2. REGIONSNAME: Der Name der Region, die gesichert werden soll.
|
||||
#? Rückgabewert:
|
||||
# - 0: Erfolgreiche Ausführung der Funktion
|
||||
#? Verwendungsbeispiel:
|
||||
# regionbackup "BackupScreen" "MyRegion"
|
||||
##
|
||||
function regionbackup() {
|
||||
# Letzte Bearbeitung 01.10.2023
|
||||
# regionbackup "$BACKUPSCREEN" "$BACKUPREGION"
|
||||
echo "Erstelle Backup von: $BACKUPSCREEN $BACKUPREGION"
|
||||
|
||||
sleep 1
|
||||
BACKUPVERZEICHNISSCREENNAME=$1
|
||||
REGIONSNAME=$2
|
||||
|
||||
echo
|
||||
echo "Backup $BACKUPVERZEICHNISSCREENNAME der Region $REGIONSNAME"
|
||||
cd /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin || return 1 # Test ob Verzeichnis vorhanden.
|
||||
mkdir -p /$STARTVERZEICHNIS/backup # Backup Verzeichnis anlegen falls nicht vorhanden.
|
||||
echo "Ich kann nicht pruefen ob die Region im OpenSimulator vorhanden ist."
|
||||
echo "Sollte sie nicht vorhanden sein wird root also alle Regionen gespeichert"
|
||||
# Ist die Region Online oder Offline?
|
||||
if [ -f /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"$REGIONSNAME".ini.offline ]; then
|
||||
echo "$REGIONSNAME ist heruntergefahren."
|
||||
else
|
||||
screen -S "$BACKUPVERZEICHNISSCREENNAME" -p 0 -X eval "stuff 'change region ${REGIONSNAME//\"/}'^M"
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME $REGIONSNAME"
|
||||
screen -S "$BACKUPVERZEICHNISSCREENNAME" -p 0 -X eval "stuff 'save oar /$STARTVERZEICHNIS/backup/'$DATUM'-$REGIONSNAME.oar'^M"
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME $DATUM-$REGIONSNAME.oar"
|
||||
|
||||
# Neu xml backup
|
||||
screen -S "$BACKUPVERZEICHNISSCREENNAME" -p 0 -X eval "stuff 'save xml2 /$STARTVERZEICHNIS/backup/'$DATUM'-$REGIONSNAME.xml2'^M"
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME $DATUM-$REGIONSNAME.xml2"
|
||||
# Neu xml backup ende
|
||||
|
||||
screen -S "$BACKUPVERZEICHNISSCREENNAME" -p 0 -X eval "stuff 'terrain save /$STARTVERZEICHNIS/backup/'$DATUM'-$REGIONSNAME.png'^M"
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME $DATUM-$REGIONSNAME.png"
|
||||
screen -S "$BACKUPVERZEICHNISSCREENNAME" -p 0 -X eval "stuff 'terrain save /$STARTVERZEICHNIS/backup/'$DATUM'-$REGIONSNAME.raw'^M"
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME $DATUM-$REGIONSNAME.raw"
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME Region $DATUM-$REGIONSNAME RAW und PNG Terrain werden gespeichert"
|
||||
fi
|
||||
|
||||
sleep 10
|
||||
if [ -f /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"$REGIONSNAME".ini.offline ]; then
|
||||
cp /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"$REGIONSNAME".ini.offline /$STARTVERZEICHNIS/backup/"$DATUM"-"$REGIONSNAME".ini.offline
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME Die Regions $DATUM-$REGIONSNAME.ini.offline wird gespeichert"
|
||||
fi
|
||||
if [ -f /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"$REGIONSNAME".ini ]; then
|
||||
cp /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"$REGIONSNAME".ini /$STARTVERZEICHNIS/backup/"$DATUM"-"$REGIONSNAME".ini
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME Die Regions $DATUM-$REGIONSNAME.ini wird gespeichert"
|
||||
fi
|
||||
if [ -f /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"${REGIONSNAME//\"/}" ]; then
|
||||
cp /$STARTVERZEICHNIS/"$BACKUPVERZEICHNISSCREENNAME"/bin/Regions/"${REGIONSNAME//\"/}" /$STARTVERZEICHNIS/backup/"$DATUM"-"$REGIONSNAME".ini
|
||||
echo "$BACKUPVERZEICHNISSCREENNAME Die Regions $DATUM-$REGIONSNAME.ini wird gespeichert"
|
||||
fi
|
||||
|
||||
echo "Backup der Region $REGIONSNAME wird fertiggestellt."
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
## * autoallclean.
|
||||
# loescht Log, dll, so, exe, aot Dateien fuer einen saubere neue installation, mit Robust.
|
||||
# Hierbei werden keine Datenbanken oder Konfigurationen geloescht aber opensim ist anschliessend nicht mehr startbereit.
|
||||
# Um opensim wieder Funktionsbereit zu machen muss ein Upgrade oder ein oscopy vorgang ausgefuehrt werden.
|
||||
#? @param keine.
|
||||
#? @return nichts wird zurueckgegeben.
|
||||
# todo: nichts.
|
||||
##
|
||||
function autoallclean() {
|
||||
# Letzte Bearbeitung 01.10.2023
|
||||
makeverzeichnisliste
|
||||
sleep 1
|
||||
for ((i = 0; i < "$ANZAHLVERZEICHNISSLISTE"; i++)); do
|
||||
# Dateien
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.log
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.dll
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.exe
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.so
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.xml
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.dylib
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.example
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.sample
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.txt
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.config
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.py
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.old
|
||||
rm /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/*.pdb
|
||||
|
||||
# Verzeichnisse leeren
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/assetcache/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/maptiles/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/MeshCache/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/j2kDecodeCache/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/ScriptEngines/*
|
||||
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/addin-db-002/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/addon-modules/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/assets/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/bakes/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/data/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/Estates/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/inventory/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/lib/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/lib32/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/lib64/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/Library/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/openmetaverse_data/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/robust-include/*
|
||||
|
||||
echo "autoallclean: ${VERZEICHNISSLISTE[$i]} geloescht"
|
||||
sleep 1
|
||||
done
|
||||
# nochmal das gleiche mit Robust
|
||||
echo "autoallclean: $ROBUSTVERZEICHNIS geloescht"
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.log
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.dll
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.exe
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.so
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.xml
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.dylib
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.example
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.sample
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.txt
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.config
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.py
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.old
|
||||
rm /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/*.pdb
|
||||
|
||||
rm -r /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/assetcache/*
|
||||
rm -r /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/maptiles/*
|
||||
rm -r /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/MeshCache/*
|
||||
rm -r /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/j2kDecodeCache/*
|
||||
rm -r /$STARTVERZEICHNIS/$ROBUSTVERZEICHNIS/bin/ScriptEngines/*
|
||||
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/addin-db-002/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/addon-modules/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/assets/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/bakes/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/data/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/Estates/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/inventory/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/lib/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/lib32/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/lib64/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/Library/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/openmetaverse_data/*
|
||||
rm -r /$STARTVERZEICHNIS/"${VERZEICHNISSLISTE[$i]}"/bin/robust-include/*
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
## * autoregionbackup
|
||||
# Diese Funktion durchläuft die Regionen in Ihrem OpenSimulator-Grid und erstellt automatische Backups.
|
||||
#? Parameter:
|
||||
# Keine Parameter erforderlich.
|
||||
#? Rückgabewert:
|
||||
# - Kein expliziter Rückgabewert
|
||||
#? Verwendungsbeispiel:
|
||||
# autoregionbackup
|
||||
# todo: Uebergabe Parameter Fehler. Bug Modus mit extra ausgaben. Ist keine osmregionlist.ini vorhanden muss sie erstellt werden.
|
||||
##
|
||||
function autoregionbackup() {
|
||||
# Letzte Bearbeitung 01.10.2023
|
||||
echo "Automatisches Backup wird gestartet."
|
||||
|
||||
# Ist die osmregionlist.ini vorhanden?
|
||||
if [ ! -f "/$STARTVERZEICHNIS/osmregionlist.ini" ]; then
|
||||
echo "Die osmregionlist.ini Datei ist noch nicht vorhanden und wird erstellt."
|
||||
createregionlist
|
||||
else
|
||||
echo "Die osmregionlist.ini Datei ist bereits vorhanden."
|
||||
fi
|
||||
|
||||
makeregionsliste
|
||||
sleep 1
|
||||
for ((i = 0; i < "$ANZAHLREGIONSLISTE"; i++)); do
|
||||
BACKUPSCREEN=$(echo "${REGIONSLISTE[$i]}" | cut -d ' ' -f 1)
|
||||
BACKUPREGION=$(echo "${REGIONSLISTE[$i]}" | cut -d ' ' -f 2)
|
||||
echo "Starte Backup von: $BACKUPSCREEN $BACKUPREGION" # Testausgabe
|
||||
regionbackup "$BACKUPSCREEN" "$BACKUPREGION"
|
||||
if [ -f /$STARTVERZEICHNIS/"$BACKUPSCREEN"/bin/Regions/"$BACKUPREGION".ini.offline ]; then
|
||||
echo "$BACKUPREGION Region ist Offline und wird uebersprungen."
|
||||
else
|
||||
sleep $BACKUPWARTEZEIT
|
||||
echo "BACKUPWARTEZEIT $BACKUPWARTEZEIT Sekunden." # Testausgabe
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# Zähle die Tabellen in der Datenbank und die Asset-Typen in der Tabelle 'assets'.
|
||||
# bash osmtool_backup.sh datenbanktabellen "mein_benutzer" "geheim123" "meine_datenbank"
|
||||
function datenbanktabellen() {
|
||||
username=$1
|
||||
password=$2
|
||||
databasename=$3
|
||||
logfile="/$STARTVERZEICHNIS/backup/${databasename}/status_report.txt"
|
||||
|
||||
mkdir -p "/$STARTVERZEICHNIS/backup/${databasename}" || exit
|
||||
|
||||
echo "📊 Statusbericht für Datenbank: $databasename" | tee "$logfile"
|
||||
echo "📅 Datum: $(date '+%Y-%m-%d %H:%M:%S')" | tee -a "$logfile"
|
||||
|
||||
# Tabellen zählen
|
||||
tabellenanzahl=$(mysql -u"$username" -p"$password" -D"$databasename" -e "SHOW TABLES;" | tail -n +2 | wc -l)
|
||||
echo "📦 Tabellen gefunden: $tabellenanzahl" | tee -a "$logfile"
|
||||
|
||||
# Asset-Typen zählen (wenn Tabelle vorhanden)
|
||||
if mysql -u"$username" -p"$password" -D"$databasename" -e "SHOW TABLES LIKE 'assets';" | grep -q "assets"; then
|
||||
assettypen_anzahl=$(mysql -u"$username" -p"$password" -D"$databasename" -e "SELECT COUNT(DISTINCT assetType) FROM assets;" | tail -n 1)
|
||||
echo "🎨 Asset-Typen in 'assets': $assettypen_anzahl" | tee -a "$logfile"
|
||||
else
|
||||
echo "⚠️ Tabelle 'assets' nicht gefunden." | tee -a "$logfile"
|
||||
fi
|
||||
|
||||
echo "✅ Bericht gespeichert unter: $logfile"
|
||||
}
|
||||
|
||||
|
||||
# beispiel: screen -fa -S BACKUPNOASSETS -d -U -m bash osmtool.sh backuptabelle_noassets "mein_benutzer" "geheim123" "meine_datenbank"
|
||||
function backuptabelle_noassets() {
|
||||
username=$1
|
||||
password=$2
|
||||
databasename=$3
|
||||
|
||||
mkdir -p /$STARTVERZEICHNIS/backup/"$databasename" || exit
|
||||
logfile="/$STARTVERZEICHNIS/backup/${databasename}/backup_log.txt"
|
||||
|
||||
# Tabellennamen holen und speichern
|
||||
mysql -u"$username" -p"$password" -D"$databasename" -e "SHOW TABLES;" | tail -n +2 > /$STARTVERZEICHNIS/backup/"$databasename"/liste.txt
|
||||
|
||||
# Anzahl der Tabellen zählen
|
||||
tabellenanzahl=$(wc -l < /$STARTVERZEICHNIS/backup/"$databasename"/liste.txt)
|
||||
echo "📦 Tabellen gefunden: $tabellenanzahl" | tee -a "$logfile"
|
||||
|
||||
# Tabellen sichern (außer 'assets')
|
||||
gesichert=0
|
||||
while IFS= read -r tabellenname; do
|
||||
sleep 1
|
||||
if [[ "$tabellenname" != "assets" ]]; then
|
||||
mysqldump -u"$username" -p"$password" "$databasename" "$tabellenname" | zip > /$STARTVERZEICHNIS/backup/"$databasename"/"$tabellenname".sql.zip
|
||||
echo "✅ Gesichert: $tabellenname" | tee -a "$logfile"
|
||||
((gesichert++))
|
||||
fi
|
||||
done < /$STARTVERZEICHNIS/backup/"$databasename"/liste.txt
|
||||
|
||||
echo "🔒 Tabellen gesichert (ohne 'assets'): $gesichert" | tee -a "$logfile"
|
||||
return 0
|
||||
}
|
||||
|
||||
# screen -fa -S ASSETBACKUP -d -U -m bash osmtool.sh asset_backup "mein_benutzer" "geheim123" "meine_datenbank"
|
||||
function asset_backup() {
|
||||
username=$1
|
||||
password=$2
|
||||
databasename=$3
|
||||
fromtable="assets"
|
||||
fromtypes="assetType"
|
||||
|
||||
mkdir -p /$STARTVERZEICHNIS/backup/"$databasename"/assets || exit
|
||||
cd /$STARTVERZEICHNIS/backup/"$databasename"/assets || exit
|
||||
logfile="./asset_backup_log.txt"
|
||||
|
||||
# Assettypen holen
|
||||
mysql -u"$username" -p"$password" -D"$databasename" -e "SELECT DISTINCT $fromtypes FROM $fromtable;" | tail -n +2 > typen.txt
|
||||
assettypen_anzahl=$(wc -l < typen.txt)
|
||||
echo "📦 Assettypen gefunden: $assettypen_anzahl" | tee -a "$logfile"
|
||||
|
||||
gesichert=0
|
||||
while IFS= read -r assettype; do
|
||||
filename="assetType_${assettype}"
|
||||
echo "✅ Sichere Asset-Typ: $assettype → $filename.sql.zip" | tee -a "$logfile"
|
||||
mysqldump -u"$username" -p"$password" "$databasename" --tables "$fromtable" --where="$fromtypes = '$assettype'" | zip > "$filename.sql.zip"
|
||||
((gesichert++))
|
||||
done < typen.txt
|
||||
|
||||
echo "🔒 Assettypen gesichert: $gesichert" | tee -a "$logfile"
|
||||
}
|
||||
|
||||
Unterschiedliche assettypen der Tabelle assets zählen
|
||||
|
||||
# screen -fa -S DBRESTORE -d -U -m bash osmtool.sh db_restoretabelle_noassets "mein_benutzer" "geheim123" "meine_datenbank"
|
||||
function db_restoretabelle_noassets() {
|
||||
username=$1
|
||||
password=$2
|
||||
databasename=$3
|
||||
restorepath="/$STARTVERZEICHNIS/backup/${databasename}"
|
||||
logfile="${restorepath}/restore_log.txt"
|
||||
|
||||
cd "$restorepath" || exit
|
||||
|
||||
if [[ ! -f liste.txt ]]; then
|
||||
echo "❌ Keine 'liste.txt' gefunden. Backup-Datei fehlt oder ungültig." | tee -a "$logfile"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "📦 Starte Wiederherstellung aus: $restorepath" | tee -a "$logfile"
|
||||
|
||||
restored=0
|
||||
total=$(grep -v "^assets$" liste.txt | wc -l)
|
||||
echo "🔍 Tabellen zur Wiederherstellung (ohne 'assets'): $total" | tee -a "$logfile"
|
||||
|
||||
while IFS= read -r tabellenname; do
|
||||
if [[ "$tabellenname" != "assets" ]]; then
|
||||
zipfile="${tabellenname}.sql.zip"
|
||||
if [[ -f "$zipfile" ]]; then
|
||||
echo "🔄 Wiederherstellung: $tabellenname" | tee -a "$logfile"
|
||||
unzip -p "$zipfile" | mysql -u"$username" -p"$password" "$databasename"
|
||||
((restored++))
|
||||
else
|
||||
echo "⚠️ Datei fehlt: $zipfile" | tee -a "$logfile"
|
||||
fi
|
||||
fi
|
||||
done < liste.txt
|
||||
|
||||
echo "✅ Tabellen erfolgreich wiederhergestellt: $restored von $total" | tee -a "$logfile"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Wiederherstellung der Asset-Typen
|
||||
function asset_restore() {
|
||||
username=$1
|
||||
password=$2
|
||||
databasename=$3
|
||||
restorepath="/$STARTVERZEICHNIS/backup/${databasename}/assets"
|
||||
logfile="${restorepath}/asset_restore_log.txt"
|
||||
|
||||
cd "$restorepath" || exit
|
||||
|
||||
zipfiles=(assetType_*.sql.zip)
|
||||
anzahl=${#zipfiles[@]}
|
||||
echo "📦 Asset-Backups gefunden: $anzahl" | tee -a "$logfile"
|
||||
|
||||
restored=0
|
||||
for zipfile in "${zipfiles[@]}"; do
|
||||
echo "🔄 Wiederherstellung: $zipfile" | tee -a "$logfile"
|
||||
unzip -p "$zipfile" | mysql -u"$username" -p"$password" "$databasename"
|
||||
((restored++))
|
||||
done
|
||||
|
||||
echo "✅ Assettypen wiederhergestellt: $restored" | tee -a "$logfile"
|
||||
}
|
||||
|
||||
# Sichere die Datenbanken 'wordweb' und 'money' in ZIP-Dateien.
|
||||
# bash osmtool_backup.sh sichere_wordweb_und_money "mein_benutzer" "geheim123"
|
||||
|
||||
function sichere_wordweb_und_money() {
|
||||
username=$1
|
||||
password=$2
|
||||
logfile="/$STARTVERZEICHNIS/backup/db_sicherung_log.txt"
|
||||
datum=$(date '+%Y-%m-%d_%H-%M-%S')
|
||||
|
||||
mkdir -p /$STARTVERZEICHNIS/backup/wordweb
|
||||
mkdir -p /$STARTVERZEICHNIS/backup/money
|
||||
|
||||
echo "📅 Sicherung gestartet: $datum" | tee -a "$logfile"
|
||||
|
||||
# WORDWEB sichern
|
||||
echo "💾 Sichere Datenbank: wordweb" | tee -a "$logfile"
|
||||
mysqldump -u"$username" -p"$password" wordweb | zip > /$STARTVERZEICHNIS/backup/wordweb/wordweb_${datum}.sql.zip
|
||||
size_wordweb=$(du -sh /$STARTVERZEICHNIS/backup/wordweb/wordweb_${datum}.sql.zip | cut -f1)
|
||||
echo "✅ wordweb gesichert → Größe: $size_wordweb" | tee -a "$logfile"
|
||||
|
||||
# MONEY sichern
|
||||
echo "💾 Sichere Datenbank: money" | tee -a "$logfile"
|
||||
mysqldump -u"$username" -p"$password" money | zip > /$STARTVERZEICHNIS/backup/money/money_${datum}.sql.zip
|
||||
size_money=$(du -sh /$STARTVERZEICHNIS/backup/money/money_${datum}.sql.zip | cut -f1)
|
||||
echo "✅ money gesichert → Größe: $size_money" | tee -a "$logfile"
|
||||
|
||||
echo "📦 Sicherung abgeschlossen: $(date '+%Y-%m-%d %H:%M:%S')" | tee -a "$logfile"
|
||||
}
|
||||
|
||||
function restore_wordweb_und_money() {
|
||||
username=$1
|
||||
password=$2
|
||||
for dbname in wordweb money; do
|
||||
restorepath="/$STARTVERZEICHNIS/backup/${dbname}"
|
||||
latestfile=$(ls -t "$restorepath"/*.sql.zip | head -n 1)
|
||||
if [[ -f "$latestfile" ]]; then
|
||||
echo "🔄 Wiederherstellung: $dbname aus $latestfile"
|
||||
unzip -p "$latestfile" | mysql -u"$username" -p"$password" "$dbname"
|
||||
else
|
||||
echo "⚠️ Keine Backup-Datei gefunden für $dbname"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Backup-Konfigurationsdateien aus robust/bin und sim-Verzeichnissen
|
||||
# bash osmtool_backup.sh backup_config
|
||||
function backup_config() {
|
||||
echo "${SYM_WAIT} ${COLOR_START}Sichere Konfigurationsdateien...${COLOR_RESET}"
|
||||
|
||||
# Zielverzeichnis für Backups
|
||||
backup_root="/opt/backup/config"
|
||||
|
||||
# Backup aus robust/bin
|
||||
if [[ -d "robust/bin" ]]; then
|
||||
src_dir="robust/bin"
|
||||
dest_dir="${backup_root}/${src_dir}"
|
||||
echo "${SYM_OK} ${COLOR_START}Sichere ${COLOR_DIR}${src_dir}${COLOR_RESET} nach ${COLOR_DIR}${dest_dir}${COLOR_RESET}"
|
||||
find "$src_dir" -type f -name "*.ini" | while read -r file; do
|
||||
rel_path="${file#$src_dir/}" # relativer Pfad
|
||||
mkdir -p "${dest_dir}/$(dirname "$rel_path")"
|
||||
cp "$file" "${dest_dir}/$rel_path"
|
||||
done
|
||||
else
|
||||
echo "${SYM_BAD} ${COLOR_DIR}robust/bin${COLOR_RESET} nicht gefunden. Überspringe."
|
||||
fi
|
||||
|
||||
# Backup aus sim-Verzeichnissen
|
||||
for ((i=1; i<=999; i++)); do
|
||||
sim_dir="sim$i/bin"
|
||||
if [[ -d "$sim_dir" ]]; then
|
||||
dest_dir="${backup_root}/${sim_dir}"
|
||||
echo "${SYM_OK} ${COLOR_START}Sichere ${COLOR_DIR}${sim_dir}${COLOR_RESET} nach ${COLOR_DIR}${dest_dir}${COLOR_RESET}"
|
||||
find "$sim_dir" -type f -name "*.ini" | while read -r file; do
|
||||
rel_path="${file#$sim_dir/}"
|
||||
mkdir -p "${dest_dir}/$(dirname "$rel_path")"
|
||||
cp "$file" "${dest_dir}/$rel_path"
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${SYM_OK} ${COLOR_START}Backup abgeschlossen.${COLOR_RESET}"
|
||||
echo .
|
||||
}
|
||||
|
||||
# Restore-Konfigurationsdateien aus dem backup Verzeichnis nach robust/bin und sim-Verzeichnissen
|
||||
# bash osmtool_backup.sh restore_config
|
||||
function restore_config() {
|
||||
echo "${SYM_WAIT} ${COLOR_START}Stelle Konfigurationsdateien aus Backup wieder her...${COLOR_RESET}"
|
||||
|
||||
# Quellverzeichnis für Backups
|
||||
backup_root="/opt/backup/config"
|
||||
|
||||
# Restore für robust/bin
|
||||
src_dir="${backup_root}/robust/bin"
|
||||
dest_dir="robust/bin"
|
||||
if [[ -d "$src_dir" ]]; then
|
||||
echo "${SYM_OK} ${COLOR_START}Stelle ${COLOR_DIR}${dest_dir}${COLOR_RESET} aus ${COLOR_DIR}${src_dir}${COLOR_RESET} wieder her"
|
||||
find "$src_dir" -type f -name "*.ini" | while read -r file; do
|
||||
rel_path="${file#$src_dir/}"
|
||||
mkdir -p "${dest_dir}/$(dirname "$rel_path")"
|
||||
cp "$file" "${dest_dir}/$rel_path"
|
||||
done
|
||||
else
|
||||
echo "${SYM_BAD} ${COLOR_DIR}${src_dir}${COLOR_RESET} nicht gefunden. Überspringe."
|
||||
fi
|
||||
|
||||
# Restore für sim-Verzeichnisse
|
||||
for ((i=1; i<=999; i++)); do
|
||||
src_dir="${backup_root}/sim$i/bin"
|
||||
dest_dir="sim$i/bin"
|
||||
if [[ -d "$src_dir" ]]; then
|
||||
echo "${SYM_OK} ${COLOR_START}Stelle ${COLOR_DIR}${dest_dir}${COLOR_RESET} aus ${COLOR_DIR}${src_dir}${COLOR_RESET} wieder her"
|
||||
find "$src_dir" -type f -name "*.ini" | while read -r file; do
|
||||
rel_path="${file#$src_dir/}"
|
||||
mkdir -p "${dest_dir}/$(dirname "$rel_path")"
|
||||
cp "$file" "${dest_dir}/$rel_path"
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${SYM_OK} ${COLOR_START}Wiederherstellung abgeschlossen.${COLOR_RESET}"
|
||||
echo .
|
||||
}
|
||||
|
||||
|
||||
|
||||
case $KOMMANDO in
|
||||
"regionsiniteilen") regionsiniteilen "$2" "$3" "$4" ;;
|
||||
"autoregionsiniteilen") autoregionsiniteilen ;;
|
||||
"createregionlist") createregionlist ;;
|
||||
"regionbackup") regionbackup "$2" "$3" ;;
|
||||
"backup_config") backup_config ;;
|
||||
"restore_config") restore_config ;;
|
||||
"autoallclean") autoallclean ;;
|
||||
"autoregionbackup") autoregionbackup ;;
|
||||
"datenbanktabellen") datenbanktabellen "$2" "$3" "$4" ;;
|
||||
"backuptabelle_noassets") backuptabelle_noassets "$2" "$3" "$4" ;;
|
||||
"asset_backup") asset_backup "$2" "$3" "$4" ;;
|
||||
"db_restoretabelle_noassets") db_restoretabelle_noassets "$2" "$3" "$4" ;;
|
||||
"asset_restore") asset_restore "$2" "$3" "$4" ;;
|
||||
"sichere_wordweb_und_money") sichere_wordweb_und_money "$2" "$3" ;;
|
||||
"restore_wordweb_und_money") restore_wordweb_und_money "$2" "$3" ;;
|
||||
*) echo "Unbekanntes Kommando: $KOMMANDO" ;;
|
||||
esac
|
||||
# Ende des Skripts
|
||||
exit 0
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
MOD_DIR="$BASE_DIR/modular"
|
||||
|
||||
# shellcheck source=./modular/osmtool_core.sh
|
||||
source "$MOD_DIR/osmtool_core.sh"
|
||||
init_i18n
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_main.sh [--mode <cli|ui>] [--lang <de|en|fr|es>] [--profile <grid-sim|robust|standalone>] --module <install|startstop|cleanup|health|backup|restore|update|config|report|smoke|cron> [module-options]
|
||||
|
||||
Examples:
|
||||
osmtool_main.sh --module install --action prepare-ubuntu
|
||||
osmtool_main.sh --module startstop --target grid --action restart --workdir /opt
|
||||
osmtool_main.sh --module cleanup --action log-clean --workdir /opt
|
||||
osmtool_main.sh --module health --action run --workdir /opt
|
||||
osmtool_main.sh --module backup --action db-backup --db-user root --db-pass secret --db-name opensim
|
||||
osmtool_main.sh --module update --action create-rollback --workdir /opt
|
||||
osmtool_main.sh --module config --action validate-runtime --workdir /opt
|
||||
osmtool_main.sh --module report --action generate --workdir /opt
|
||||
osmtool_main.sh --module smoke --action run --profile grid-sim --workdir /opt
|
||||
osmtool_main.sh --module cron --action list
|
||||
osmtool_main.sh --mode ui
|
||||
EOF
|
||||
print_usage_common
|
||||
}
|
||||
|
||||
dispatch_module() {
|
||||
local module="$1"
|
||||
shift
|
||||
|
||||
case "$module" in
|
||||
install)
|
||||
"$MOD_DIR/osmtool_install.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
startstop)
|
||||
"$MOD_DIR/osmtool_startstop.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
cleanup)
|
||||
"$MOD_DIR/osmtool_cleanup.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
health)
|
||||
"$MOD_DIR/osmtool_health.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
backup)
|
||||
"$MOD_DIR/osmtool_data.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
update)
|
||||
"$MOD_DIR/osmtool_update.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
config)
|
||||
"$MOD_DIR/osmtool_config.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
report)
|
||||
"$MOD_DIR/osmtool_report.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
smoke)
|
||||
"$MOD_DIR/osmtool_smoke.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
cron)
|
||||
bash "$MOD_DIR/osmtool_cron.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
restore)
|
||||
"$MOD_DIR/osmtool_restore.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
*)
|
||||
die "$(msg ERR_UNKNOWN_MODULE): $module"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
default_target_for_profile() {
|
||||
case "$1" in
|
||||
grid-sim) echo "grid" ;;
|
||||
robust) echo "robust" ;;
|
||||
standalone) echo "standalone" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
args_have_target() {
|
||||
local prev=""
|
||||
local token
|
||||
for token in "$@"; do
|
||||
if [[ "$prev" == "--target" ]]; then
|
||||
return 0
|
||||
fi
|
||||
prev="$token"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
ui_flow() {
|
||||
local module action target
|
||||
|
||||
PROFILE="$(show_menu "$(msg APP_TITLE)" "$(msg MENU_CHOOSE_PROFILE)" \
|
||||
"grid-sim" "$(msg PROFILE_GRID_SIM)" \
|
||||
"robust" "$(msg PROFILE_ROBUST)" \
|
||||
"standalone" "$(msg PROFILE_STANDALONE)")"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
module="$(show_menu "$(msg APP_TITLE)" "$(msg MENU_CHOOSE_MODULE)" \
|
||||
"install" "$(msg MENU_INSTALL)" \
|
||||
"startstop" "$(msg MENU_STARTSTOP)" \
|
||||
"cleanup" "$(msg MENU_CLEANUP)" \
|
||||
"health" "$(msg MENU_HEALTH)" \
|
||||
"backup" "$(msg MENU_BACKUP)" \
|
||||
"restore" "$(msg MENU_RESTORE)" \
|
||||
"update" "$(msg MENU_UPDATE)" \
|
||||
"config" "$(msg MENU_CONFIG)" \
|
||||
"report" "$(msg MENU_REPORT)" \
|
||||
"smoke" "$(msg MENU_SMOKE)" \
|
||||
"cron" "$(msg MENU_CRON)")"
|
||||
|
||||
case "$module" in
|
||||
install)
|
||||
action="$(show_menu "$(msg MENU_INSTALL)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"bootstrap-server" "bootstrap-server" \
|
||||
"server-check" "server-check" \
|
||||
"prepare-ubuntu" "prepare-ubuntu" \
|
||||
"install-opensim-deps" "install-opensim-deps" \
|
||||
"install-dotnet8" "install-dotnet8" \
|
||||
"install-opensim" "install-opensim" \
|
||||
"configure-opensim" "configure-opensim" \
|
||||
"configure-database" "configure-database" \
|
||||
"compile-janus" "compile-janus" \
|
||||
"configure-janus" "configure-janus" \
|
||||
"install-janus" "install-janus")"
|
||||
dispatch_module install --action "$action"
|
||||
;;
|
||||
startstop)
|
||||
if [[ "$PROFILE" == "grid-sim" ]]; then
|
||||
target="$(show_menu "$(msg MENU_STARTSTOP)" "$(msg MENU_CHOOSE_TARGET)" \
|
||||
"grid" "$(msg TARGET_GRID)" \
|
||||
"robust" "$(msg TARGET_ROBUST)" \
|
||||
"sim1" "$(msg TARGET_SIM1)" \
|
||||
"janus" "$(msg TARGET_JANUS)")"
|
||||
elif [[ "$PROFILE" == "robust" ]]; then
|
||||
target="$(show_menu "$(msg MENU_STARTSTOP)" "$(msg MENU_CHOOSE_TARGET)" \
|
||||
"robust" "$(msg TARGET_ROBUST)" \
|
||||
"janus" "$(msg TARGET_JANUS)")"
|
||||
else
|
||||
target="$(show_menu "$(msg MENU_STARTSTOP)" "$(msg MENU_CHOOSE_TARGET)" \
|
||||
"standalone" "$(msg TARGET_STANDALONE)" \
|
||||
"janus" "$(msg TARGET_JANUS)")"
|
||||
fi
|
||||
|
||||
action="$(show_menu "$(msg MENU_STARTSTOP)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"start" "$(msg ACTION_START)" \
|
||||
"stop" "$(msg ACTION_STOP)" \
|
||||
"restart" "$(msg ACTION_RESTART)")"
|
||||
dispatch_module startstop --target "$target" --action "$action"
|
||||
;;
|
||||
cleanup)
|
||||
action="$(show_menu "$(msg MENU_CLEANUP)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"cache-clean" "$(msg ACTION_CACHE_CLEAN)" \
|
||||
"log-clean" "$(msg ACTION_LOG_CLEAN)" \
|
||||
"tmp-clean" "$(msg ACTION_TMP_CLEAN)" \
|
||||
"reboot" "$(msg ACTION_REBOOT)")"
|
||||
dispatch_module cleanup --action "$action"
|
||||
;;
|
||||
health)
|
||||
action="$(show_menu "$(msg MENU_HEALTH)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"run" "$(msg ACTION_HEALTH_RUN)")"
|
||||
dispatch_module health --action "$action"
|
||||
;;
|
||||
backup)
|
||||
action="$(show_menu "$(msg MENU_BACKUP)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"db-backup" "$(msg ACTION_DB_BACKUP)" \
|
||||
"oar-backup" "$(msg ACTION_OAR_BACKUP)" \
|
||||
"full-backup" "$(msg ACTION_FULL_BACKUP)")"
|
||||
dispatch_module backup --action "$action"
|
||||
;;
|
||||
restore)
|
||||
action="$(show_menu "$(msg MENU_RESTORE)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"list-backups" "$(msg ACTION_RESTORE_LIST)" \
|
||||
"db-restore" "$(msg ACTION_RESTORE_DB)" \
|
||||
"oar-restore" "$(msg ACTION_RESTORE_OAR)" \
|
||||
"full-restore" "$(msg ACTION_RESTORE_FULL)")"
|
||||
dispatch_module restore --action "$action"
|
||||
;;
|
||||
update)
|
||||
action="$(show_menu "$(msg MENU_UPDATE)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"create-rollback" "$(msg ACTION_UPDATE_ROLLBACK)" \
|
||||
"list-rollbacks" "$(msg ACTION_UPDATE_LIST)" \
|
||||
"update-opensim" "$(msg ACTION_UPDATE_OPENSIM)" \
|
||||
"update-janus" "$(msg ACTION_UPDATE_JANUS)" \
|
||||
"full-update" "$(msg ACTION_UPDATE_FULL)")"
|
||||
dispatch_module update --action "$action"
|
||||
;;
|
||||
config)
|
||||
action="$(show_menu "$(msg MENU_CONFIG)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"validate-file" "$(msg ACTION_CONFIG_FILE)" \
|
||||
"validate-runtime" "$(msg ACTION_CONFIG_RUNTIME)")"
|
||||
dispatch_module config --action "$action"
|
||||
;;
|
||||
report)
|
||||
action="$(show_menu "$(msg MENU_REPORT)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"generate" "$(msg ACTION_REPORT_GENERATE)")"
|
||||
dispatch_module report --action "$action"
|
||||
;;
|
||||
smoke)
|
||||
action="$(show_menu "$(msg MENU_SMOKE)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"run" "$(msg ACTION_SMOKE_RUN)")"
|
||||
dispatch_module smoke --action "$action"
|
||||
;;
|
||||
cron)
|
||||
action="$(show_menu "$(msg MENU_CRON)" "$(msg MENU_CHOOSE_ACTION)" \
|
||||
"install" "$(msg ACTION_CRON_INSTALL)" \
|
||||
"list" "$(msg ACTION_CRON_LIST)" \
|
||||
"remove" "$(msg ACTION_CRON_REMOVE)")"
|
||||
dispatch_module cron --action "$action"
|
||||
;;
|
||||
*)
|
||||
die "$(msg ERR_UNKNOWN_UI_MODULE): $module"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
MODE="cli"
|
||||
MODULE=""
|
||||
LANG_OVERRIDE="${OSM_LANG:-de}"
|
||||
PROFILE="grid-sim"
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--mode) MODE="$2"; shift 2 ;;
|
||||
--lang) LANG_OVERRIDE="$2"; shift 2 ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--module) MODULE="$2"; shift 2 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
if [[ "$MODE" == "ui" ]]; then
|
||||
ui_flow
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[[ -n "$MODULE" ]] || die "$(msg ERR_MISSING_MODULE)"
|
||||
|
||||
if [[ "$MODULE" == "startstop" ]] && ! args_have_target "$@"; then
|
||||
dispatch_module "$MODULE" --target "$(default_target_for_profile "$PROFILE")" "$@"
|
||||
else
|
||||
dispatch_module "$MODULE" "$@"
|
||||
fi
|
||||
@@ -0,0 +1,270 @@
|
||||
#!/bin/bash
|
||||
|
||||
#* WARTEZEITEN muessen leider sein damit der Server nicht überfordert wird.
|
||||
Simulator_Start_wait=15 # Sekunden
|
||||
MoneyServer_Start_wait=30 # Sekunden
|
||||
RobustServer_Start_wait=30 # Sekunden
|
||||
Simulator_Stop_wait=15 # Sekunden
|
||||
MoneyServer_Stop_wait=30 # Sekunden
|
||||
RobustServer_Stop_wait=30 # Sekunden
|
||||
|
||||
#?──────────────────────────────────────────────────────────────────────────────────────────
|
||||
#* Start Stop Grid
|
||||
#?──────────────────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
function opensimstart() {
|
||||
echo "${SYM_WAIT} ${COLOR_START}Starte das Grid!${COLOR_RESET}"
|
||||
|
||||
# 1. RobustServer (muss zuerst laufen)
|
||||
if [[ -d "robust/bin" && -f "robust/bin/Robust.dll" ]]; then
|
||||
echo "${SYM_OK} ${COLOR_START}Starte ${COLOR_SERVER}RobustServer ${COLOR_RESET} ${COLOR_START}aus ${COLOR_DIR}robust/bin...${COLOR_RESET}"
|
||||
(cd robust/bin && screen -fa -S robustserver -d -U -m dotnet Robust.dll)
|
||||
sleep "$RobustServer_Start_wait"
|
||||
else
|
||||
echo "${SYM_BAD} ${COLOR_SERVER}RobustServer: ${COLOR_BAD}Robust.dll nicht gefunden.${COLOR_RESET} ${COLOR_START}Überspringe Start.${COLOR_RESET}"
|
||||
fi
|
||||
|
||||
# 2. MoneyServer (optional)
|
||||
if [[ -f "robust/bin/MoneyServer.dll" ]]; then
|
||||
echo "${SYM_OK} ${COLOR_START}Starte ${COLOR_SERVER}MoneyServer${COLOR_RESET} ${COLOR_START}aus ${COLOR_DIR}robust/bin...${COLOR_RESET}"
|
||||
(cd robust/bin && screen -fa -S moneyserver -d -U -m dotnet MoneyServer.dll)
|
||||
sleep "$MoneyServer_Start_wait"
|
||||
fi
|
||||
|
||||
# 3. SIM1 ZUERST (sequentiell)
|
||||
if [[ -d "sim1/bin" && -f "sim1/bin/OpenSim.dll" ]]; then
|
||||
echo "${SYM_OK} ${COLOR_START}Starte ${COLOR_SERVER}sim1${COLOR_RESET} ${COLOR_START}(primäre Region)...${COLOR_RESET}"
|
||||
(cd sim1/bin && screen -fa -S sim1 -d -U -m dotnet OpenSim.dll)
|
||||
sleep "$Simulator_Start_wait"
|
||||
else
|
||||
echo "${SYM_BAD} ${COLOR_SERVER}sim1: ${COLOR_BAD}OpenSim.dll nicht gefunden.${COLOR_RESET}"
|
||||
fi
|
||||
|
||||
# 4. SIM2-SIM99 PARALLEL
|
||||
echo "${SYM_INFO} ${COLOR_START}Starte sekundäre Simulatoren parallel...${COLOR_RESET}"
|
||||
|
||||
# Maximal 10 parallele Jobs
|
||||
MAX_JOBS=10
|
||||
for ((i=2; i<=99; i++)); do
|
||||
sim_dir="sim$i/bin"
|
||||
if [[ -d "$sim_dir" && -f "$sim_dir/OpenSim.dll" ]]; then
|
||||
|
||||
# Warten falls zu viele Jobs laufen
|
||||
while (( $(jobs -p | wc -l) >= MAX_JOBS )); do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "${SYM_OK} ${COLOR_START}Starte ${COLOR_SERVER}sim$i${COLOR_RESET} ${COLOR_START}aus ${COLOR_DIR}$sim_dir...${COLOR_RESET}"
|
||||
(cd "$sim_dir" && screen -fa -S "sim$i" -d -U -m dotnet OpenSim.dll) &
|
||||
fi
|
||||
done
|
||||
|
||||
wait # Warte auf alle Hintergrundjobs
|
||||
echo "${SYM_OK} ${COLOR_START}Alle Simulatoren gestartet.${COLOR_RESET}"
|
||||
echo .
|
||||
}
|
||||
|
||||
function opensimstop() {
|
||||
echo "${SYM_WAIT} ${COLOR_STOP}Stoppe das Grid!${COLOR_RESET}"
|
||||
local MAX_PARALLEL=10 # Maximale parallele Stopp-Vorgänge
|
||||
|
||||
# 1. Paralleles Stoppen von sim999 bis sim2
|
||||
echo "${SYM_INFO} ${COLOR_STOP}Stoppe sekundäre Simulatoren parallel...${COLOR_RESET}"
|
||||
for ((i=999; i>=2; i--)); do
|
||||
sim_name="sim$i"
|
||||
|
||||
# Warten falls zu viele parallele Jobs laufen
|
||||
#while [ $(jobs -p | wc -l) -ge $MAX_PARALLEL ]; do
|
||||
while [ "$(jobs -p | wc -l)" -ge $MAX_PARALLEL ]; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
if screen -list | grep -q "$sim_name"; then
|
||||
echo "${SYM_OK} ${COLOR_STOP}Stoppe ${COLOR_SERVER}$sim_name${COLOR_RESET}"
|
||||
(
|
||||
screen -S "$sim_name" -p 0 -X stuff "shutdown^M"
|
||||
sleep $Simulator_Stop_wait
|
||||
) &
|
||||
fi
|
||||
done
|
||||
wait # Warte auf alle parallelen Stopp-Vorgänge
|
||||
|
||||
# 2. Sim1 sequentiell stoppen
|
||||
if screen -list | grep -q "sim1"; then
|
||||
echo "${SYM_OK} ${COLOR_STOP}Stoppe ${COLOR_SERVER}sim1${COLOR_RESET} ${COLOR_STOP}(primäre Region)...${COLOR_RESET}"
|
||||
screen -S "sim1" -p 0 -X stuff "shutdown^M"
|
||||
sleep $Simulator_Stop_wait
|
||||
fi
|
||||
|
||||
# 3. MoneyServer stoppen
|
||||
if screen -list | grep -q "moneyserver"; then
|
||||
echo "${SYM_OK} ${COLOR_STOP}Stoppe ${COLOR_SERVER}MoneyServer${COLOR_RESET} ${COLOR_STOP}...${COLOR_RESET}"
|
||||
screen -S moneyserver -p 0 -X stuff "shutdown^M"
|
||||
sleep $MoneyServer_Stop_wait
|
||||
else
|
||||
echo "${SYM_BAD} ${COLOR_SERVER}MoneyServer: ${COLOR_BAD}Läuft nicht.${COLOR_RESET}"
|
||||
fi
|
||||
|
||||
# 4. RobustServer stoppen (zuletzt)
|
||||
if screen -list | grep -q "robustserver"; then
|
||||
echo "${SYM_OK} ${COLOR_STOP}Stoppe ${COLOR_SERVER}RobustServer${COLOR_RESET} ${COLOR_STOP}...${COLOR_RESET}"
|
||||
screen -S robustserver -p 0 -X stuff "shutdown^M"
|
||||
sleep $RobustServer_Stop_wait
|
||||
else
|
||||
echo "${SYM_BAD} ${COLOR_SERVER}RobustServer: ${COLOR_BAD}Läuft nicht.${COLOR_RESET}"
|
||||
fi
|
||||
|
||||
echo "${SYM_OK} ${COLOR_STOP}Alle Dienste gestoppt.${COLOR_RESET}"
|
||||
echo .
|
||||
}
|
||||
|
||||
# check_screens ist eine Grid Funktion und funktioniert nicht im Standalone.
|
||||
# bash osmtool_backup.sh check_screens
|
||||
function check_screens() {
|
||||
# echo "Überprüfung der laufenden OpenSim-Prozesse..."
|
||||
|
||||
restart_all=false
|
||||
|
||||
# Überprüfen, ob RobustServer läuft
|
||||
if [[ -d "robust/bin" && -f "robust/bin/Robust.dll" ]]; then
|
||||
screenRO=$(screen -ls | grep -w "robustserver")
|
||||
if [[ -z "$screenRO" ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - RobustServer läuft nicht und muss neu gestartet werden." >> ProblemRestarts.log
|
||||
restart_all=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Überprüfen, ob MoneyServer läuft
|
||||
if [[ -d "robust/bin" && -f "robust/bin/MoneyServer.dll" ]];then
|
||||
screenMoney=$(screen -ls | grep -w "moneyserver")
|
||||
if [[ -z "$screenMoney" ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - MoneyServer läuft nicht und muss neu gestartet werden." >> ProblemRestarts.log
|
||||
restart_all=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Überprüfen, ob sim1 läuft
|
||||
if [[ -d "sim1/bin" && -f "sim1/bin/OpenSim.dll" ]]; then
|
||||
screenSim1=$(screen -ls | grep -w "sim1")
|
||||
if [[ -z "$screenSim1" ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - Sim1 läuft nicht und muss neu gestartet werden." >> ProblemRestarts.log
|
||||
restart_all=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Falls eines der kritischen Systeme ausgefallen ist, alles neu starten
|
||||
if [[ "$restart_all" == true ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - Kritische Prozesse sind ausgefallen! OpenSim wird komplett neu gestartet." >> ProblemRestarts.log
|
||||
# opensimstart
|
||||
opensimrestart
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Überprüfen, ob andere Regionen (sim2 bis sim999) einzeln neu gestartet werden müssen
|
||||
for ((i=2; i<=999; i++)); do
|
||||
sim_dir="sim$i/bin"
|
||||
if [[ -d "$sim_dir" && -f "$sim_dir/OpenSim.dll" ]]; then
|
||||
screenSim=$(screen -ls | grep -w "sim$i")
|
||||
if [[ -z "$screenSim" ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - Sim$i läuft nicht und wird einzeln neu gestartet." >> ProblemRestarts.log
|
||||
cd "$sim_dir" || continue
|
||||
screen -fa -S "sim$i" -d -U -m dotnet OpenSim.dll
|
||||
cd - >/dev/null 2>&1 || continue
|
||||
sleep $Simulator_Start_wait
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo .
|
||||
}
|
||||
|
||||
# Neu Test
|
||||
function check_screens_neu() {
|
||||
echo "${SYM_WAIT} ${COLOR_START}Überprüfe laufende OpenSim-Prozesse...${COLOR_RESET}"
|
||||
restart_all=false
|
||||
log_file="ProblemRestarts.log"
|
||||
|
||||
timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
# Funktion zum Screen-Check
|
||||
function screen_running() {
|
||||
screen -ls | grep -qw "$1"
|
||||
}
|
||||
|
||||
# RobustServer prüfen
|
||||
if [[ -d "robust/bin" && -f "robust/bin/Robust.dll" ]]; then
|
||||
if ! screen_running "robustserver"; then
|
||||
echo "$timestamp - RobustServer läuft nicht." >> "$log_file"
|
||||
restart_all=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# MoneyServer prüfen
|
||||
if [[ -f "robust/bin/MoneyServer.dll" ]]; then
|
||||
if ! screen_running "moneyserver"; then
|
||||
echo "$timestamp - MoneyServer läuft nicht." >> "$log_file"
|
||||
restart_all=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# sim1 prüfen
|
||||
if [[ -d "sim1/bin" && -f "sim1/bin/OpenSim.dll" ]]; then
|
||||
if ! screen_running "sim1"; then
|
||||
echo "$timestamp - sim1 läuft nicht." >> "$log_file"
|
||||
restart_all=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Falls kritische Komponenten fehlen → kompletten Neustart
|
||||
if [[ "$restart_all" == true ]]; then
|
||||
echo "$timestamp - Kritische Komponenten fehlen. Starte das gesamte Grid neu." >> "$log_file"
|
||||
opensimrestart
|
||||
return 0
|
||||
fi
|
||||
|
||||
# sim2 bis sim999 einzeln prüfen und ggf. neu starten
|
||||
for ((i=2; i<=999; i++)); do
|
||||
sim_dir="sim$i/bin"
|
||||
if [[ -d "$sim_dir" && -f "$sim_dir/OpenSim.dll" ]]; then
|
||||
if ! screen_running "sim$i"; then
|
||||
echo "$timestamp - sim$i läuft nicht. Starte Region neu." >> "$log_file"
|
||||
cd "$sim_dir" || continue
|
||||
screen -fa -S "sim$i" -d -U -m dotnet OpenSim.dll
|
||||
cd - >/dev/null 2>&1 || continue
|
||||
sleep $Simulator_Start_wait
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${SYM_OK} ${COLOR_START}Überprüfung abgeschlossen.${COLOR_RESET}"
|
||||
screen -ls || echo "Keine Screen-Sessions gefunden"
|
||||
}
|
||||
|
||||
|
||||
function opensimrestart() {
|
||||
opensimstop
|
||||
sleep $Simulator_Stop_wait # Wartezeit für Dienst-Stopp
|
||||
opensimstart
|
||||
screen -ls || echo "Keine Screen-Sessions gefunden"
|
||||
}
|
||||
|
||||
|
||||
KOMMANDO="$1"
|
||||
|
||||
case $KOMMANDO in
|
||||
"start")
|
||||
opensimstart
|
||||
;;
|
||||
"stop")
|
||||
opensimstop
|
||||
;;
|
||||
"restart")
|
||||
opensimrestart
|
||||
;;
|
||||
"check_screens")
|
||||
check_screens_neu
|
||||
;;
|
||||
*)
|
||||
opensimrestart
|
||||
;;
|
||||
esac
|
||||
# Ende des Skripts
|
||||
@@ -0,0 +1,77 @@
|
||||
# OSMTool Web PHP (DE/EN/FR/ES)
|
||||
|
||||
This folder contains a minimal and secure PHP web controller for `osmtool_main.sh`.
|
||||
|
||||
## Features
|
||||
|
||||
- Login-protected web UI
|
||||
- Language switch: `de`, `en`, `fr`, `es`
|
||||
- CSRF protection
|
||||
- Whitelisted actions only
|
||||
- Runner script wrapper for safer command execution
|
||||
|
||||
## File Layout
|
||||
|
||||
- `public/index.php` - web UI and request handling
|
||||
- `src/bootstrap.php` - session, auth helpers, CSRF
|
||||
- `src/i18n.php` - translations
|
||||
- `src/runner.php` - command whitelist and execution
|
||||
- `src/config.sample.php` - configuration template
|
||||
- `bin/osmtool_web_runner.sh` - controlled bridge to `osmtool_main.sh`
|
||||
|
||||
## Setup
|
||||
|
||||
1. Typical Linux deploy path:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /var/www/html/osmtool-web
|
||||
sudo cp -a webphp/. /var/www/html/osmtool-web/
|
||||
sudo chown -R www-data:www-data /var/www/html/osmtool-web
|
||||
```
|
||||
|
||||
1. Edit config values:
|
||||
|
||||
```bash
|
||||
nano /var/www/html/osmtool-web/src/config.php
|
||||
```
|
||||
|
||||
1. Set execute bit for runner and main script:
|
||||
|
||||
```bash
|
||||
chmod +x /var/www/html/osmtool-web/bin/osmtool_web_runner.sh
|
||||
chmod +x /opt/opensimMULTITOOLS-II/osmtool_main.sh
|
||||
```
|
||||
|
||||
1. Configure web server document root to:
|
||||
|
||||
```text
|
||||
/var/www/html/osmtool-web/public
|
||||
```
|
||||
|
||||
1. Open in browser and log in with `web_password` from config.
|
||||
|
||||
## Sudoers Example (recommended)
|
||||
|
||||
Use `visudo` and allow only the web runner:
|
||||
|
||||
```text
|
||||
www-data ALL=(manni) NOPASSWD: /var/www/html/osmtool-web/bin/osmtool_web_runner.sh
|
||||
```
|
||||
|
||||
Then keep `use_sudo=true` and `sudo_user=manni` in config.
|
||||
|
||||
## Supported Actions
|
||||
|
||||
- `start`
|
||||
- `stop`
|
||||
- `restart`
|
||||
- `smoke`
|
||||
- `report`
|
||||
- `health`
|
||||
- `cron-list`
|
||||
|
||||
## Notes
|
||||
|
||||
- Do not expose this UI publicly without HTTPS and IP restrictions.
|
||||
- Keep the password strong and unique.
|
||||
- Extend actions only in `src/runner.php` and `bin/osmtool_web_runner.sh` together.
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
MAIN_SCRIPT="$PROJECT_ROOT/osmtool_main.sh"
|
||||
|
||||
if [[ ! -x "$MAIN_SCRIPT" ]]; then
|
||||
echo "ERROR: osmtool_main.sh not executable: $MAIN_SCRIPT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ACTION="${1:-}"
|
||||
PROFILE="${2:-grid-sim}"
|
||||
LANG="${3:-de}"
|
||||
WORKDIR="${4:-/opt}"
|
||||
|
||||
case "$PROFILE" in
|
||||
grid-sim|robust|standalone) ;;
|
||||
*) echo "ERROR: invalid profile" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
case "$LANG" in
|
||||
de|en|fr|es) ;;
|
||||
*) echo "ERROR: invalid language" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
run_main() {
|
||||
bash "$MAIN_SCRIPT" --mode cli --profile "$PROFILE" --lang "$LANG" --workdir "$WORKDIR" "$@"
|
||||
}
|
||||
|
||||
case "$ACTION" in
|
||||
start)
|
||||
run_main --module startstop --action start
|
||||
;;
|
||||
stop)
|
||||
run_main --module startstop --action stop
|
||||
;;
|
||||
restart)
|
||||
run_main --module startstop --action restart
|
||||
;;
|
||||
smoke)
|
||||
run_main --module smoke --action run
|
||||
;;
|
||||
report)
|
||||
run_main --module report --action generate
|
||||
;;
|
||||
health)
|
||||
run_main --module health --action run
|
||||
;;
|
||||
cron-list)
|
||||
run_main --module cron --action list
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unsupported action" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../src/bootstrap.php';
|
||||
require_once __DIR__ . '/../src/runner.php';
|
||||
|
||||
$lang = detect_lang(supported_languages());
|
||||
$_SESSION['lang'] = $lang;
|
||||
|
||||
$message = '';
|
||||
$messageType = 'ok';
|
||||
$resultOutput = '';
|
||||
$resultCode = null;
|
||||
|
||||
if (isset($_GET['logout'])) {
|
||||
$_SESSION = [];
|
||||
session_destroy();
|
||||
header('Location: index.php?lang=' . urlencode($lang));
|
||||
exit;
|
||||
}
|
||||
|
||||
if (($_POST['form'] ?? '') === 'login') {
|
||||
$postedLang = detect_lang(supported_languages());
|
||||
$_SESSION['lang'] = $postedLang;
|
||||
$lang = $postedLang;
|
||||
|
||||
if (!verify_csrf($_POST['csrf'] ?? null)) {
|
||||
$message = t($lang, 'csrf_error');
|
||||
$messageType = 'error';
|
||||
} else {
|
||||
$password = (string)($_POST['password'] ?? '');
|
||||
$expected = (string)($config['web_password'] ?? '');
|
||||
if ($expected !== '' && hash_equals($expected, $password)) {
|
||||
$_SESSION['auth'] = true;
|
||||
header('Location: index.php?lang=' . urlencode($lang));
|
||||
exit;
|
||||
}
|
||||
$message = t($lang, 'invalid_login');
|
||||
$messageType = 'error';
|
||||
}
|
||||
}
|
||||
|
||||
if (is_logged_in() && (($_POST['form'] ?? '') === 'run')) {
|
||||
if (!verify_csrf($_POST['csrf'] ?? null)) {
|
||||
$message = t($lang, 'csrf_error');
|
||||
$messageType = 'error';
|
||||
} else {
|
||||
$action = (string)($_POST['action'] ?? '');
|
||||
$profile = (string)($_POST['profile'] ?? 'grid-sim');
|
||||
$workdir = (string)($_POST['workdir'] ?? (string)($config['default_workdir'] ?? '/opt'));
|
||||
|
||||
$result = run_whitelisted_action($config, $action, $profile, $lang, $workdir);
|
||||
$resultOutput = (string)($result['output'] ?? '');
|
||||
$resultCode = (int)($result['exitCode'] ?? 1);
|
||||
|
||||
if (($result['ok'] ?? false) === true) {
|
||||
$message = t($lang, 'status_ok') . ' (exit=' . $resultCode . ')';
|
||||
$messageType = 'ok';
|
||||
} else {
|
||||
$message = t($lang, 'status_error') . ' (exit=' . $resultCode . ')';
|
||||
$messageType = 'error';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$actions = [
|
||||
'start' => t($lang, 'action_start'),
|
||||
'stop' => t($lang, 'action_stop'),
|
||||
'restart' => t($lang, 'action_restart'),
|
||||
'smoke' => t($lang, 'action_smoke'),
|
||||
'report' => t($lang, 'action_report'),
|
||||
'health' => t($lang, 'action_health'),
|
||||
'cron-list' => t($lang, 'action_cron_list'),
|
||||
];
|
||||
|
||||
$profiles = [
|
||||
'grid-sim' => 'grid-sim',
|
||||
'robust' => 'robust',
|
||||
'standalone' => 'standalone',
|
||||
];
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= h($lang) ?>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title><?= h(t($lang, 'title')) ?></title>
|
||||
<style>
|
||||
:root {
|
||||
--bg1: #0f172a;
|
||||
--bg2: #1e293b;
|
||||
--card: #111827;
|
||||
--line: #334155;
|
||||
--text: #e5e7eb;
|
||||
--muted: #94a3b8;
|
||||
--ok: #16a34a;
|
||||
--err: #dc2626;
|
||||
--btn: #0284c7;
|
||||
--btnHover: #0369a1;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", Tahoma, sans-serif;
|
||||
background: radial-gradient(1000px 600px at 20% 0%, #1d4ed8 0%, transparent 60%),
|
||||
radial-gradient(900px 500px at 100% 100%, #0ea5e9 0%, transparent 50%),
|
||||
linear-gradient(160deg, var(--bg1), var(--bg2));
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
padding: 24px;
|
||||
}
|
||||
.wrap { max-width: 980px; margin: 0 auto; }
|
||||
.card {
|
||||
background: color-mix(in oklab, var(--card), black 8%);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
padding: 18px;
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,.25);
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
h1 { margin: 0 0 8px; font-size: 1.7rem; }
|
||||
p { margin: 0 0 12px; color: var(--muted); }
|
||||
.topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
label { display: block; margin-bottom: 6px; font-weight: 600; }
|
||||
input, select, button {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--line);
|
||||
background: #0b1220;
|
||||
color: var(--text);
|
||||
padding: 10px 12px;
|
||||
}
|
||||
button {
|
||||
background: var(--btn);
|
||||
border: none;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover { background: var(--btnHover); }
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.full { grid-column: 1 / -1; }
|
||||
.msg {
|
||||
margin: 10px 0;
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.ok { background: rgba(22,163,74,.2); border: 1px solid rgba(22,163,74,.5); }
|
||||
.error { background: rgba(220,38,38,.2); border: 1px solid rgba(220,38,38,.5); }
|
||||
pre {
|
||||
background: #020617;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
overflow: auto;
|
||||
max-height: 420px;
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.lang-links a {
|
||||
color: #bae6fd;
|
||||
margin-right: 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.lang-links a:hover { text-decoration: underline; }
|
||||
@media (max-width: 800px) {
|
||||
.grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
<div class="topbar">
|
||||
<div>
|
||||
<h1><?= h(t($lang, 'title')) ?></h1>
|
||||
<p><?= h(t($lang, 'subtitle')) ?></p>
|
||||
</div>
|
||||
<div class="lang-links">
|
||||
<a href="?lang=de">DE</a>
|
||||
<a href="?lang=en">EN</a>
|
||||
<a href="?lang=fr">FR</a>
|
||||
<a href="?lang=es">ES</a>
|
||||
<?php if (is_logged_in()): ?>
|
||||
| <a href="?logout=1&lang=<?= h($lang) ?>"><?= h(t($lang, 'logout')) ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($message !== ''): ?>
|
||||
<div class="msg <?= h($messageType) ?>"><?= h($message) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!is_logged_in()): ?>
|
||||
<form method="post">
|
||||
<input type="hidden" name="form" value="login">
|
||||
<input type="hidden" name="csrf" value="<?= h(csrf_token()) ?>">
|
||||
<input type="hidden" name="lang" value="<?= h($lang) ?>">
|
||||
<div class="grid">
|
||||
<div class="full">
|
||||
<label><?= h(t($lang, 'password')) ?></label>
|
||||
<input type="password" name="password" autocomplete="current-password" required>
|
||||
</div>
|
||||
<div class="full">
|
||||
<button type="submit"><?= h(t($lang, 'login')) ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<p><?= h(t($lang, 'hint')) ?></p>
|
||||
<form method="post">
|
||||
<input type="hidden" name="form" value="run">
|
||||
<input type="hidden" name="csrf" value="<?= h(csrf_token()) ?>">
|
||||
<input type="hidden" name="lang" value="<?= h($lang) ?>">
|
||||
|
||||
<div class="grid">
|
||||
<div>
|
||||
<label><?= h(t($lang, 'profile')) ?></label>
|
||||
<select name="profile" required>
|
||||
<?php foreach ($profiles as $value => $label): ?>
|
||||
<option value="<?= h($value) ?>"><?= h($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label><?= h(t($lang, 'action')) ?></label>
|
||||
<select name="action" required>
|
||||
<?php foreach ($actions as $value => $label): ?>
|
||||
<option value="<?= h($value) ?>"><?= h($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="full">
|
||||
<label><?= h(t($lang, 'workdir')) ?></label>
|
||||
<input name="workdir" value="<?= h((string)($config['default_workdir'] ?? '/opt')) ?>">
|
||||
</div>
|
||||
<div class="full">
|
||||
<button type="submit"><?= h(t($lang, 'execute')) ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if ($resultCode !== null): ?>
|
||||
<div class="card" style="margin-top:14px;">
|
||||
<label><?= h(t($lang, 'output')) ?></label>
|
||||
<pre><?= h($resultOutput) ?></pre>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
$configFile = __DIR__ . '/config.php';
|
||||
if (!is_file($configFile)) {
|
||||
$configFile = __DIR__ . '/config.sample.php';
|
||||
}
|
||||
|
||||
$config = require $configFile;
|
||||
|
||||
if (!isset($config['session_key']) || !is_string($config['session_key'])) {
|
||||
throw new RuntimeException('Missing session_key in config.');
|
||||
}
|
||||
|
||||
session_name('osmtool_web');
|
||||
session_set_cookie_params([
|
||||
'lifetime' => 0,
|
||||
'path' => '/',
|
||||
'secure' => false,
|
||||
'httponly' => true,
|
||||
'samesite' => 'Strict',
|
||||
]);
|
||||
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['session_seed'])) {
|
||||
$_SESSION['session_seed'] = hash('sha256', $config['session_key'] . random_int(1000, 999999));
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/i18n.php';
|
||||
|
||||
function is_logged_in(): bool
|
||||
{
|
||||
return isset($_SESSION['auth']) && $_SESSION['auth'] === true;
|
||||
}
|
||||
|
||||
function require_login(): void
|
||||
{
|
||||
if (!is_logged_in()) {
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function csrf_token(): string
|
||||
{
|
||||
if (!isset($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
return $_SESSION['csrf_token'];
|
||||
}
|
||||
|
||||
function verify_csrf(?string $token): bool
|
||||
{
|
||||
if (!isset($_SESSION['csrf_token']) || !is_string($token)) {
|
||||
return false;
|
||||
}
|
||||
return hash_equals($_SESSION['csrf_token'], $token);
|
||||
}
|
||||
|
||||
function h(string $value): string
|
||||
{
|
||||
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'session_key' => 'change-me-super-random-session-key',
|
||||
'web_password' => 'ChangeMeNow-2026',
|
||||
// Default assumes deployment under /var/www/html/osmtool-web
|
||||
'runner_path' => realpath(__DIR__ . '/../bin/osmtool_web_runner.sh') ?: (__DIR__ . '/../bin/osmtool_web_runner.sh'),
|
||||
'command_timeout_seconds' => 120,
|
||||
'default_workdir' => '/opt',
|
||||
'use_sudo' => true,
|
||||
'sudo_user' => 'manni',
|
||||
];
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
// Set this to a strong random value in production.
|
||||
'session_key' => 'change-me-super-random-session-key',
|
||||
|
||||
// Default login password. Replace immediately in production.
|
||||
'web_password' => 'ChangeMeNow-2026',
|
||||
|
||||
// Default assumes deployment under /var/www/html/osmtool-web.
|
||||
// You can keep this dynamic path or set an absolute path manually.
|
||||
'runner_path' => realpath(__DIR__ . '/../bin/osmtool_web_runner.sh') ?: (__DIR__ . '/../bin/osmtool_web_runner.sh'),
|
||||
|
||||
// Web timeout in seconds.
|
||||
'command_timeout_seconds' => 120,
|
||||
|
||||
// Default workdir passed to osmtool_main.sh.
|
||||
'default_workdir' => '/opt',
|
||||
|
||||
// Allow running through sudo if needed.
|
||||
'use_sudo' => true,
|
||||
|
||||
// If use_sudo=true, command becomes: sudo -n <sudo_user> <runner>
|
||||
// Example: www-data (Linux) or your service account.
|
||||
'sudo_user' => 'manni',
|
||||
];
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
function supported_languages(): array
|
||||
{
|
||||
return ['de', 'en', 'fr', 'es'];
|
||||
}
|
||||
|
||||
function translations(): array
|
||||
{
|
||||
return [
|
||||
'de' => [
|
||||
'title' => 'OSMTool Web Steuerung',
|
||||
'subtitle' => 'Sichere Web-Oberflaeche fuer OpenSim Aktionen',
|
||||
'login_title' => 'Anmeldung',
|
||||
'password' => 'Passwort',
|
||||
'login' => 'Einloggen',
|
||||
'logout' => 'Ausloggen',
|
||||
'language' => 'Sprache',
|
||||
'profile' => 'Profil',
|
||||
'action' => 'Aktion',
|
||||
'execute' => 'Ausfuehren',
|
||||
'workdir' => 'Workdir',
|
||||
'output' => 'Ausgabe',
|
||||
'status_ok' => 'Erfolgreich',
|
||||
'status_error' => 'Fehler',
|
||||
'invalid_login' => 'Anmeldung fehlgeschlagen.',
|
||||
'csrf_error' => 'Ungueltiges Formular-Token.',
|
||||
'not_allowed' => 'Aktion nicht erlaubt.',
|
||||
'run_failed' => 'Ausfuehrung fehlgeschlagen.',
|
||||
'hint' => 'Es werden nur freigegebene Aktionen ausgefuehrt.',
|
||||
'action_start' => 'Start',
|
||||
'action_stop' => 'Stop',
|
||||
'action_restart' => 'Neustart',
|
||||
'action_smoke' => 'Smoke-Test',
|
||||
'action_report' => 'Report erzeugen',
|
||||
'action_health' => 'Healthcheck',
|
||||
'action_cron_list' => 'Cronjobs anzeigen',
|
||||
],
|
||||
'en' => [
|
||||
'title' => 'OSMTool Web Control',
|
||||
'subtitle' => 'Secure web interface for OpenSim actions',
|
||||
'login_title' => 'Login',
|
||||
'password' => 'Password',
|
||||
'login' => 'Sign in',
|
||||
'logout' => 'Sign out',
|
||||
'language' => 'Language',
|
||||
'profile' => 'Profile',
|
||||
'action' => 'Action',
|
||||
'execute' => 'Execute',
|
||||
'workdir' => 'Workdir',
|
||||
'output' => 'Output',
|
||||
'status_ok' => 'Success',
|
||||
'status_error' => 'Error',
|
||||
'invalid_login' => 'Login failed.',
|
||||
'csrf_error' => 'Invalid form token.',
|
||||
'not_allowed' => 'Action not allowed.',
|
||||
'run_failed' => 'Execution failed.',
|
||||
'hint' => 'Only whitelisted actions are executed.',
|
||||
'action_start' => 'Start',
|
||||
'action_stop' => 'Stop',
|
||||
'action_restart' => 'Restart',
|
||||
'action_smoke' => 'Smoke test',
|
||||
'action_report' => 'Generate report',
|
||||
'action_health' => 'Health check',
|
||||
'action_cron_list' => 'List cron jobs',
|
||||
],
|
||||
'fr' => [
|
||||
'title' => 'Controle Web OSMTool',
|
||||
'subtitle' => 'Interface web securisee pour les actions OpenSim',
|
||||
'login_title' => 'Connexion',
|
||||
'password' => 'Mot de passe',
|
||||
'login' => 'Se connecter',
|
||||
'logout' => 'Se deconnecter',
|
||||
'language' => 'Langue',
|
||||
'profile' => 'Profil',
|
||||
'action' => 'Action',
|
||||
'execute' => 'Executer',
|
||||
'workdir' => 'Repertoire de travail',
|
||||
'output' => 'Sortie',
|
||||
'status_ok' => 'Succes',
|
||||
'status_error' => 'Erreur',
|
||||
'invalid_login' => 'Echec de connexion.',
|
||||
'csrf_error' => 'Jeton de formulaire invalide.',
|
||||
'not_allowed' => 'Action non autorisee.',
|
||||
'run_failed' => 'Execution echouee.',
|
||||
'hint' => 'Seules les actions en liste blanche sont executees.',
|
||||
'action_start' => 'Demarrer',
|
||||
'action_stop' => 'Arreter',
|
||||
'action_restart' => 'Redemarrer',
|
||||
'action_smoke' => 'Test smoke',
|
||||
'action_report' => 'Generer un rapport',
|
||||
'action_health' => 'Controle de sante',
|
||||
'action_cron_list' => 'Lister les cron jobs',
|
||||
],
|
||||
'es' => [
|
||||
'title' => 'Control Web OSMTool',
|
||||
'subtitle' => 'Interfaz web segura para acciones de OpenSim',
|
||||
'login_title' => 'Inicio de sesion',
|
||||
'password' => 'Contrasena',
|
||||
'login' => 'Entrar',
|
||||
'logout' => 'Salir',
|
||||
'language' => 'Idioma',
|
||||
'profile' => 'Perfil',
|
||||
'action' => 'Accion',
|
||||
'execute' => 'Ejecutar',
|
||||
'workdir' => 'Directorio de trabajo',
|
||||
'output' => 'Salida',
|
||||
'status_ok' => 'Correcto',
|
||||
'status_error' => 'Error',
|
||||
'invalid_login' => 'Error de inicio de sesion.',
|
||||
'csrf_error' => 'Token de formulario invalido.',
|
||||
'not_allowed' => 'Accion no permitida.',
|
||||
'run_failed' => 'La ejecucion fallo.',
|
||||
'hint' => 'Solo se ejecutan acciones permitidas.',
|
||||
'action_start' => 'Iniciar',
|
||||
'action_stop' => 'Detener',
|
||||
'action_restart' => 'Reiniciar',
|
||||
'action_smoke' => 'Prueba smoke',
|
||||
'action_report' => 'Generar informe',
|
||||
'action_health' => 'Chequeo de salud',
|
||||
'action_cron_list' => 'Listar cron jobs',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
function detect_lang(array $supported): string
|
||||
{
|
||||
$lang = $_GET['lang'] ?? $_POST['lang'] ?? $_SESSION['lang'] ?? 'de';
|
||||
if (!is_string($lang) || !in_array($lang, $supported, true)) {
|
||||
return 'de';
|
||||
}
|
||||
return $lang;
|
||||
}
|
||||
|
||||
function t(string $lang, string $key): string
|
||||
{
|
||||
$all = translations();
|
||||
return $all[$lang][$key] ?? $all['en'][$key] ?? $key;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
function allowed_profiles(): array
|
||||
{
|
||||
return ['grid-sim', 'robust', 'standalone'];
|
||||
}
|
||||
|
||||
function allowed_actions(): array
|
||||
{
|
||||
return ['start', 'stop', 'restart', 'smoke', 'report', 'health', 'cron-list'];
|
||||
}
|
||||
|
||||
function build_command(array $config, string $action, string $profile, string $lang, string $workdir): array
|
||||
{
|
||||
$runnerPath = (string)($config['runner_path'] ?? '');
|
||||
if ($runnerPath === '') {
|
||||
throw new RuntimeException('runner_path missing in config.');
|
||||
}
|
||||
|
||||
$base = [];
|
||||
$useSudo = (bool)($config['use_sudo'] ?? false);
|
||||
if ($useSudo) {
|
||||
$sudoUser = (string)($config['sudo_user'] ?? '');
|
||||
if ($sudoUser === '') {
|
||||
throw new RuntimeException('sudo_user missing in config.');
|
||||
}
|
||||
$base = ['sudo', '-n', '-u', $sudoUser];
|
||||
}
|
||||
|
||||
return array_merge($base, [$runnerPath, $action, $profile, $lang, $workdir]);
|
||||
}
|
||||
|
||||
function run_whitelisted_action(array $config, string $action, string $profile, string $lang, string $workdir): array
|
||||
{
|
||||
if (!in_array($action, allowed_actions(), true)) {
|
||||
return ['ok' => false, 'exitCode' => 2, 'output' => "ERROR: action not allowed\n"];
|
||||
}
|
||||
|
||||
if (!in_array($profile, allowed_profiles(), true)) {
|
||||
return ['ok' => false, 'exitCode' => 2, 'output' => "ERROR: invalid profile\n"];
|
||||
}
|
||||
|
||||
if (!in_array($lang, supported_languages(), true)) {
|
||||
return ['ok' => false, 'exitCode' => 2, 'output' => "ERROR: invalid language\n"];
|
||||
}
|
||||
|
||||
$workdirClean = trim($workdir);
|
||||
if ($workdirClean === '') {
|
||||
$workdirClean = (string)($config['default_workdir'] ?? '/opt');
|
||||
}
|
||||
|
||||
$cmd = build_command($config, $action, $profile, $lang, $workdirClean);
|
||||
$descriptorSpec = [
|
||||
0 => ['pipe', 'r'],
|
||||
1 => ['pipe', 'w'],
|
||||
2 => ['pipe', 'w'],
|
||||
];
|
||||
|
||||
$process = proc_open($cmd, $descriptorSpec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
return ['ok' => false, 'exitCode' => 1, 'output' => "ERROR: unable to start process\n"];
|
||||
}
|
||||
|
||||
fclose($pipes[0]);
|
||||
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
$exitCode = proc_close($process);
|
||||
$output = (string)$stdout . (string)$stderr;
|
||||
|
||||
return ['ok' => $exitCode === 0, 'exitCode' => $exitCode, 'output' => $output];
|
||||
}
|
||||
Reference in New Issue
Block a user