Merge branch 'wartung/einstellungen-stand-altreste' into wartung/restarbeiten
# Conflicts: # deploy/deploy.sh
This commit is contained in:
+13
-8
@@ -24,6 +24,10 @@ BACKUP_DIR="${MC_BACKUP_DIR:-/srv/models/mc2-backups}"
|
||||
JOB_TIMEOUT="${MC_AUTOUPDATE_JOB_TIMEOUT:-1200}" # Sekunden für den Hermes-Job
|
||||
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||
|
||||
# Wartungsfenster für den Neustart (seit 24.09.2026 einstellbar): im_wartungsfenster, fenster_text.
|
||||
# shellcheck source=deploy/wartungsfenster.sh
|
||||
. "$SRC_DIR/wartungsfenster.sh"
|
||||
|
||||
say(){ echo "[autoupdate] $*"; }
|
||||
notify(){ bash "$SRC_DIR/notify.sh" -s "[Box-Update]" "$1" || true; }
|
||||
# Dringend = geht auch nachts sofort raus (sonst sammelt notify.sh bis zur Morgenmeldung um 07:00).
|
||||
@@ -190,8 +194,9 @@ Wahrscheinliche Ursache/Fix (Box-Diagnose): $sugg}"
|
||||
# laeuft die Box weiter auf dem alten Kernel. Das faellt niemandem auf — am
|
||||
# 27.08.2026 lag die Box 7 Wochen mit drei ungenutzten Kerneln da.
|
||||
#
|
||||
# Der Neustart haengt bewusst am WOECHENTLICHEN Lauf (So 04:30) und nicht an
|
||||
# einem eigenen Timer: ein Ort fuer alle Automatik (Lehre vom 20.08.).
|
||||
# Der Neustart haengt bewusst am WOECHENTLICHEN Lauf (Standard So 04:30, in den
|
||||
# Einstellungen der Oberflaeche verschiebbar) und nicht an einem eigenen Timer:
|
||||
# ein Ort fuer alle Automatik (Lehre vom 20.08.).
|
||||
# Er passiert NUR, wenn Ubuntu ihn selbst anfordert (/var/run/reboot-required).
|
||||
#
|
||||
# WICHTIG: Die Linger-Pruefung ist die entscheidende Zeile hier. Ohne Linger=yes
|
||||
@@ -207,14 +212,14 @@ reboot_wenn_noetig(){
|
||||
|
||||
local pakete; pakete="$(sort -u /var/run/reboot-required.pkgs 2>/dev/null | tr '\n' ' ')"
|
||||
|
||||
# Sicherung 0 (24.09.2026): neu gestartet wird nur im Wartungsfenster, sonntags 04:00-06:59.
|
||||
# Sicherung 0 (24.09.2026): neu gestartet wird nur im Wartungsfenster — drei Stunden ab der vollen
|
||||
# Stunde des eingestellten Update-Beginns, Standard Sonntag 04:00-06:59 (deploy/wartungsfenster.sh).
|
||||
# Anlass: Ein nachgeholter Lauf (Persistent=true beim Einschalten des Timers) startete die Box
|
||||
# an einem Donnerstagnachmittag neu. Laeufe ausserhalb des Fensters melden den Neustart nur an.
|
||||
local tag stunde
|
||||
tag="$(date +%u)"; stunde="$((10#$(date +%H)))"
|
||||
if [ "${MC_AUTOUPDATE_REBOOT_JETZT:-0}" != "1" ] && { [ "$tag" != "7" ] || [ "$stunde" -lt 4 ] || [ "$stunde" -ge 7 ]; }; then
|
||||
notify "Neustart steht an (${pakete:-Kernel/libc}), passiert aber erst im Wartungsfenster am Sonntag frueh."
|
||||
verlauf neustart offen "Neustart steht an (${pakete:-Kernel/libc}), erst im Wartungsfenster am Sonntag früh."
|
||||
if [ "${MC_AUTOUPDATE_REBOOT_JETZT:-0}" != "1" ] && ! im_wartungsfenster; then
|
||||
local fenster; fenster="$(fenster_text)"
|
||||
notify "Neustart steht an (${pakete:-Kernel/libc}), passiert aber erst im Wartungsfenster ($fenster)."
|
||||
verlauf neustart offen "Neustart steht an (${pakete:-Kernel/libc}), erst im Wartungsfenster ($fenster)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
||||
+49
-8
@@ -8,8 +8,9 @@
|
||||
# erst beim nächsten Lauf (die alte Falle: bash lief nach dem Pull mit der alten Datei).
|
||||
# Stufe 2: Prüftor (deploy/pruefen.sh), Abhängigkeiten, llama-swap-Config nur, wenn sich der
|
||||
# Abzug in DIESEM Deploy geändert hat, Units/Drop-ins/Cron-Skripte/Skills/Plugins
|
||||
# ausspielen, Dienste neu starten, Nachprüfung. Scheitert irgendein Schritt: zurück auf
|
||||
# den alten Stand, Dienste neu starten, dringende Meldung.
|
||||
# ausspielen (den Radar-Schalter der Oberfläche respektieren), Dienste neu starten,
|
||||
# Nachprüfung, Stand-Datei schreiben. Scheitert irgendein Schritt: zurück auf den alten
|
||||
# Stand, Dienste neu starten, dringende Meldung.
|
||||
#
|
||||
# Aufruf auf der Box: bash ~/mission-control-v2/deploy/deploy.sh
|
||||
# Schalter: MC_DEPLOY_TROTZDEM=1 (auch bei laufenden Jobs), MC_DEPLOY_OHNE_TESTS=1 (Notfall),
|
||||
@@ -21,6 +22,9 @@ export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||
API="http://127.0.0.1:9001"
|
||||
LSWAP_LIVE="/etc/llama-swap/config.yaml"
|
||||
DEPLOY_LOG="/srv/models/mc2-deploy.log"
|
||||
# Einstellungen der Oberfläche (Radar-Schalter, Update-Zeitfenster) und der Software-Stand (seit 24.09.2026).
|
||||
EINSTELLUNGEN="/srv/models/mc2-einstellungen.json"
|
||||
STAND_DATEI="/srv/models/mc2-stand.json"
|
||||
|
||||
# Units, die ganz dem Repo gehören (deploy.sh spielt sie aus). Aktiviert wird nur, was laufen soll:
|
||||
# Konsole und Spracherkennung schlafen seit 24.09.2026 (disable --now), ihre Units bleiben aber aktuell.
|
||||
@@ -42,6 +46,27 @@ SKILLS_ALT="autonomie konzept-fliessband llm-wiki morning-report orchestrator pr
|
||||
review trend-radar wartung konzept_fliessband llm_wiki morning_report projekt_start
|
||||
trend_radar betrieb-playbook pc-pfad-cache"
|
||||
|
||||
# Radar-Schalter der Oberfläche (Einstellungen → Modell-Radar): Steht er auf aus, bleibt mc2-radar.timer aus.
|
||||
# Fehlt die Datei oder ist sie unlesbar, gilt „an“ wie vor dem Schalter.
|
||||
radar_aus() {
|
||||
python3 - "$EINSTELLUNGEN" <<'PY' 2>/dev/null
|
||||
import json
|
||||
import sys
|
||||
|
||||
try:
|
||||
with open(sys.argv[1], encoding="utf-8") as f:
|
||||
an = (json.load(f).get("radar") or {}).get("an", True)
|
||||
except (OSError, ValueError, AttributeError):
|
||||
an = True
|
||||
sys.exit(0 if an is False else 1)
|
||||
PY
|
||||
}
|
||||
|
||||
# Software-Stand für die Oberfläche (Einstellungen → Software-Stand): Commit, Betreff, Commit-Datum, Zeitpunkt.
|
||||
stand_schreiben() {
|
||||
git log -1 --format='%h%n%cI%n%s' HEAD | python3 deploy/stand-schreiben.py "$STAND_DATEI"
|
||||
}
|
||||
|
||||
# Laufende Update-Aufträge (Gruppe maintenance). Seit Phase 2 überleben Aufträge den Neustart von
|
||||
# MC2 (eigene systemd-Einheiten) — ein Download darf also weiterlaufen. Ein Update aber führt
|
||||
# Skripte aus diesem Checkout aus; die darf der Deploy nicht mitten im Lauf austauschen.
|
||||
@@ -119,22 +144,37 @@ stufe2() {
|
||||
echo "Hinweis: Die lebende llama-swap-Config weicht vom Repo-Abzug ab (Änderung über die Oberfläche?) — nicht angefasst."
|
||||
fi
|
||||
|
||||
# 4. Units und Drop-ins (alle Repo-Units, damit Box und Repo nicht auseinanderlaufen)
|
||||
local ziel="$HOME/.config/systemd/user" u
|
||||
# 4. Units und Drop-ins (alle Repo-Units, damit Box und Repo nicht auseinanderlaufen). Das Drop-in
|
||||
# mc2-autoupdate.timer.d/zeitfenster.conf gehört der Oberfläche (Einstellungen → Update-Zeitfenster):
|
||||
# Der Deploy überschreibt und löscht es nie.
|
||||
local ziel="$HOME/.config/systemd/user" u aktiv="$AKTIV" radar_an=1
|
||||
for u in $UNITS; do
|
||||
install -m 644 "deploy/$u" "$ziel/$u"
|
||||
done
|
||||
install -D -m 644 deploy/mc2-steward.service.d-warmset.conf "$ziel/mc2-steward.service.d/warmset.conf"
|
||||
install -D -m 644 deploy/mission-control-2.service.d-override.conf "$ziel/mission-control-2.service.d/override.conf"
|
||||
systemctl --user daemon-reload
|
||||
# Radar-Schalter der Oberfläche: Steht er auf aus, bleibt der Timer aus (vorher schaltete jeder Deploy ihn ein).
|
||||
if radar_aus; then
|
||||
radar_an=0
|
||||
aktiv="${aktiv//mc2-radar.timer/}"
|
||||
systemctl --user disable --now mc2-radar.timer >/dev/null 2>&1 || true
|
||||
echo "Modell-Radar ist in den Einstellungen ausgeschaltet — es bleibt aus."
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
systemctl --user enable $AKTIV >/dev/null 2>&1
|
||||
systemctl --user enable $aktiv >/dev/null 2>&1
|
||||
# shellcheck disable=SC2086
|
||||
systemctl --user start mc2-radar.timer mc2-backup.timer mc2-morgenmeldung.timer projekte-sync.timer \
|
||||
mc2-probe-wiederherstellung.timer
|
||||
systemctl --user start mc2-backup.timer mc2-morgenmeldung.timer projekte-sync.timer mc2-probe-wiederherstellung.timer
|
||||
# Den Radar-Timer nur ohne Nachholen starten (Persistent=true): Läuft er nicht, erst den Stempel auf jetzt
|
||||
# setzen — sonst holt er den verpassten Lauf sofort nach, mitten am Tag.
|
||||
if [ "$radar_an" = 1 ] && ! systemctl --user is-active --quiet mc2-radar.timer; then
|
||||
mkdir -p "$HOME/.local/share/systemd/timers"
|
||||
touch "$HOME/.local/share/systemd/timers/stamp-mc2-radar.timer"
|
||||
systemctl --user start mc2-radar.timer
|
||||
fi
|
||||
# Den Update-Timer nur starten, wenn er nicht schon läuft: Mit Persistent=true holt ein frisch
|
||||
# gestarteter Timer einen verpassten Sonntagslauf sofort nach (so am 24.09.2026 passiert). Neu
|
||||
# gestartet wird die Box dabei ohnehin nur sonntags zwischen 04 und 07 Uhr (autoupdate.sh).
|
||||
# gestartet wird die Box dabei ohnehin nur im Wartungsfenster (autoupdate.sh, wartungsfenster.sh).
|
||||
systemctl --user is-active --quiet mc2-autoupdate.timer || systemctl --user start mc2-autoupdate.timer
|
||||
|
||||
# 5. Cron-Skripte für Hermes (~/.hermes/scripts ist die Vorgabe von `hermes cron --script`)
|
||||
@@ -179,6 +219,7 @@ stufe2() {
|
||||
|
||||
trap - ERR
|
||||
echo "$(date -Is) $neu (vorher ${vorher:0:7})" >> "$DEPLOY_LOG" 2>/dev/null || true
|
||||
stand_schreiben || echo "Hinweis: Die Stand-Datei $STAND_DATEI ließ sich nicht schreiben."
|
||||
echo "✅ Deploy $neu ist live (vorher ${vorher:0:7})."
|
||||
homelab_mitziehen
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# ausrollen.sh — den Homelab-Teil in seinen Container bringen (erstmals und bei jedem Update).
|
||||
#
|
||||
# Läuft am PC (Git-Bash, im Repo). Schickt den Stand von HEAD (backend, deploy, frontend/dist) per SSH in
|
||||
# den Container, lässt einrichten.sh laufen und startet die Dienste neu. Der Container braucht so keinen
|
||||
# Zugang zu Gitea. Vorher: bash deploy/pruefen.sh (und deploy/probelauf-box.sh).
|
||||
# Läuft am PC (Git-Bash, im Repo) oder im Deploy der Box. Schickt den Stand von HEAD (backend, deploy,
|
||||
# frontend/dist) per SSH in den Container, lässt einrichten.sh laufen und startet die Dienste neu. Danach hält
|
||||
# es den Stand in /var/lib/mc2/mc2-stand.json fest. Der Container braucht so keinen Zugang zu Gitea.
|
||||
# Vorher: bash deploy/pruefen.sh (und deploy/probelauf-box.sh).
|
||||
#
|
||||
# Nutzung: bash deploy/homelab/ausrollen.sh <ip-des-containers> [partner-url]
|
||||
set -euo pipefail
|
||||
@@ -17,3 +18,10 @@ git archive --format=tar HEAD backend deploy frontend/dist ruff.toml \
|
||||
| ssh -o BatchMode=yes "$ZIEL" "mkdir -p /opt/mc2 && find /opt/mc2 -mindepth 1 -maxdepth 1 ! -name backend -exec rm -rf {} + \
|
||||
&& find /opt/mc2/backend -mindepth 1 -maxdepth 1 ! -name .venv -exec rm -rf {} + 2>/dev/null; tar -x -C /opt/mc2"
|
||||
ssh -o BatchMode=yes "$ZIEL" "bash /opt/mc2/deploy/homelab/einrichten.sh '$PARTNER'"
|
||||
# Software-Stand für die Oberfläche (Einstellungen → Software-Stand, seit 24.09.2026): erst nach erfolgreichem
|
||||
# Einrichten, also wenn dieser Stand wirklich läuft. Liegt im Datenordner, den das Ausrollen nicht leert. Scheitert
|
||||
# nur das, gilt das Ausrollen trotzdem als gelungen.
|
||||
git log -1 --format='%h%n%cI%n%s' HEAD \
|
||||
| ssh -o BatchMode=yes "$ZIEL" "python3 /opt/mc2/deploy/stand-schreiben.py /var/lib/mc2/mc2-stand.json \
|
||||
&& chown mc2:mc2 /var/lib/mc2/mc2-stand.json" \
|
||||
|| echo "Hinweis: Die Stand-Datei im Container ließ sich nicht schreiben."
|
||||
|
||||
+24
-4
@@ -102,13 +102,22 @@ env_wert() {
|
||||
wert="${wert%\'}"; wert="${wert#\'}"
|
||||
printf '%s' "$wert"
|
||||
}
|
||||
# Warum der Zweitweg scheiterte, steht seit 24.09.2026 mit im FALLBACK-Eintrag (der Telegram-Test der Oberfläche
|
||||
# zeigt es an). Ohne Klammern im Text: services/update_verlauf.py trennt den Eintrag an „): “.
|
||||
DIREKT_GRUND=""
|
||||
telegram_direkt() {
|
||||
local token chat thread text
|
||||
[ -r "$TG_ENV" ] || return 1
|
||||
local token chat thread text rc
|
||||
if [ ! -r "$TG_ENV" ]; then
|
||||
DIREKT_GRUND="Zugangsdatei $TG_ENV fehlt oder ist nicht lesbar"
|
||||
return 1
|
||||
fi
|
||||
token="$(env_wert TELEGRAM_BOT_TOKEN)"
|
||||
chat="$(env_wert TELEGRAM_HOME_CHANNEL)"
|
||||
thread="$(env_wert TELEGRAM_HOME_CHANNEL_THREAD_ID)"
|
||||
[ -n "$token" ] && [ -n "$chat" ] || return 1
|
||||
if [ -z "$token" ] || [ -z "$chat" ]; then
|
||||
DIREKT_GRUND="TELEGRAM_BOT_TOKEN oder TELEGRAM_HOME_CHANNEL fehlt in $TG_ENV"
|
||||
return 1
|
||||
fi
|
||||
text="$MSG"
|
||||
[ -n "$SUBJECT" ] && text="$SUBJECT
|
||||
$MSG"
|
||||
@@ -116,6 +125,15 @@ $MSG"
|
||||
| curl -sf -m 15 -o /dev/null --config - \
|
||||
--data-urlencode "chat_id=$chat" --data-urlencode "text=$text" \
|
||||
${thread:+--data-urlencode "message_thread_id=$thread"}
|
||||
rc=$?
|
||||
case "$rc" in
|
||||
0) return 0 ;;
|
||||
22) DIREKT_GRUND="Telegram lehnt ab, HTTP-Fehler – Token oder Chat falsch?" ;;
|
||||
6|7) DIREKT_GRUND="Telegram nicht erreichbar, keine Verbindung" ;;
|
||||
28) DIREKT_GRUND="Telegram antwortet nicht rechtzeitig" ;;
|
||||
*) DIREKT_GRUND="curl endete mit Code $rc" ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
if telegram_direkt; then
|
||||
# „OK telegram direkt“: services/update_verlauf.py erkennt beide Wege.
|
||||
@@ -124,7 +142,9 @@ if telegram_direkt; then
|
||||
fi
|
||||
|
||||
# Letzter Ausweg: Logfile + wall — Meldung darf nie verloren gehen.
|
||||
echo "$TS FALLBACK (telegram fehlgeschlagen: $SEND_OUT): $MSG" >> "$LOG"
|
||||
GRUND="$SEND_OUT"
|
||||
[ -n "$DIREKT_GRUND" ] && GRUND="${GRUND:+$GRUND; }Zweitweg: $DIREKT_GRUND"
|
||||
echo "$TS FALLBACK (telegram fehlgeschlagen: $GRUND): $MSG" >> "$LOG"
|
||||
if [ "${MC_NOTIFY_OHNE_WALL:-0}" != "1" ]; then
|
||||
printf '%s\n' "MC2-Meldung: ${SUBJECT:+$SUBJECT }$MSG" | wall 2>/dev/null || true
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
"""stand-schreiben.py — den Software-Stand einer Instanz festhalten (seit 24.09.2026).
|
||||
|
||||
deploy.sh (KI-Box) und homelab/ausrollen.sh (Container des Homelab-Teils) rufen es nach einem erfolgreichen
|
||||
Umschalten auf. Es liest drei Zeilen von stdin, genau wie `git log -1 --format='%h%n%cI%n%s'` sie liefert:
|
||||
Commit kurz, Commit-Datum (ISO), Betreff. Dazu kommt der Zeitpunkt des Deploys, und alles landet als JSON in der
|
||||
angegebenen Datei (atomar). Die Oberfläche zeigt daraus „Software-Stand“ (backend/services/software_stand.py).
|
||||
|
||||
Nur Standardbibliothek: Es läuft mit dem python3 des Systems, auch im Container ohne git.
|
||||
|
||||
Nutzung: git log -1 --format='%h%n%cI%n%s' HEAD | python3 deploy/stand-schreiben.py /srv/models/mc2-stand.json
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def stand_aus(zeilen: list[str], jetzt: datetime) -> dict:
|
||||
"""Die drei git-Zeilen und der Zeitpunkt des Deploys als Stand. Leere Felder werden None."""
|
||||
commit, datum, betreff = ([z.strip() for z in zeilen] + ["", "", ""])[:3]
|
||||
return {"commit": commit or None, "betreff": betreff or None, "commit_datum": datum or None,
|
||||
"deploy_zeit": jetzt.isoformat(timespec="seconds")}
|
||||
|
||||
|
||||
def schreiben(ziel: Path, stand: dict) -> None:
|
||||
"""Atomar: erst eine Nachbardatei, dann umbenennen — ein Leser sieht nie eine halbe Datei."""
|
||||
ziel.parent.mkdir(parents=True, exist_ok=True)
|
||||
fd, tmp = tempfile.mkstemp(prefix=".mc2-stand-", suffix=".tmp", dir=ziel.parent)
|
||||
try:
|
||||
with os.fdopen(fd, "w", encoding="utf-8") as f:
|
||||
json.dump(stand, f, ensure_ascii=False, indent=1)
|
||||
os.chmod(tmp, 0o644)
|
||||
os.replace(tmp, ziel)
|
||||
except BaseException:
|
||||
Path(tmp).unlink(missing_ok=True)
|
||||
raise
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
if len(argv) != 2:
|
||||
print("Nutzung: git log -1 --format='%h%n%cI%n%s' | python3 stand-schreiben.py <datei>", file=sys.stderr)
|
||||
return 2
|
||||
# Bytes lesen und selbst als UTF-8 deuten: Im Container ist die Locale oft C/POSIX.
|
||||
zeilen = sys.stdin.buffer.read().decode("utf-8", "replace").splitlines()
|
||||
stand = stand_aus(zeilen, datetime.now().astimezone())
|
||||
if not stand["commit"]:
|
||||
print("Kein Commit auf stdin — Stand nicht geschrieben.", file=sys.stderr)
|
||||
return 1
|
||||
schreiben(Path(argv[1]), stand)
|
||||
print(f"Stand {stand['commit']} festgehalten in {argv[1]}.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# wartungsfenster.sh — wann die Box nach einem Update neu starten darf (zum Einbinden, seit 24.09.2026).
|
||||
#
|
||||
# autoupdate.sh bindet es ein (source). Das Fenster beginnt zur vollen Stunde des eingestellten Update-Beginns und
|
||||
# dauert drei Stunden: Standard So 04:30 → Sonntag 04:00–06:59 (so stand es bis 24.09. fest in autoupdate.sh).
|
||||
# Den Beginn stellt die Oberfläche ein (Einstellungen → Update-Zeitfenster); sie legt ihn in der Einstellungsdatei
|
||||
# ab und stellt den Timer um (backend/services/einstellungen.py, dort steht dieselbe Regel als Text für die Anzeige).
|
||||
#
|
||||
# Test-Schalter: MC_WARTUNGSFENSTER="<Tag 1-7> <HH:MM>" statt der Datei, MC_FENSTER_JETZT="<Tag 1-7> <HH:MM>"
|
||||
# (Zeit vortäuschen), MC_EINSTELLUNGEN (andere Datei).
|
||||
|
||||
WARTUNG_EINSTELLUNGEN="${MC_EINSTELLUNGEN:-/srv/models/mc2-einstellungen.json}"
|
||||
WARTUNG_DAUER_MIN=180
|
||||
WARTUNG_TAGE=(Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag)
|
||||
|
||||
# Setzt FENSTER_TAG (1 = Montag … 7 = Sonntag) und FENSTER_STUNDE. Fehlt die Datei oder steht Unsinn darin: So 04:30.
|
||||
fenster_lesen() {
|
||||
local roh="${MC_WARTUNGSFENSTER:-}" tag uhr
|
||||
if [ -z "$roh" ] && [ -r "$WARTUNG_EINSTELLUNGEN" ] && command -v jq >/dev/null 2>&1; then
|
||||
roh="$(jq -r '"\(.update_fenster.tag // 7) \(.update_fenster.uhrzeit // "04:30")"' "$WARTUNG_EINSTELLUNGEN" \
|
||||
2>/dev/null)"
|
||||
fi
|
||||
tag="${roh%% *}"
|
||||
uhr="${roh#* }"
|
||||
if ! [[ "$tag" =~ ^[1-7]$ && "$uhr" =~ ^([01][0-9]|2[0-3]):[0-5][0-9]$ ]]; then
|
||||
tag=7
|
||||
uhr="04:30"
|
||||
fi
|
||||
FENSTER_TAG="$tag"
|
||||
FENSTER_STUNDE="$((10#${uhr%%:*}))"
|
||||
}
|
||||
|
||||
# Erfolg (0), wenn jetzt Neustart-Zeit ist. Rechnet in Minuten ab Montag 00:00, damit ein Fenster über Mitternacht
|
||||
# (Samstag 23:00 – Sonntag 01:59) und über das Wochenende hinaus (Sonntag 23:00 – Montag 01:59) stimmt.
|
||||
im_wartungsfenster() {
|
||||
fenster_lesen
|
||||
local jetzt="${MC_FENSTER_JETZT:-$(date '+%u %H:%M')}" tag uhr minute beginn
|
||||
tag="${jetzt%% *}"
|
||||
uhr="${jetzt#* }"
|
||||
minute=$(( (tag - 1) * 1440 + 10#${uhr%%:*} * 60 + 10#${uhr##*:} ))
|
||||
beginn=$(( (FENSTER_TAG - 1) * 1440 + FENSTER_STUNDE * 60 ))
|
||||
[ $(( (minute - beginn + 10080) % 10080 )) -lt "$WARTUNG_DAUER_MIN" ]
|
||||
}
|
||||
|
||||
# Das Fenster in Worten, etwa „Sonntag 04:00–06:59“ oder „Samstag 23:00 – Sonntag 01:59“.
|
||||
fenster_text() {
|
||||
fenster_lesen
|
||||
local ende=$(( FENSTER_STUNDE * 60 + WARTUNG_DAUER_MIN - 1 )) tag_ende="$FENSTER_TAG" von bis
|
||||
if [ "$ende" -ge 1440 ]; then
|
||||
ende=$(( ende - 1440 ))
|
||||
tag_ende=$(( FENSTER_TAG % 7 + 1 ))
|
||||
fi
|
||||
von="$(printf '%02d:00' "$FENSTER_STUNDE")"
|
||||
bis="$(printf '%02d:%02d' $(( ende / 60 )) $(( ende % 60 )))"
|
||||
if [ "$tag_ende" = "$FENSTER_TAG" ]; then
|
||||
printf '%s %s–%s' "${WARTUNG_TAGE[FENSTER_TAG - 1]}" "$von" "$bis"
|
||||
else
|
||||
printf '%s %s – %s %s' "${WARTUNG_TAGE[FENSTER_TAG - 1]}" "$von" "${WARTUNG_TAGE[tag_ende - 1]}" "$bis"
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user