mirror of
https://github.com/ManfredAabye/opensimMULTITOOLS-II.git
synced 2026-08-14 00:47:58 +00:00
200420261134
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 ManfredAabye
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 ManfredAabye
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -1,201 +1,201 @@
|
||||
# opensimMULTITOOL II V26.4.230.588
|
||||
|
||||
Diese README ist fuer Einsteiger geschrieben.
|
||||
|
||||
Wenn du noch nie mit OpenSim oder Bash gearbeitet hast, starte mit den Schritten in diesem Dokument von oben nach unten.
|
||||
|
||||
## 1. Was ist dieses Projekt?
|
||||
|
||||
opensimMULTITOOLS-II hilft dir, einen OpenSim-Server zu:
|
||||
|
||||
- installieren
|
||||
- starten und stoppen
|
||||
- neu starten
|
||||
- sichern (Backups)
|
||||
- warten und pruefen
|
||||
|
||||
Das Projekt besteht aus zwei Hauptteilen:
|
||||
|
||||
- CLI-Skripte (Konsole): fuer Administration per Terminal
|
||||
- Web-Oberflaeche unter webphp/: fuer Bedienung im Browser
|
||||
|
||||
Voraussetzungen
|
||||
|
||||
- Linux Server
|
||||
|
||||
## 2. Wichtige Sicherheitshinweise
|
||||
|
||||
- Vor groesseren Aktionen immer Backup machen.
|
||||
- Erst in einer Testumgebung pruefen, dann auf Produktivsystem nutzen.
|
||||
- Die Web-Oberflaeche nur mit HTTPS und moeglichst mit IP-Einschraenkung betreiben.
|
||||
- Standard-Passwoerter sofort aendern.
|
||||
|
||||
## 3. Projektstruktur (kurz erklaert)
|
||||
|
||||
- osmtool_main.sh: Hauptstarter fuer Module und Aktionen
|
||||
- modular/: einzelne Fachmodule (install, startstop, backup, restore, ...)
|
||||
- webphp/: Web-Oberflaeche (PHP)
|
||||
- osmtool.sh: klassisches Hauptskript mit vielen Direktfunktionen
|
||||
|
||||
## 4. Schnellstart fuer Einsteiger (CLI)
|
||||
|
||||
Voraussetzung: Du arbeitest auf Linux und hast Zugriff auf das Projektverzeichnis.
|
||||
|
||||
### Schritt 1: In das Projektverzeichnis wechseln
|
||||
|
||||
```bash
|
||||
cd /opt/opensimMULTITOOLS-II
|
||||
```
|
||||
|
||||
### Schritt 2: Ubuntu vorbereiten
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh install-grid-sim
|
||||
```
|
||||
|
||||
Hinweis: `install-grid-sim` fuehrt die komplette Installationskette fuer `grid-sim` aus.
|
||||
|
||||
### Schritt 3: OpenSim-Abhaengigkeiten installieren
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh install-grid-sim
|
||||
```
|
||||
|
||||
### Schritt 4: Server-Check ausfuehren
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh healthcheck
|
||||
```
|
||||
|
||||
### Schritt 5: OpenSim installieren und konfigurieren
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh install-grid-sim
|
||||
```
|
||||
|
||||
### Schritt 6: Datenbank einrichten
|
||||
|
||||
```bash
|
||||
export OSM_DB_PASS='DEIN_PASSWORT'
|
||||
bash osmtool_main.sh dbsetup
|
||||
```
|
||||
|
||||
### Schritt 7: Grid starten
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh opensimrestart
|
||||
```
|
||||
|
||||
## 5. Alltagsbefehle (die wichtigsten)
|
||||
|
||||
```bash
|
||||
# Grid neu starten
|
||||
bash osmtool_main.sh opensimrestart
|
||||
|
||||
# Robust-Datenbank sichern
|
||||
export OSM_DB_PASS='DEIN_PASSWORT'
|
||||
bash osmtool_main.sh dbbackup
|
||||
|
||||
# Cronjobs installieren (automatische Backups/Checks)
|
||||
bash osmtool_main.sh croninstall
|
||||
```
|
||||
|
||||
Unterstuetzte Kurzbefehle (Ein-Wort-Aufruf):
|
||||
|
||||
- install-grid-sim
|
||||
- opensimstart
|
||||
- opensimstop
|
||||
- opensimrestart
|
||||
- healthcheck
|
||||
- smoketest
|
||||
- dailyreport
|
||||
- croninstall
|
||||
- cronlist
|
||||
- janusinstall
|
||||
- janusrestart
|
||||
- dbsetup
|
||||
- dbbackup
|
||||
|
||||
## 6. Web-Oberflaeche (webphp)
|
||||
|
||||
Die Web-Oberflaeche ist in webphp/ enthalten und zeigt unter anderem:
|
||||
|
||||
- Modulaktionen
|
||||
- Kommando-Vorschau
|
||||
- Ausgabe der Befehle
|
||||
- Live-Status (Screens, Ports, Artefakte)
|
||||
|
||||
Detaillierte Web-Anleitung: webphp/README.md
|
||||
|
||||
### Wichtige Konfigurationsregel
|
||||
|
||||
Fuer die aktive Web-Konfiguration gilt:
|
||||
|
||||
- webphp/src/config.php = wird wirklich benutzt
|
||||
- webphp/src/config.sample.php = nur Vorlage
|
||||
|
||||
Wenn du Ports oder Screens fuer den Live-Status aendern willst, musst du in config.php anpassen.
|
||||
|
||||
## 7. Login-Sicherheit der Web-Oberflaeche
|
||||
|
||||
Die Web-Oberflaeche hat einen Schutz gegen Brute-Force-Logins:
|
||||
|
||||
- Nach mehreren falschen Passwortversuchen wird die IP temporaer gesperrt.
|
||||
- Sperrzeit und Schwelle sind konfigurierbar.
|
||||
- Login-Ereignisse koennen in einer Audit-Logdatei gespeichert werden.
|
||||
|
||||
Wichtige Einstellungen in webphp/src/config.php:
|
||||
|
||||
- auth_lockout_max_attempts
|
||||
- auth_lockout_seconds
|
||||
- optional: auth_store_path
|
||||
- optional: auth_audit_log_path
|
||||
|
||||
## 8. check_screens einfach erklaert
|
||||
|
||||
Die Funktion check_screens in osmtool.sh:
|
||||
|
||||
- prueft, ob wichtige Screen-Sessions laufen
|
||||
- schreibt Ergebnisse in ProblemRestarts.log
|
||||
- meldet auch, wenn ein Dienst laeuft
|
||||
- startet ausgefallene Dienste neu (kritische Dienste mit Komplett-Neustart)
|
||||
|
||||
## 9. Typische Fehler und schnelle Loesungen
|
||||
|
||||
### Problem: Im Live-Status werden alte oder falsche Ports angezeigt
|
||||
|
||||
Loesung:
|
||||
|
||||
1. Ports in webphp/src/config.php aendern (nicht nur in config.sample.php).
|
||||
2. Browser mit Hard-Reload neu laden (z. B. Ctrl+Shift+R).
|
||||
3. Sicherstellen, dass du die richtige Instanz/den richtigen Server aufrufst.
|
||||
|
||||
### Problem: Login gesperrt nach Fehlversuchen
|
||||
|
||||
Loesung:
|
||||
|
||||
- Sperrzeit in auth_lockout_seconds abwarten
|
||||
- oder Sperrdaten in der konfigurierten Lockout-Datei pruefen
|
||||
|
||||
## 10. Nuetzliche Dateien
|
||||
|
||||
- osmtool_main.sh
|
||||
- osmtool.sh
|
||||
- modular/osmtool_startstop.sh
|
||||
- modular/osmtool_install.sh
|
||||
- webphp/public/index.php
|
||||
- webphp/src/config.php
|
||||
- webphp/src/runner.php
|
||||
- webphp/src/web_init.php
|
||||
|
||||
## 11. Hilfe
|
||||
|
||||
- Wiki: [opensimMULTITOOLS-II Wiki](https://github.com/ManfredAabye/opensimMULTITOOLS-II/wiki)
|
||||
- Web-Dokumentation: webphp/README.md
|
||||
|
||||
## 12. Lizenz
|
||||
|
||||
- Skriptname: osmtool.sh
|
||||
- Version: V26.4.230.588
|
||||
- Autor: Manfred Aabye
|
||||
- Lizenz: MIT
|
||||
# opensimMULTITOOL II V26.4.230.588
|
||||
|
||||
Diese README ist fuer Einsteiger geschrieben.
|
||||
|
||||
Wenn du noch nie mit OpenSim oder Bash gearbeitet hast, starte mit den Schritten in diesem Dokument von oben nach unten.
|
||||
|
||||
## 1. Was ist dieses Projekt?
|
||||
|
||||
opensimMULTITOOLS-II hilft dir, einen OpenSim-Server zu:
|
||||
|
||||
- installieren
|
||||
- starten und stoppen
|
||||
- neu starten
|
||||
- sichern (Backups)
|
||||
- warten und pruefen
|
||||
|
||||
Das Projekt besteht aus zwei Hauptteilen:
|
||||
|
||||
- CLI-Skripte (Konsole): fuer Administration per Terminal
|
||||
- Web-Oberflaeche unter webphp/: fuer Bedienung im Browser
|
||||
|
||||
Voraussetzungen
|
||||
|
||||
- Linux Server
|
||||
|
||||
## 2. Wichtige Sicherheitshinweise
|
||||
|
||||
- Vor groesseren Aktionen immer Backup machen.
|
||||
- Erst in einer Testumgebung pruefen, dann auf Produktivsystem nutzen.
|
||||
- Die Web-Oberflaeche nur mit HTTPS und moeglichst mit IP-Einschraenkung betreiben.
|
||||
- Standard-Passwoerter sofort aendern.
|
||||
|
||||
## 3. Projektstruktur (kurz erklaert)
|
||||
|
||||
- osmtool_main.sh: Hauptstarter fuer Module und Aktionen
|
||||
- modular/: einzelne Fachmodule (install, startstop, backup, restore, ...)
|
||||
- webphp/: Web-Oberflaeche (PHP)
|
||||
- osmtool.sh: klassisches Hauptskript mit vielen Direktfunktionen
|
||||
|
||||
## 4. Schnellstart fuer Einsteiger (CLI)
|
||||
|
||||
Voraussetzung: Du arbeitest auf Linux und hast Zugriff auf das Projektverzeichnis.
|
||||
|
||||
### Schritt 1: In das Projektverzeichnis wechseln
|
||||
|
||||
```bash
|
||||
cd /opt/opensimMULTITOOLS-II
|
||||
```
|
||||
|
||||
### Schritt 2: Ubuntu vorbereiten
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh install-grid-sim
|
||||
```
|
||||
|
||||
Hinweis: `install-grid-sim` fuehrt die komplette Installationskette fuer `grid-sim` aus.
|
||||
|
||||
### Schritt 3: OpenSim-Abhaengigkeiten installieren
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh install-grid-sim
|
||||
```
|
||||
|
||||
### Schritt 4: Server-Check ausfuehren
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh healthcheck
|
||||
```
|
||||
|
||||
### Schritt 5: OpenSim installieren und konfigurieren
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh install-grid-sim
|
||||
```
|
||||
|
||||
### Schritt 6: Datenbank einrichten
|
||||
|
||||
```bash
|
||||
export OSM_DB_PASS='DEIN_PASSWORT'
|
||||
bash osmtool_main.sh dbsetup
|
||||
```
|
||||
|
||||
### Schritt 7: Grid starten
|
||||
|
||||
```bash
|
||||
bash osmtool_main.sh opensimrestart
|
||||
```
|
||||
|
||||
## 5. Alltagsbefehle (die wichtigsten)
|
||||
|
||||
```bash
|
||||
# Grid neu starten
|
||||
bash osmtool_main.sh opensimrestart
|
||||
|
||||
# Robust-Datenbank sichern
|
||||
export OSM_DB_PASS='DEIN_PASSWORT'
|
||||
bash osmtool_main.sh dbbackup
|
||||
|
||||
# Cronjobs installieren (automatische Backups/Checks)
|
||||
bash osmtool_main.sh croninstall
|
||||
```
|
||||
|
||||
Unterstuetzte Kurzbefehle (Ein-Wort-Aufruf):
|
||||
|
||||
- install-grid-sim
|
||||
- opensimstart
|
||||
- opensimstop
|
||||
- opensimrestart
|
||||
- healthcheck
|
||||
- smoketest
|
||||
- dailyreport
|
||||
- croninstall
|
||||
- cronlist
|
||||
- janusinstall
|
||||
- janusrestart
|
||||
- dbsetup
|
||||
- dbbackup
|
||||
|
||||
## 6. Web-Oberflaeche (webphp)
|
||||
|
||||
Die Web-Oberflaeche ist in webphp/ enthalten und zeigt unter anderem:
|
||||
|
||||
- Modulaktionen
|
||||
- Kommando-Vorschau
|
||||
- Ausgabe der Befehle
|
||||
- Live-Status (Screens, Ports, Artefakte)
|
||||
|
||||
Detaillierte Web-Anleitung: webphp/README.md
|
||||
|
||||
### Wichtige Konfigurationsregel
|
||||
|
||||
Fuer die aktive Web-Konfiguration gilt:
|
||||
|
||||
- webphp/src/config.php = wird wirklich benutzt
|
||||
- webphp/src/config.sample.php = nur Vorlage
|
||||
|
||||
Wenn du Ports oder Screens fuer den Live-Status aendern willst, musst du in config.php anpassen.
|
||||
|
||||
## 7. Login-Sicherheit der Web-Oberflaeche
|
||||
|
||||
Die Web-Oberflaeche hat einen Schutz gegen Brute-Force-Logins:
|
||||
|
||||
- Nach mehreren falschen Passwortversuchen wird die IP temporaer gesperrt.
|
||||
- Sperrzeit und Schwelle sind konfigurierbar.
|
||||
- Login-Ereignisse koennen in einer Audit-Logdatei gespeichert werden.
|
||||
|
||||
Wichtige Einstellungen in webphp/src/config.php:
|
||||
|
||||
- auth_lockout_max_attempts
|
||||
- auth_lockout_seconds
|
||||
- optional: auth_store_path
|
||||
- optional: auth_audit_log_path
|
||||
|
||||
## 8. check_screens einfach erklaert
|
||||
|
||||
Die Funktion check_screens in osmtool.sh:
|
||||
|
||||
- prueft, ob wichtige Screen-Sessions laufen
|
||||
- schreibt Ergebnisse in ProblemRestarts.log
|
||||
- meldet auch, wenn ein Dienst laeuft
|
||||
- startet ausgefallene Dienste neu (kritische Dienste mit Komplett-Neustart)
|
||||
|
||||
## 9. Typische Fehler und schnelle Loesungen
|
||||
|
||||
### Problem: Im Live-Status werden alte oder falsche Ports angezeigt
|
||||
|
||||
Loesung:
|
||||
|
||||
1. Ports in webphp/src/config.php aendern (nicht nur in config.sample.php).
|
||||
2. Browser mit Hard-Reload neu laden (z. B. Ctrl+Shift+R).
|
||||
3. Sicherstellen, dass du die richtige Instanz/den richtigen Server aufrufst.
|
||||
|
||||
### Problem: Login gesperrt nach Fehlversuchen
|
||||
|
||||
Loesung:
|
||||
|
||||
- Sperrzeit in auth_lockout_seconds abwarten
|
||||
- oder Sperrdaten in der konfigurierten Lockout-Datei pruefen
|
||||
|
||||
## 10. Nuetzliche Dateien
|
||||
|
||||
- osmtool_main.sh
|
||||
- osmtool.sh
|
||||
- modular/osmtool_startstop.sh
|
||||
- modular/osmtool_install.sh
|
||||
- webphp/public/index.php
|
||||
- webphp/src/config.php
|
||||
- webphp/src/runner.php
|
||||
- webphp/src/web_init.php
|
||||
|
||||
## 11. Hilfe
|
||||
|
||||
- Wiki: [opensimMULTITOOLS-II Wiki](https://github.com/ManfredAabye/opensimMULTITOOLS-II/wiki)
|
||||
- Web-Dokumentation: webphp/README.md
|
||||
|
||||
## 12. Lizenz
|
||||
|
||||
- Skriptname: osmtool.sh
|
||||
- Version: V26.4.230.588
|
||||
- Autor: Manfred Aabye
|
||||
- Lizenz: MIT
|
||||
|
||||
+125
-125
@@ -1,125 +1,125 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
|
||||
+219
-219
@@ -1,220 +1,220 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_config.sh [--workdir <path>] --action <init-config|validate-file|validate-runtime>
|
||||
[--file <path>] [--strict <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_config.sh --action init-config
|
||||
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"
|
||||
|
||||
if [[ "$ACTION" != "init-config" && ! -f "$OSMTOOL_CONFIG_FILE" ]]; then
|
||||
if [[ -t 0 ]]; then
|
||||
log INFO "Shared configuration not found. Starting interactive setup."
|
||||
init_shared_config_interactive
|
||||
else
|
||||
log INFO "Shared configuration not found at $OSMTOOL_CONFIG_FILE (non-interactive mode)"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$STRICT" in
|
||||
true|false) ;;
|
||||
*) die "--strict must be true or false" ;;
|
||||
esac
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
init-config)
|
||||
init_shared_config_interactive
|
||||
;;
|
||||
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" ;;
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
osmtool_config.sh [--workdir <path>] --action <init-config|validate-file|validate-runtime>
|
||||
[--file <path>] [--strict <true|false>]
|
||||
|
||||
Examples:
|
||||
osmtool_config.sh --action init-config
|
||||
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"
|
||||
|
||||
if [[ "$ACTION" != "init-config" && ! -f "$OSMTOOL_CONFIG_FILE" ]]; then
|
||||
if [[ -t 0 ]]; then
|
||||
log INFO "Shared configuration not found. Starting interactive setup."
|
||||
init_shared_config_interactive
|
||||
else
|
||||
log INFO "Shared configuration not found at $OSMTOOL_CONFIG_FILE (non-interactive mode)"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$STRICT" in
|
||||
true|false) ;;
|
||||
*) die "--strict must be true or false" ;;
|
||||
esac
|
||||
|
||||
log INFO "Using profile: $PROFILE"
|
||||
|
||||
case "$ACTION" in
|
||||
init-config)
|
||||
init_shared_config_interactive
|
||||
;;
|
||||
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
|
||||
+456
-456
@@ -1,456 +1,456 @@
|
||||
#!/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"
|
||||
export OSMTOOL_CONFIG_FILE="${OSMTOOL_CONFIG_FILE:-$ROOT_DIR/osmtool_config.json}"
|
||||
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
|
||||
}
|
||||
|
||||
config_get_string() {
|
||||
local key="$1"
|
||||
local default_value="$2"
|
||||
local value=""
|
||||
|
||||
[[ -f "$OSMTOOL_CONFIG_FILE" ]] || {
|
||||
printf '%s' "$default_value"
|
||||
return
|
||||
}
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
value="$(jq -r --arg k "$key" '.[$k] // empty' "$OSMTOOL_CONFIG_FILE" 2>/dev/null || true)"
|
||||
else
|
||||
value="$(sed -n -E "s/^[[:space:]]*\"${key}\"[[:space:]]*:[[:space:]]*\"([^\"]*)\"[[:space:]]*,?[[:space:]]*$/\1/p" "$OSMTOOL_CONFIG_FILE" | head -n1)"
|
||||
fi
|
||||
|
||||
if [[ -n "$value" ]]; then
|
||||
printf '%s' "$value"
|
||||
else
|
||||
printf '%s' "$default_value"
|
||||
fi
|
||||
}
|
||||
|
||||
config_get_bool() {
|
||||
local key="$1"
|
||||
local default_value="$2"
|
||||
local value=""
|
||||
|
||||
[[ -f "$OSMTOOL_CONFIG_FILE" ]] || {
|
||||
printf '%s' "$default_value"
|
||||
return
|
||||
}
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
value="$(jq -r --arg k "$key" '.[$k] // empty' "$OSMTOOL_CONFIG_FILE" 2>/dev/null || true)"
|
||||
else
|
||||
value="$(sed -n -E "s/^[[:space:]]*\"${key}\"[[:space:]]*:[[:space:]]*(true|false)[[:space:]]*,?[[:space:]]*$/\1/p" "$OSMTOOL_CONFIG_FILE" | head -n1)"
|
||||
fi
|
||||
|
||||
case "$value" in
|
||||
true|false) printf '%s' "$value" ;;
|
||||
*) printf '%s' "$default_value" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
config_get_int() {
|
||||
local key="$1"
|
||||
local default_value="$2"
|
||||
local value=""
|
||||
|
||||
[[ -f "$OSMTOOL_CONFIG_FILE" ]] || {
|
||||
printf '%s' "$default_value"
|
||||
return
|
||||
}
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
value="$(jq -r --arg k "$key" '.[$k] // empty' "$OSMTOOL_CONFIG_FILE" 2>/dev/null || true)"
|
||||
else
|
||||
value="$(sed -n -E "s/^[[:space:]]*\"${key}\"[[:space:]]*:[[:space:]]*([0-9]+)[[:space:]]*,?[[:space:]]*$/\1/p" "$OSMTOOL_CONFIG_FILE" | head -n1)"
|
||||
fi
|
||||
|
||||
if [[ "$value" =~ ^[0-9]+$ ]]; then
|
||||
printf '%s' "$value"
|
||||
else
|
||||
printf '%s' "$default_value"
|
||||
fi
|
||||
}
|
||||
|
||||
config_path_value() {
|
||||
local value="$1"
|
||||
if [[ "$value" = /* ]]; then
|
||||
printf '%s' "$value"
|
||||
else
|
||||
printf '%s' "$ROOT_DIR/$value"
|
||||
fi
|
||||
}
|
||||
|
||||
load_shared_config() {
|
||||
local cfg_lang cfg_workdir
|
||||
|
||||
cfg_lang="$(normalize_lang "$(config_get_string "language" "de")")"
|
||||
cfg_workdir="$(config_get_string "path_workdir" "$DEFAULT_WORKDIR")"
|
||||
|
||||
DEFAULT_WORKDIR="$cfg_workdir"
|
||||
export DEFAULT_WORKDIR
|
||||
|
||||
if [[ -z "${OSM_LANG:-}" ]]; then
|
||||
APP_LANG="$cfg_lang"
|
||||
fi
|
||||
|
||||
CONFIG_DB_ROOT_USER="$(config_get_string "db_root_user" "root")"
|
||||
CONFIG_DB_ROOT_PASS="$(config_get_string "db_root_pass" "")"
|
||||
CONFIG_DB_USER="$(config_get_string "db_user" "opensimuser")"
|
||||
CONFIG_DB_PASS="$(config_get_string "db_pass" "")"
|
||||
CONFIG_PUBLIC_HOST="$(config_get_string "public_host" "127.0.0.1")"
|
||||
CONFIG_GRIDNAME="$(config_get_string "gridname" "")"
|
||||
CONFIG_JANUS_PREFIX="$(config_get_string "janus_prefix" "/opt/janus")"
|
||||
CONFIG_OPENSIM_DIR="$(config_get_string "opensim_dir" "")"
|
||||
|
||||
export CONFIG_DB_ROOT_USER CONFIG_DB_ROOT_PASS CONFIG_DB_USER CONFIG_DB_PASS
|
||||
export CONFIG_PUBLIC_HOST CONFIG_GRIDNAME CONFIG_JANUS_PREFIX CONFIG_OPENSIM_DIR
|
||||
}
|
||||
|
||||
config_prompt_with_default() {
|
||||
local prompt="$1"
|
||||
local default_value="$2"
|
||||
local answer=""
|
||||
|
||||
read -r -p "$prompt [$default_value]: " answer
|
||||
if [[ -z "$answer" ]]; then
|
||||
printf '%s' "$default_value"
|
||||
else
|
||||
printf '%s' "$answer"
|
||||
fi
|
||||
}
|
||||
|
||||
write_shared_config_file() {
|
||||
local language="$1"
|
||||
local workdir="$2"
|
||||
local db_root_user="$3"
|
||||
local db_root_pass="$4"
|
||||
local db_user="$5"
|
||||
local db_pass="$6"
|
||||
local public_host="$7"
|
||||
local gridname="$8"
|
||||
local janus_prefix="$9"
|
||||
local opensim_dir="${10}"
|
||||
|
||||
cat > "$OSMTOOL_CONFIG_FILE" <<EOF
|
||||
{
|
||||
"language": "${language}",
|
||||
"path_workdir": "${workdir}",
|
||||
"path_lang_dir": "lang",
|
||||
"path_robust_bin": "robust/bin",
|
||||
"path_opensim_bin": "opensim/bin",
|
||||
"db_root_user": "${db_root_user}",
|
||||
"db_root_pass": "${db_root_pass}",
|
||||
"db_user": "${db_user}",
|
||||
"db_pass": "${db_pass}",
|
||||
"public_host": "${public_host}",
|
||||
"gridname": "${gridname}",
|
||||
"janus_prefix": "${janus_prefix}",
|
||||
"opensim_dir": "${opensim_dir}",
|
||||
"log_enabled": true,
|
||||
"old_log_del": true,
|
||||
"debug_log": "osmtool_debug.log",
|
||||
"max_log_size_mb": 10,
|
||||
"simulator_start_wait": 15,
|
||||
"moneyserver_start_wait": 30,
|
||||
"robustserver_start_wait": 30,
|
||||
"simulator_stop_wait": 15,
|
||||
"moneyserver_stop_wait": 30,
|
||||
"robustserver_stop_wait": 30
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
init_shared_config_interactive() {
|
||||
local cur_lang cur_workdir cur_db_root_user cur_db_root_pass cur_db_user cur_db_pass
|
||||
local cur_public_host cur_gridname cur_janus_prefix cur_opensim_dir
|
||||
local language workdir db_root_user db_root_pass db_user db_pass public_host gridname janus_prefix opensim_dir
|
||||
|
||||
if [[ ! -t 0 ]]; then
|
||||
die "Interactive config initialization requires a TTY"
|
||||
fi
|
||||
|
||||
cur_lang="$(normalize_lang "${OSM_LANG:-$(config_get_string "language" "de")}")"
|
||||
cur_workdir="$(config_get_string "path_workdir" "$DEFAULT_WORKDIR")"
|
||||
cur_db_root_user="$(config_get_string "db_root_user" "root")"
|
||||
cur_db_root_pass="$(config_get_string "db_root_pass" "")"
|
||||
cur_db_user="$(config_get_string "db_user" "opensimuser")"
|
||||
cur_db_pass="$(config_get_string "db_pass" "")"
|
||||
cur_public_host="$(config_get_string "public_host" "127.0.0.1")"
|
||||
cur_gridname="$(config_get_string "gridname" "")"
|
||||
cur_janus_prefix="$(config_get_string "janus_prefix" "/opt/janus")"
|
||||
cur_opensim_dir="$(config_get_string "opensim_dir" "$cur_workdir/opensim")"
|
||||
|
||||
echo "Shared configuration file: $OSMTOOL_CONFIG_FILE"
|
||||
language="$(normalize_lang "$(config_prompt_with_default "Language (de|en|fr|es)" "$cur_lang")")"
|
||||
workdir="$(config_prompt_with_default "Workdir" "$cur_workdir")"
|
||||
db_root_user="$(config_prompt_with_default "DB root user" "$cur_db_root_user")"
|
||||
db_root_pass="$(config_prompt_with_default "DB root password" "$cur_db_root_pass")"
|
||||
db_user="$(config_prompt_with_default "DB app user" "$cur_db_user")"
|
||||
db_pass="$(config_prompt_with_default "DB app password" "$cur_db_pass")"
|
||||
public_host="$(config_prompt_with_default "Public host/IP" "$cur_public_host")"
|
||||
gridname="$(config_prompt_with_default "Grid name" "$cur_gridname")"
|
||||
janus_prefix="$(config_prompt_with_default "Janus prefix" "$cur_janus_prefix")"
|
||||
opensim_dir="$(config_prompt_with_default "OpenSim source dir" "$cur_opensim_dir")"
|
||||
|
||||
mkdir -p "$(dirname "$OSMTOOL_CONFIG_FILE")"
|
||||
write_shared_config_file "$language" "$workdir" "$db_root_user" "$db_root_pass" "$db_user" "$db_pass" "$public_host" "$gridname" "$janus_prefix" "$opensim_dir"
|
||||
|
||||
load_shared_config
|
||||
set_language "$language"
|
||||
log INFO "Shared configuration written: $OSMTOOL_CONFIG_FILE"
|
||||
}
|
||||
|
||||
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 init-config|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 init-config|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
|
||||
}
|
||||
|
||||
# Load shared settings before translations and module defaults are resolved.
|
||||
load_shared_config
|
||||
|
||||
# Ensure translations are available in every script that sources this core.
|
||||
init_i18n
|
||||
#!/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"
|
||||
export OSMTOOL_CONFIG_FILE="${OSMTOOL_CONFIG_FILE:-$ROOT_DIR/osmtool_config.json}"
|
||||
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
|
||||
}
|
||||
|
||||
config_get_string() {
|
||||
local key="$1"
|
||||
local default_value="$2"
|
||||
local value=""
|
||||
|
||||
[[ -f "$OSMTOOL_CONFIG_FILE" ]] || {
|
||||
printf '%s' "$default_value"
|
||||
return
|
||||
}
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
value="$(jq -r --arg k "$key" '.[$k] // empty' "$OSMTOOL_CONFIG_FILE" 2>/dev/null || true)"
|
||||
else
|
||||
value="$(sed -n -E "s/^[[:space:]]*\"${key}\"[[:space:]]*:[[:space:]]*\"([^\"]*)\"[[:space:]]*,?[[:space:]]*$/\1/p" "$OSMTOOL_CONFIG_FILE" | head -n1)"
|
||||
fi
|
||||
|
||||
if [[ -n "$value" ]]; then
|
||||
printf '%s' "$value"
|
||||
else
|
||||
printf '%s' "$default_value"
|
||||
fi
|
||||
}
|
||||
|
||||
config_get_bool() {
|
||||
local key="$1"
|
||||
local default_value="$2"
|
||||
local value=""
|
||||
|
||||
[[ -f "$OSMTOOL_CONFIG_FILE" ]] || {
|
||||
printf '%s' "$default_value"
|
||||
return
|
||||
}
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
value="$(jq -r --arg k "$key" '.[$k] // empty' "$OSMTOOL_CONFIG_FILE" 2>/dev/null || true)"
|
||||
else
|
||||
value="$(sed -n -E "s/^[[:space:]]*\"${key}\"[[:space:]]*:[[:space:]]*(true|false)[[:space:]]*,?[[:space:]]*$/\1/p" "$OSMTOOL_CONFIG_FILE" | head -n1)"
|
||||
fi
|
||||
|
||||
case "$value" in
|
||||
true|false) printf '%s' "$value" ;;
|
||||
*) printf '%s' "$default_value" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
config_get_int() {
|
||||
local key="$1"
|
||||
local default_value="$2"
|
||||
local value=""
|
||||
|
||||
[[ -f "$OSMTOOL_CONFIG_FILE" ]] || {
|
||||
printf '%s' "$default_value"
|
||||
return
|
||||
}
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
value="$(jq -r --arg k "$key" '.[$k] // empty' "$OSMTOOL_CONFIG_FILE" 2>/dev/null || true)"
|
||||
else
|
||||
value="$(sed -n -E "s/^[[:space:]]*\"${key}\"[[:space:]]*:[[:space:]]*([0-9]+)[[:space:]]*,?[[:space:]]*$/\1/p" "$OSMTOOL_CONFIG_FILE" | head -n1)"
|
||||
fi
|
||||
|
||||
if [[ "$value" =~ ^[0-9]+$ ]]; then
|
||||
printf '%s' "$value"
|
||||
else
|
||||
printf '%s' "$default_value"
|
||||
fi
|
||||
}
|
||||
|
||||
config_path_value() {
|
||||
local value="$1"
|
||||
if [[ "$value" = /* ]]; then
|
||||
printf '%s' "$value"
|
||||
else
|
||||
printf '%s' "$ROOT_DIR/$value"
|
||||
fi
|
||||
}
|
||||
|
||||
load_shared_config() {
|
||||
local cfg_lang cfg_workdir
|
||||
|
||||
cfg_lang="$(normalize_lang "$(config_get_string "language" "de")")"
|
||||
cfg_workdir="$(config_get_string "path_workdir" "$DEFAULT_WORKDIR")"
|
||||
|
||||
DEFAULT_WORKDIR="$cfg_workdir"
|
||||
export DEFAULT_WORKDIR
|
||||
|
||||
if [[ -z "${OSM_LANG:-}" ]]; then
|
||||
APP_LANG="$cfg_lang"
|
||||
fi
|
||||
|
||||
CONFIG_DB_ROOT_USER="$(config_get_string "db_root_user" "root")"
|
||||
CONFIG_DB_ROOT_PASS="$(config_get_string "db_root_pass" "")"
|
||||
CONFIG_DB_USER="$(config_get_string "db_user" "opensimuser")"
|
||||
CONFIG_DB_PASS="$(config_get_string "db_pass" "")"
|
||||
CONFIG_PUBLIC_HOST="$(config_get_string "public_host" "127.0.0.1")"
|
||||
CONFIG_GRIDNAME="$(config_get_string "gridname" "")"
|
||||
CONFIG_JANUS_PREFIX="$(config_get_string "janus_prefix" "/opt/janus")"
|
||||
CONFIG_OPENSIM_DIR="$(config_get_string "opensim_dir" "")"
|
||||
|
||||
export CONFIG_DB_ROOT_USER CONFIG_DB_ROOT_PASS CONFIG_DB_USER CONFIG_DB_PASS
|
||||
export CONFIG_PUBLIC_HOST CONFIG_GRIDNAME CONFIG_JANUS_PREFIX CONFIG_OPENSIM_DIR
|
||||
}
|
||||
|
||||
config_prompt_with_default() {
|
||||
local prompt="$1"
|
||||
local default_value="$2"
|
||||
local answer=""
|
||||
|
||||
read -r -p "$prompt [$default_value]: " answer
|
||||
if [[ -z "$answer" ]]; then
|
||||
printf '%s' "$default_value"
|
||||
else
|
||||
printf '%s' "$answer"
|
||||
fi
|
||||
}
|
||||
|
||||
write_shared_config_file() {
|
||||
local language="$1"
|
||||
local workdir="$2"
|
||||
local db_root_user="$3"
|
||||
local db_root_pass="$4"
|
||||
local db_user="$5"
|
||||
local db_pass="$6"
|
||||
local public_host="$7"
|
||||
local gridname="$8"
|
||||
local janus_prefix="$9"
|
||||
local opensim_dir="${10}"
|
||||
|
||||
cat > "$OSMTOOL_CONFIG_FILE" <<EOF
|
||||
{
|
||||
"language": "${language}",
|
||||
"path_workdir": "${workdir}",
|
||||
"path_lang_dir": "lang",
|
||||
"path_robust_bin": "robust/bin",
|
||||
"path_opensim_bin": "opensim/bin",
|
||||
"db_root_user": "${db_root_user}",
|
||||
"db_root_pass": "${db_root_pass}",
|
||||
"db_user": "${db_user}",
|
||||
"db_pass": "${db_pass}",
|
||||
"public_host": "${public_host}",
|
||||
"gridname": "${gridname}",
|
||||
"janus_prefix": "${janus_prefix}",
|
||||
"opensim_dir": "${opensim_dir}",
|
||||
"log_enabled": true,
|
||||
"old_log_del": true,
|
||||
"debug_log": "osmtool_debug.log",
|
||||
"max_log_size_mb": 10,
|
||||
"simulator_start_wait": 15,
|
||||
"moneyserver_start_wait": 30,
|
||||
"robustserver_start_wait": 30,
|
||||
"simulator_stop_wait": 15,
|
||||
"moneyserver_stop_wait": 30,
|
||||
"robustserver_stop_wait": 30
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
init_shared_config_interactive() {
|
||||
local cur_lang cur_workdir cur_db_root_user cur_db_root_pass cur_db_user cur_db_pass
|
||||
local cur_public_host cur_gridname cur_janus_prefix cur_opensim_dir
|
||||
local language workdir db_root_user db_root_pass db_user db_pass public_host gridname janus_prefix opensim_dir
|
||||
|
||||
if [[ ! -t 0 ]]; then
|
||||
die "Interactive config initialization requires a TTY"
|
||||
fi
|
||||
|
||||
cur_lang="$(normalize_lang "${OSM_LANG:-$(config_get_string "language" "de")}")"
|
||||
cur_workdir="$(config_get_string "path_workdir" "$DEFAULT_WORKDIR")"
|
||||
cur_db_root_user="$(config_get_string "db_root_user" "root")"
|
||||
cur_db_root_pass="$(config_get_string "db_root_pass" "")"
|
||||
cur_db_user="$(config_get_string "db_user" "opensimuser")"
|
||||
cur_db_pass="$(config_get_string "db_pass" "")"
|
||||
cur_public_host="$(config_get_string "public_host" "127.0.0.1")"
|
||||
cur_gridname="$(config_get_string "gridname" "")"
|
||||
cur_janus_prefix="$(config_get_string "janus_prefix" "/opt/janus")"
|
||||
cur_opensim_dir="$(config_get_string "opensim_dir" "$cur_workdir/opensim")"
|
||||
|
||||
echo "Shared configuration file: $OSMTOOL_CONFIG_FILE"
|
||||
language="$(normalize_lang "$(config_prompt_with_default "Language (de|en|fr|es)" "$cur_lang")")"
|
||||
workdir="$(config_prompt_with_default "Workdir" "$cur_workdir")"
|
||||
db_root_user="$(config_prompt_with_default "DB root user" "$cur_db_root_user")"
|
||||
db_root_pass="$(config_prompt_with_default "DB root password" "$cur_db_root_pass")"
|
||||
db_user="$(config_prompt_with_default "DB app user" "$cur_db_user")"
|
||||
db_pass="$(config_prompt_with_default "DB app password" "$cur_db_pass")"
|
||||
public_host="$(config_prompt_with_default "Public host/IP" "$cur_public_host")"
|
||||
gridname="$(config_prompt_with_default "Grid name" "$cur_gridname")"
|
||||
janus_prefix="$(config_prompt_with_default "Janus prefix" "$cur_janus_prefix")"
|
||||
opensim_dir="$(config_prompt_with_default "OpenSim source dir" "$cur_opensim_dir")"
|
||||
|
||||
mkdir -p "$(dirname "$OSMTOOL_CONFIG_FILE")"
|
||||
write_shared_config_file "$language" "$workdir" "$db_root_user" "$db_root_pass" "$db_user" "$db_pass" "$public_host" "$gridname" "$janus_prefix" "$opensim_dir"
|
||||
|
||||
load_shared_config
|
||||
set_language "$language"
|
||||
log INFO "Shared configuration written: $OSMTOOL_CONFIG_FILE"
|
||||
}
|
||||
|
||||
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 init-config|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 init-config|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
|
||||
}
|
||||
|
||||
# Load shared settings before translations and module defaults are resolved.
|
||||
load_shared_config
|
||||
|
||||
# Ensure translations are available in every script that sources this core.
|
||||
init_i18n
|
||||
|
||||
+203
-203
@@ -1,203 +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=/dev/null
|
||||
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
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
|
||||
+170
-170
@@ -1,170 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
|
||||
+268
-268
@@ -1,268 +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=/dev/null
|
||||
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
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
|
||||
+1191
-1191
File diff suppressed because it is too large
Load Diff
+292
-292
@@ -1,293 +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=/dev/null
|
||||
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" ;;
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
+260
-260
@@ -1,260 +1,260 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
|
||||
+190
-190
@@ -1,191 +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=/dev/null
|
||||
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" ;;
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
+395
-395
@@ -1,395 +1,395 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
msgf() {
|
||||
local key="$1"
|
||||
shift
|
||||
# shellcheck disable=SC2059
|
||||
printf "$(msg "$key")" "$@"
|
||||
}
|
||||
|
||||
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:-$SIMULATOR_STOP_WAIT}"
|
||||
|
||||
if ! screen_session_exists "$screen_name"; then
|
||||
log INFO "$(msgf STARTSTOP_NOT_RUNNING "$screen_name")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
run_screen_cmd "$screen_name" "shutdown"
|
||||
log INFO "$(msgf STARTSTOP_SENT_SHUTDOWN "$screen_name")"
|
||||
sleep "$grace_seconds"
|
||||
|
||||
if screen_session_exists "$screen_name"; then
|
||||
log INFO "$(msgf STARTSTOP_FORCE_QUIT "$screen_name")"
|
||||
screen -S "$screen_name" -X quit || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if screen_session_exists "$screen_name"; then
|
||||
log ERROR "$(msgf STARTSTOP_STOP_FAILED "$screen_name")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log INFO "$(msgf STARTSTOP_STOPPED "$screen_name")"
|
||||
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 "$(msgf STARTSTOP_JANUS_BIN_MISSING "$JANUS_PREFIX/bin/janus")"
|
||||
|
||||
if [[ ! -f "$core_cfg" && ! -f "$core_cfg_legacy" ]]; then
|
||||
die "$(msgf STARTSTOP_JANUS_CORE_CFG_MISSING "$JANUS_PREFIX/etc/janus")"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$http_cfg" && ! -f "$http_cfg_legacy" ]]; then
|
||||
die "$(msgf STARTSTOP_JANUS_HTTP_CFG_MISSING "$JANUS_PREFIX/etc/janus")"
|
||||
fi
|
||||
|
||||
[[ -f "$marker" ]] || log INFO "$(msgf STARTSTOP_JANUS_MARKER_MISSING "$marker")"
|
||||
}
|
||||
|
||||
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 "$(msg STARTSTOP_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 "$(msg STARTSTOP_JANUS_CONTROL_NOT_CONFIGURED)"
|
||||
}
|
||||
|
||||
require_ini() {
|
||||
local bin_dir="$1"
|
||||
local ini_file="$2"
|
||||
local label="$3"
|
||||
|
||||
if [[ ! -f "$bin_dir/$ini_file" ]]; then
|
||||
die "$(msgf STARTSTOP_REQUIRED_INI_MISSING "$label" "$bin_dir/$ini_file")"
|
||||
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 "$(msgf STARTSTOP_ALREADY_RUNNING "$screen_name")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "$(msgf STARTSTOP_STARTING_FROM "$screen_name" "$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 "$(msgf STARTSTOP_STARTED_OK "$screen_name")"
|
||||
return 0
|
||||
else
|
||||
log ERROR "$(msgf STARTSTOP_START_FAILED "$screen_name")"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
list_sim_names_asc() {
|
||||
local sim_dir sim_name
|
||||
local sim_names=()
|
||||
|
||||
shopt -s nullglob
|
||||
for sim_dir in "$WORKDIR"/sim[0-9]*; do
|
||||
[[ -d "$sim_dir/bin" ]] || continue
|
||||
sim_name="$(basename "$sim_dir")"
|
||||
[[ "$sim_name" =~ ^sim[0-9]+$ ]] || continue
|
||||
sim_names+=("$sim_name")
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
if [[ ${#sim_names[@]} -eq 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "${sim_names[@]}" | sort -V
|
||||
}
|
||||
|
||||
start_grid() {
|
||||
local sim_name
|
||||
local sim_count=0
|
||||
|
||||
log INFO "$(msgf STARTSTOP_GRID_STARTING "$WORKDIR")"
|
||||
|
||||
[[ -d "$WORKDIR/robust/bin" ]] || die "$(msgf STARTSTOP_ROBUST_DIR_MISSING "$WORKDIR/robust/bin")"
|
||||
require_ini "$WORKDIR/robust/bin" "Robust.ini" "RobustServer"
|
||||
screen_start "robustserver" "$WORKDIR/robust/bin" "Robust.dll" || die "$(msg STARTSTOP_ROBUST_START_FAILED)"
|
||||
sleep "$ROBUSTSERVER_START_WAIT"
|
||||
|
||||
[[ -f "$WORKDIR/robust/bin/MoneyServer.dll" ]] || die "$(msgf STARTSTOP_MONEY_DLL_MISSING "$WORKDIR/robust/bin/MoneyServer.dll")"
|
||||
[[ -f "$WORKDIR/robust/bin/MoneyServer.ini" ]] || die "$(msgf STARTSTOP_MONEY_INI_MISSING "$WORKDIR/robust/bin/MoneyServer.ini")"
|
||||
screen_start "moneyserver" "$WORKDIR/robust/bin" "MoneyServer.dll" || die "$(msg STARTSTOP_MONEY_START_FAILED)"
|
||||
sleep "$MONEYSERVER_START_WAIT"
|
||||
|
||||
while IFS= read -r sim_name; do
|
||||
[[ -n "$sim_name" ]] || continue
|
||||
require_ini "$WORKDIR/$sim_name/bin" "OpenSim.ini" "$sim_name"
|
||||
screen_start "$sim_name" "$WORKDIR/$sim_name/bin" "OpenSim.dll" || die "$(msgf STARTSTOP_SIM_START_FAILED "$sim_name")"
|
||||
sleep "$SIMULATOR_START_WAIT"
|
||||
((sim_count+=1))
|
||||
done < <(list_sim_names_asc)
|
||||
|
||||
[[ "$sim_count" -gt 0 ]] || die "$(msgf STARTSTOP_NO_SIM_FOUND "$WORKDIR")"
|
||||
}
|
||||
|
||||
stop_grid() {
|
||||
local sim_names=()
|
||||
local idx
|
||||
|
||||
log INFO "$(msg STARTSTOP_GRID_STOPPING)"
|
||||
|
||||
mapfile -t sim_names < <(list_sim_names_asc)
|
||||
for ((idx=${#sim_names[@]}-1; idx>=0; idx--)); do
|
||||
stop_screen_session "${sim_names[$idx]}" "$SIMULATOR_STOP_WAIT" || true
|
||||
done
|
||||
|
||||
stop_screen_session "moneyserver" "$MONEYSERVER_STOP_WAIT" || true
|
||||
stop_screen_session "robustserver" "$ROBUSTSERVER_STOP_WAIT" || true
|
||||
}
|
||||
|
||||
logclean_grid() {
|
||||
log INFO "$(msg STARTSTOP_LOGCLEAN_BEGIN)"
|
||||
|
||||
if [[ -d "$WORKDIR/robust/bin" ]]; then
|
||||
rm -f "$WORKDIR/robust/bin/"*.log
|
||||
log INFO "$(msgf STARTSTOP_LOGS_DELETED "$WORKDIR/robust/bin")"
|
||||
fi
|
||||
|
||||
local sim_dir sim_name
|
||||
shopt -s nullglob
|
||||
for sim_dir in "$WORKDIR"/sim[0-9]*/bin; do
|
||||
sim_name="$(basename "$(dirname "$sim_dir")")"
|
||||
[[ "$sim_name" =~ ^sim[0-9]+$ ]] || continue
|
||||
rm -f "$sim_dir/"*.log
|
||||
log INFO "$(msgf STARTSTOP_LOGS_DELETED "$sim_dir")"
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
log INFO "$(msg STARTSTOP_LOGCLEAN_DONE)"
|
||||
}
|
||||
|
||||
restart_grid() {
|
||||
stop_grid
|
||||
sleep "$SIMULATOR_STOP_WAIT"
|
||||
logclean_grid
|
||||
sleep "$SIMULATOR_START_WAIT"
|
||||
start_grid
|
||||
log INFO "$(msg STARTSTOP_ACTIVE_SESSIONS)"
|
||||
screen -ls 2>/dev/null || log INFO "$(msg STARTSTOP_NO_SESSIONS)"
|
||||
}
|
||||
|
||||
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 "$(msg STARTSTOP_NAME_REQUIRED)"
|
||||
require_ini "$WORKDIR/${NAME}/bin" "OpenSim.ini" "$NAME"
|
||||
screen_start "$NAME" "$WORKDIR/${NAME}/bin" "OpenSim.dll"
|
||||
;;
|
||||
*)
|
||||
die "$(msgf STARTSTOP_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 "$(msg STARTSTOP_NAME_REQUIRED)"
|
||||
stop_screen_session "$NAME"
|
||||
;;
|
||||
*) die "$(msgf STARTSTOP_UNSUPPORTED_STOP_TARGET "$target")" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
TARGET=""
|
||||
ACTION=""
|
||||
NAME=""
|
||||
PROFILE="grid-sim"
|
||||
JANUS_PREFIX="${JANUS_PREFIX:-/opt/janus}"
|
||||
|
||||
# Wartezeiten (Sekunden) – entsprechen den bewährten Werten aus osmtool.sh
|
||||
SIMULATOR_STOP_WAIT="${SIMULATOR_STOP_WAIT:-15}"
|
||||
MONEYSERVER_STOP_WAIT="${MONEYSERVER_STOP_WAIT:-30}"
|
||||
ROBUSTSERVER_STOP_WAIT="${ROBUSTSERVER_STOP_WAIT:-30}"
|
||||
SIMULATOR_START_WAIT="${SIMULATOR_START_WAIT:-15}"
|
||||
MONEYSERVER_START_WAIT="${MONEYSERVER_START_WAIT:-30}"
|
||||
ROBUSTSERVER_START_WAIT="${ROBUSTSERVER_START_WAIT:-30}"
|
||||
|
||||
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 "$(msgf ERR_UNKNOWN_OPTION "$1")" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$TARGET" ]] || die "$(msg ERR_MISSING_TARGET)"
|
||||
[[ -n "$ACTION" ]] || die "$(msg ERR_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 "$(msgf INFO_USING_PROFILE "$PROFILE")"
|
||||
|
||||
if [[ "$TARGET" == "grid" ]]; then
|
||||
case "$ACTION" in
|
||||
start) start_grid ;;
|
||||
stop) stop_grid ;;
|
||||
restart) restart_grid ;;
|
||||
*) die "$(msgf ERR_UNSUPPORTED_GRID_ACTION "$ACTION")" ;;
|
||||
esac
|
||||
else
|
||||
case "$ACTION" in
|
||||
start) start_single "$TARGET" ;;
|
||||
stop) stop_single "$TARGET" ;;
|
||||
restart)
|
||||
stop_single "$TARGET"
|
||||
sleep 3
|
||||
start_single "$TARGET"
|
||||
;;
|
||||
*) die "$(msgf ERR_UNSUPPORTED_ACTION "$ACTION")" ;;
|
||||
esac
|
||||
fi
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/osmtool_core.sh"
|
||||
|
||||
msgf() {
|
||||
local key="$1"
|
||||
shift
|
||||
# shellcheck disable=SC2059
|
||||
printf "$(msg "$key")" "$@"
|
||||
}
|
||||
|
||||
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:-$SIMULATOR_STOP_WAIT}"
|
||||
|
||||
if ! screen_session_exists "$screen_name"; then
|
||||
log INFO "$(msgf STARTSTOP_NOT_RUNNING "$screen_name")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
run_screen_cmd "$screen_name" "shutdown"
|
||||
log INFO "$(msgf STARTSTOP_SENT_SHUTDOWN "$screen_name")"
|
||||
sleep "$grace_seconds"
|
||||
|
||||
if screen_session_exists "$screen_name"; then
|
||||
log INFO "$(msgf STARTSTOP_FORCE_QUIT "$screen_name")"
|
||||
screen -S "$screen_name" -X quit || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if screen_session_exists "$screen_name"; then
|
||||
log ERROR "$(msgf STARTSTOP_STOP_FAILED "$screen_name")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log INFO "$(msgf STARTSTOP_STOPPED "$screen_name")"
|
||||
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 "$(msgf STARTSTOP_JANUS_BIN_MISSING "$JANUS_PREFIX/bin/janus")"
|
||||
|
||||
if [[ ! -f "$core_cfg" && ! -f "$core_cfg_legacy" ]]; then
|
||||
die "$(msgf STARTSTOP_JANUS_CORE_CFG_MISSING "$JANUS_PREFIX/etc/janus")"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$http_cfg" && ! -f "$http_cfg_legacy" ]]; then
|
||||
die "$(msgf STARTSTOP_JANUS_HTTP_CFG_MISSING "$JANUS_PREFIX/etc/janus")"
|
||||
fi
|
||||
|
||||
[[ -f "$marker" ]] || log INFO "$(msgf STARTSTOP_JANUS_MARKER_MISSING "$marker")"
|
||||
}
|
||||
|
||||
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 "$(msg STARTSTOP_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 "$(msg STARTSTOP_JANUS_CONTROL_NOT_CONFIGURED)"
|
||||
}
|
||||
|
||||
require_ini() {
|
||||
local bin_dir="$1"
|
||||
local ini_file="$2"
|
||||
local label="$3"
|
||||
|
||||
if [[ ! -f "$bin_dir/$ini_file" ]]; then
|
||||
die "$(msgf STARTSTOP_REQUIRED_INI_MISSING "$label" "$bin_dir/$ini_file")"
|
||||
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 "$(msgf STARTSTOP_ALREADY_RUNNING "$screen_name")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "$(msgf STARTSTOP_STARTING_FROM "$screen_name" "$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 "$(msgf STARTSTOP_STARTED_OK "$screen_name")"
|
||||
return 0
|
||||
else
|
||||
log ERROR "$(msgf STARTSTOP_START_FAILED "$screen_name")"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
list_sim_names_asc() {
|
||||
local sim_dir sim_name
|
||||
local sim_names=()
|
||||
|
||||
shopt -s nullglob
|
||||
for sim_dir in "$WORKDIR"/sim[0-9]*; do
|
||||
[[ -d "$sim_dir/bin" ]] || continue
|
||||
sim_name="$(basename "$sim_dir")"
|
||||
[[ "$sim_name" =~ ^sim[0-9]+$ ]] || continue
|
||||
sim_names+=("$sim_name")
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
if [[ ${#sim_names[@]} -eq 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "${sim_names[@]}" | sort -V
|
||||
}
|
||||
|
||||
start_grid() {
|
||||
local sim_name
|
||||
local sim_count=0
|
||||
|
||||
log INFO "$(msgf STARTSTOP_GRID_STARTING "$WORKDIR")"
|
||||
|
||||
[[ -d "$WORKDIR/robust/bin" ]] || die "$(msgf STARTSTOP_ROBUST_DIR_MISSING "$WORKDIR/robust/bin")"
|
||||
require_ini "$WORKDIR/robust/bin" "Robust.ini" "RobustServer"
|
||||
screen_start "robustserver" "$WORKDIR/robust/bin" "Robust.dll" || die "$(msg STARTSTOP_ROBUST_START_FAILED)"
|
||||
sleep "$ROBUSTSERVER_START_WAIT"
|
||||
|
||||
[[ -f "$WORKDIR/robust/bin/MoneyServer.dll" ]] || die "$(msgf STARTSTOP_MONEY_DLL_MISSING "$WORKDIR/robust/bin/MoneyServer.dll")"
|
||||
[[ -f "$WORKDIR/robust/bin/MoneyServer.ini" ]] || die "$(msgf STARTSTOP_MONEY_INI_MISSING "$WORKDIR/robust/bin/MoneyServer.ini")"
|
||||
screen_start "moneyserver" "$WORKDIR/robust/bin" "MoneyServer.dll" || die "$(msg STARTSTOP_MONEY_START_FAILED)"
|
||||
sleep "$MONEYSERVER_START_WAIT"
|
||||
|
||||
while IFS= read -r sim_name; do
|
||||
[[ -n "$sim_name" ]] || continue
|
||||
require_ini "$WORKDIR/$sim_name/bin" "OpenSim.ini" "$sim_name"
|
||||
screen_start "$sim_name" "$WORKDIR/$sim_name/bin" "OpenSim.dll" || die "$(msgf STARTSTOP_SIM_START_FAILED "$sim_name")"
|
||||
sleep "$SIMULATOR_START_WAIT"
|
||||
((sim_count+=1))
|
||||
done < <(list_sim_names_asc)
|
||||
|
||||
[[ "$sim_count" -gt 0 ]] || die "$(msgf STARTSTOP_NO_SIM_FOUND "$WORKDIR")"
|
||||
}
|
||||
|
||||
stop_grid() {
|
||||
local sim_names=()
|
||||
local idx
|
||||
|
||||
log INFO "$(msg STARTSTOP_GRID_STOPPING)"
|
||||
|
||||
mapfile -t sim_names < <(list_sim_names_asc)
|
||||
for ((idx=${#sim_names[@]}-1; idx>=0; idx--)); do
|
||||
stop_screen_session "${sim_names[$idx]}" "$SIMULATOR_STOP_WAIT" || true
|
||||
done
|
||||
|
||||
stop_screen_session "moneyserver" "$MONEYSERVER_STOP_WAIT" || true
|
||||
stop_screen_session "robustserver" "$ROBUSTSERVER_STOP_WAIT" || true
|
||||
}
|
||||
|
||||
logclean_grid() {
|
||||
log INFO "$(msg STARTSTOP_LOGCLEAN_BEGIN)"
|
||||
|
||||
if [[ -d "$WORKDIR/robust/bin" ]]; then
|
||||
rm -f "$WORKDIR/robust/bin/"*.log
|
||||
log INFO "$(msgf STARTSTOP_LOGS_DELETED "$WORKDIR/robust/bin")"
|
||||
fi
|
||||
|
||||
local sim_dir sim_name
|
||||
shopt -s nullglob
|
||||
for sim_dir in "$WORKDIR"/sim[0-9]*/bin; do
|
||||
sim_name="$(basename "$(dirname "$sim_dir")")"
|
||||
[[ "$sim_name" =~ ^sim[0-9]+$ ]] || continue
|
||||
rm -f "$sim_dir/"*.log
|
||||
log INFO "$(msgf STARTSTOP_LOGS_DELETED "$sim_dir")"
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
log INFO "$(msg STARTSTOP_LOGCLEAN_DONE)"
|
||||
}
|
||||
|
||||
restart_grid() {
|
||||
stop_grid
|
||||
sleep "$SIMULATOR_STOP_WAIT"
|
||||
logclean_grid
|
||||
sleep "$SIMULATOR_START_WAIT"
|
||||
start_grid
|
||||
log INFO "$(msg STARTSTOP_ACTIVE_SESSIONS)"
|
||||
screen -ls 2>/dev/null || log INFO "$(msg STARTSTOP_NO_SESSIONS)"
|
||||
}
|
||||
|
||||
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 "$(msg STARTSTOP_NAME_REQUIRED)"
|
||||
require_ini "$WORKDIR/${NAME}/bin" "OpenSim.ini" "$NAME"
|
||||
screen_start "$NAME" "$WORKDIR/${NAME}/bin" "OpenSim.dll"
|
||||
;;
|
||||
*)
|
||||
die "$(msgf STARTSTOP_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 "$(msg STARTSTOP_NAME_REQUIRED)"
|
||||
stop_screen_session "$NAME"
|
||||
;;
|
||||
*) die "$(msgf STARTSTOP_UNSUPPORTED_STOP_TARGET "$target")" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
WORKDIR="$DEFAULT_WORKDIR"
|
||||
TARGET=""
|
||||
ACTION=""
|
||||
NAME=""
|
||||
PROFILE="grid-sim"
|
||||
JANUS_PREFIX="${JANUS_PREFIX:-/opt/janus}"
|
||||
|
||||
# Wartezeiten (Sekunden) – entsprechen den bewährten Werten aus osmtool.sh
|
||||
SIMULATOR_STOP_WAIT="${SIMULATOR_STOP_WAIT:-15}"
|
||||
MONEYSERVER_STOP_WAIT="${MONEYSERVER_STOP_WAIT:-30}"
|
||||
ROBUSTSERVER_STOP_WAIT="${ROBUSTSERVER_STOP_WAIT:-30}"
|
||||
SIMULATOR_START_WAIT="${SIMULATOR_START_WAIT:-15}"
|
||||
MONEYSERVER_START_WAIT="${MONEYSERVER_START_WAIT:-30}"
|
||||
ROBUSTSERVER_START_WAIT="${ROBUSTSERVER_START_WAIT:-30}"
|
||||
|
||||
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 "$(msgf ERR_UNKNOWN_OPTION "$1")" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$TARGET" ]] || die "$(msg ERR_MISSING_TARGET)"
|
||||
[[ -n "$ACTION" ]] || die "$(msg ERR_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 "$(msgf INFO_USING_PROFILE "$PROFILE")"
|
||||
|
||||
if [[ "$TARGET" == "grid" ]]; then
|
||||
case "$ACTION" in
|
||||
start) start_grid ;;
|
||||
stop) stop_grid ;;
|
||||
restart) restart_grid ;;
|
||||
*) die "$(msgf ERR_UNSUPPORTED_GRID_ACTION "$ACTION")" ;;
|
||||
esac
|
||||
else
|
||||
case "$ACTION" in
|
||||
start) start_single "$TARGET" ;;
|
||||
stop) stop_single "$TARGET" ;;
|
||||
restart)
|
||||
stop_single "$TARGET"
|
||||
sleep 3
|
||||
start_single "$TARGET"
|
||||
;;
|
||||
*) die "$(msgf ERR_UNSUPPORTED_ACTION "$ACTION")" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
+261
-261
@@ -1,262 +1,262 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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" ;;
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
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
|
||||
+6919
-6919
File diff suppressed because it is too large
Load Diff
+718
-718
File diff suppressed because it is too large
Load Diff
+430
-430
@@ -1,430 +1,430 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
MOD_DIR="$BASE_DIR/modular"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
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]
|
||||
osmtool_main.sh server_install
|
||||
osmtool_main.sh <configinit|install-grid-sim|opensimstart|opensimstop|opensimrestart|healthcheck|smoketest|dailyreport|croninstall|cronlist|janusinstall|janusrestart|dbsetup|dbbackup>
|
||||
|
||||
Examples:
|
||||
osmtool_main.sh install-grid-sim
|
||||
osmtool_main.sh server_install
|
||||
osmtool_main.sh opensimstart
|
||||
osmtool_main.sh opensimrestart
|
||||
osmtool_main.sh croninstall
|
||||
osmtool_main.sh dbbackup
|
||||
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)
|
||||
bash "$MOD_DIR/osmtool_install.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
startstop)
|
||||
bash "$MOD_DIR/osmtool_startstop.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
cleanup)
|
||||
bash "$MOD_DIR/osmtool_cleanup.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
health)
|
||||
bash "$MOD_DIR/osmtool_health.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
backup)
|
||||
bash "$MOD_DIR/osmtool_data.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
update)
|
||||
bash "$MOD_DIR/osmtool_update.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
config)
|
||||
bash "$MOD_DIR/osmtool_config.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
report)
|
||||
bash "$MOD_DIR/osmtool_report.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
smoke)
|
||||
bash "$MOD_DIR/osmtool_smoke.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
cron)
|
||||
bash "$MOD_DIR/osmtool_cron.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
restore)
|
||||
bash "$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)" \
|
||||
"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:-$APP_LANG}"
|
||||
PROFILE="grid-sim"
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
MODE="ui"
|
||||
ui_flow
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "h" || "${1:-}" == "help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "server_install" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
log INFO "Running server_install shortcut (prepare-ubuntu -> install-opensim-deps -> install-dotnet8 -> server-check -> install-opensim -> configure-opensim)"
|
||||
dispatch_module install --action prepare-ubuntu --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim-deps --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-dotnet8 --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action server-check --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action configure-opensim --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "configinit" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
dispatch_module config --action init-config --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "install-grid-sim" ]]; then
|
||||
PROFILE="grid-sim"
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
# Pflichtparameter: Datenbank-Credentials und Anzahl Simulatoren
|
||||
_db_user="${OSM_DB_USER:-}"
|
||||
_db_pass="${OSM_DB_PASS:-}"
|
||||
_sim_count="${OSM_SIM_COUNT:-1}"
|
||||
_hostname="${OSM_HOST:-}"
|
||||
_gridname="${OSM_GRIDNAME:-}"
|
||||
|
||||
if [[ -z "$_db_user" || -z "$_db_pass" ]]; then
|
||||
log ERROR "Datenbankzugangsdaten fehlen. Vor dem Aufruf setzen:"
|
||||
log ERROR " export OSM_DB_USER=opensim"
|
||||
log ERROR " export OSM_DB_PASS='MeinSicheresPasswort'"
|
||||
log ERROR " export OSM_SIM_COUNT=3 # Anzahl sim-Instanzen"
|
||||
log ERROR " export OSM_HOST=1.2.3.4 # Öffentliche IP oder Hostname"
|
||||
log ERROR " export OSM_GRIDNAME='Mein Grid'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log INFO "Starte install-grid-sim (prepare-ubuntu → deps → dotnet8 → server-check → install-opensim → configure-database → configure-opensim)"
|
||||
|
||||
dispatch_module install --action prepare-ubuntu --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim-deps --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-dotnet8 --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action server-check --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim --workdir "$DEFAULT_WORKDIR"
|
||||
# Datenbanken vor configure-opensim anlegen (ConnectionStrings werden danach geschrieben)
|
||||
dispatch_module install --action configure-database --workdir "$DEFAULT_WORKDIR" \
|
||||
--db-user "$_db_user" --db-pass "$_db_pass" --sim-count "$_sim_count"
|
||||
# Ini-Dateien mit Credentials, Hostname und Gridname befüllen
|
||||
dispatch_module install --action configure-opensim --workdir "$DEFAULT_WORKDIR" \
|
||||
--db-user "$_db_user" --db-pass "$_db_pass" \
|
||||
${_hostname:+--public-host "$_hostname"} \
|
||||
${_gridname:+--gridname "$_gridname"}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "opensimstart" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target "$(default_target_for_profile "$PROFILE")" --action start --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "opensimstop" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target "$(default_target_for_profile "$PROFILE")" --action stop --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "opensimrestart" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target "$(default_target_for_profile "$PROFILE")" --action restart --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "healthcheck" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module health --action run --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "smoketest" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module smoke --action run --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "dailyreport" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module report --action generate --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "croninstall" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module cron --action install --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "cronlist" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module cron --action list --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "janusinstall" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module install --action install-janus --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "janusrestart" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target janus --action restart --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "dbsetup" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
DB_USER_SHORT="${OSM_DB_USER:-opensim}"
|
||||
DB_PASS_SHORT="${OSM_DB_PASS:-}"
|
||||
DB_ROOT_USER_SHORT="${OSM_DB_ROOT_USER:-root}"
|
||||
DB_ROOT_PASS_SHORT="${OSM_DB_ROOT_PASS:-}"
|
||||
|
||||
[[ -n "$DB_PASS_SHORT" ]] || die "dbsetup requires OSM_DB_PASS environment variable"
|
||||
|
||||
dispatch_module install --action configure-database --workdir "$DEFAULT_WORKDIR" --db-user "$DB_USER_SHORT" --db-pass "$DB_PASS_SHORT" --db-root-user "$DB_ROOT_USER_SHORT" --db-root-pass "$DB_ROOT_PASS_SHORT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "dbbackup" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
DB_USER_SHORT="${OSM_DB_USER:-root}"
|
||||
DB_PASS_SHORT="${OSM_DB_PASS:-}"
|
||||
DB_NAME_SHORT="${OSM_DB_NAME:-opensim}"
|
||||
|
||||
[[ -n "$DB_PASS_SHORT" ]] || die "dbbackup requires OSM_DB_PASS environment variable"
|
||||
|
||||
dispatch_module backup --action db-backup --workdir "$DEFAULT_WORKDIR" --db-user "$DB_USER_SHORT" --db-pass "$DB_PASS_SHORT" --db-name "$DB_NAME_SHORT"
|
||||
exit 0
|
||||
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
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
MOD_DIR="$BASE_DIR/modular"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
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]
|
||||
osmtool_main.sh server_install
|
||||
osmtool_main.sh <configinit|install-grid-sim|opensimstart|opensimstop|opensimrestart|healthcheck|smoketest|dailyreport|croninstall|cronlist|janusinstall|janusrestart|dbsetup|dbbackup>
|
||||
|
||||
Examples:
|
||||
osmtool_main.sh install-grid-sim
|
||||
osmtool_main.sh server_install
|
||||
osmtool_main.sh opensimstart
|
||||
osmtool_main.sh opensimrestart
|
||||
osmtool_main.sh croninstall
|
||||
osmtool_main.sh dbbackup
|
||||
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)
|
||||
bash "$MOD_DIR/osmtool_install.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
startstop)
|
||||
bash "$MOD_DIR/osmtool_startstop.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
cleanup)
|
||||
bash "$MOD_DIR/osmtool_cleanup.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
health)
|
||||
bash "$MOD_DIR/osmtool_health.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
backup)
|
||||
bash "$MOD_DIR/osmtool_data.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
update)
|
||||
bash "$MOD_DIR/osmtool_update.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
config)
|
||||
bash "$MOD_DIR/osmtool_config.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
report)
|
||||
bash "$MOD_DIR/osmtool_report.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
smoke)
|
||||
bash "$MOD_DIR/osmtool_smoke.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
cron)
|
||||
bash "$MOD_DIR/osmtool_cron.sh" --profile "$PROFILE" "$@"
|
||||
;;
|
||||
restore)
|
||||
bash "$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)" \
|
||||
"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:-$APP_LANG}"
|
||||
PROFILE="grid-sim"
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
MODE="ui"
|
||||
ui_flow
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "h" || "${1:-}" == "help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "server_install" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
log INFO "Running server_install shortcut (prepare-ubuntu -> install-opensim-deps -> install-dotnet8 -> server-check -> install-opensim -> configure-opensim)"
|
||||
dispatch_module install --action prepare-ubuntu --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim-deps --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-dotnet8 --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action server-check --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action configure-opensim --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "configinit" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
dispatch_module config --action init-config --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "install-grid-sim" ]]; then
|
||||
PROFILE="grid-sim"
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
# Pflichtparameter: Datenbank-Credentials und Anzahl Simulatoren
|
||||
_db_user="${OSM_DB_USER:-}"
|
||||
_db_pass="${OSM_DB_PASS:-}"
|
||||
_sim_count="${OSM_SIM_COUNT:-1}"
|
||||
_hostname="${OSM_HOST:-}"
|
||||
_gridname="${OSM_GRIDNAME:-}"
|
||||
|
||||
if [[ -z "$_db_user" || -z "$_db_pass" ]]; then
|
||||
log ERROR "Datenbankzugangsdaten fehlen. Vor dem Aufruf setzen:"
|
||||
log ERROR " export OSM_DB_USER=opensim"
|
||||
log ERROR " export OSM_DB_PASS='MeinSicheresPasswort'"
|
||||
log ERROR " export OSM_SIM_COUNT=3 # Anzahl sim-Instanzen"
|
||||
log ERROR " export OSM_HOST=1.2.3.4 # Öffentliche IP oder Hostname"
|
||||
log ERROR " export OSM_GRIDNAME='Mein Grid'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log INFO "Starte install-grid-sim (prepare-ubuntu → deps → dotnet8 → server-check → install-opensim → configure-database → configure-opensim)"
|
||||
|
||||
dispatch_module install --action prepare-ubuntu --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim-deps --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-dotnet8 --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action server-check --workdir "$DEFAULT_WORKDIR"
|
||||
dispatch_module install --action install-opensim --workdir "$DEFAULT_WORKDIR"
|
||||
# Datenbanken vor configure-opensim anlegen (ConnectionStrings werden danach geschrieben)
|
||||
dispatch_module install --action configure-database --workdir "$DEFAULT_WORKDIR" \
|
||||
--db-user "$_db_user" --db-pass "$_db_pass" --sim-count "$_sim_count"
|
||||
# Ini-Dateien mit Credentials, Hostname und Gridname befüllen
|
||||
dispatch_module install --action configure-opensim --workdir "$DEFAULT_WORKDIR" \
|
||||
--db-user "$_db_user" --db-pass "$_db_pass" \
|
||||
${_hostname:+--public-host "$_hostname"} \
|
||||
${_gridname:+--gridname "$_gridname"}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "opensimstart" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target "$(default_target_for_profile "$PROFILE")" --action start --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "opensimstop" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target "$(default_target_for_profile "$PROFILE")" --action stop --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "opensimrestart" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target "$(default_target_for_profile "$PROFILE")" --action restart --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "healthcheck" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module health --action run --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "smoketest" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module smoke --action run --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "dailyreport" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module report --action generate --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "croninstall" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module cron --action install --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "cronlist" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module cron --action list --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "janusinstall" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module install --action install-janus --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "janusrestart" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
dispatch_module startstop --target janus --action restart --workdir "$DEFAULT_WORKDIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "dbsetup" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
DB_USER_SHORT="${OSM_DB_USER:-opensim}"
|
||||
DB_PASS_SHORT="${OSM_DB_PASS:-}"
|
||||
DB_ROOT_USER_SHORT="${OSM_DB_ROOT_USER:-root}"
|
||||
DB_ROOT_PASS_SHORT="${OSM_DB_ROOT_PASS:-}"
|
||||
|
||||
[[ -n "$DB_PASS_SHORT" ]] || die "dbsetup requires OSM_DB_PASS environment variable"
|
||||
|
||||
dispatch_module install --action configure-database --workdir "$DEFAULT_WORKDIR" --db-user "$DB_USER_SHORT" --db-pass "$DB_PASS_SHORT" --db-root-user "$DB_ROOT_USER_SHORT" --db-root-pass "$DB_ROOT_PASS_SHORT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "dbbackup" ]]; then
|
||||
set_language "$LANG_OVERRIDE"
|
||||
validate_profile "$PROFILE"
|
||||
|
||||
DB_USER_SHORT="${OSM_DB_USER:-root}"
|
||||
DB_PASS_SHORT="${OSM_DB_PASS:-}"
|
||||
DB_NAME_SHORT="${OSM_DB_NAME:-opensim}"
|
||||
|
||||
[[ -n "$DB_PASS_SHORT" ]] || die "dbbackup requires OSM_DB_PASS environment variable"
|
||||
|
||||
dispatch_module backup --action db-backup --workdir "$DEFAULT_WORKDIR" --db-user "$DB_USER_SHORT" --db-pass "$DB_PASS_SHORT" --db-name "$DB_NAME_SHORT"
|
||||
exit 0
|
||||
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
|
||||
|
||||
+269
-269
@@ -1,270 +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
|
||||
#!/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
|
||||
@@ -1,42 +1,42 @@
|
||||
#!/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
|
||||
|
||||
MODULE="${1:-}"
|
||||
ACTION="${2:-}"
|
||||
PROFILE="${3:-grid-sim}"
|
||||
LANG="${4:-de}"
|
||||
WORKDIR="${5:-/opt}"
|
||||
|
||||
shift $(( $# >= 5 ? 5 : $# ))
|
||||
|
||||
EXTRA_ARGS=("$@")
|
||||
|
||||
case "$MODULE" in
|
||||
install|startstop|cleanup|health|backup|restore|update|config|report|smoke|cron) ;;
|
||||
*) echo "ERROR: unsupported module" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
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" --module "$MODULE" --action "$ACTION" "${EXTRA_ARGS[@]}"
|
||||
}
|
||||
|
||||
run_main
|
||||
#!/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
|
||||
|
||||
MODULE="${1:-}"
|
||||
ACTION="${2:-}"
|
||||
PROFILE="${3:-grid-sim}"
|
||||
LANG="${4:-de}"
|
||||
WORKDIR="${5:-/opt}"
|
||||
|
||||
shift $(( $# >= 5 ? 5 : $# ))
|
||||
|
||||
EXTRA_ARGS=("$@")
|
||||
|
||||
case "$MODULE" in
|
||||
install|startstop|cleanup|health|backup|restore|update|config|report|smoke|cron) ;;
|
||||
*) echo "ERROR: unsupported module" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
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" --module "$MODULE" --action "$ACTION" "${EXTRA_ARGS[@]}"
|
||||
}
|
||||
|
||||
run_main
|
||||
|
||||
Reference in New Issue
Block a user