Wer einen länger laufenden Build per SSH auf einem Cloud-Mac startet, den Laptop zuklappt und sich später erneut verbindet, findet das ursprüngliche Terminal nicht mehr vor. Das größte Problem ist dabei nicht, den Build erneut auszuführen, sondern festzustellen, ob der Auftrag fehlgeschlagen, abgeschlossen oder noch im Hintergrund aktiv ist. Statt die Verbindungs-Timeouts pauschal zu verlängern, sollten Netzwerkverbindung, Terminalsitzung und eigentliche Aufgabe als drei getrennte Ebenen behandelt werden: SSH stellt den Zugang zum Knoten her, tmux bewahrt den Terminalkontext, und Protokolle sowie Exit-Code belegen das Ergebnis.
Zuerst klären, welche Ebene von der Unterbrechung betroffen ist
Wird eine Remote-Desktop- oder SSH-Verbindung getrennt, fällt lediglich der interaktive Kanal zwischen dem Client und dem Cloud-Mac aus. Der physische Knoten läuft deshalb weiter. Vordergrundprozesse, die direkt an das SSH-Pseudoterminal gebunden sind, können beim Schließen der Sitzung jedoch ein Hangup-Signal erhalten. Auch ein über die grafische Oberfläche geöffnetes Terminal eignet sich nicht als Einstiegspunkt für unbeaufsichtigte Aufgaben, da das Schließen des Fensters oder das Abmelden vom Desktop dessen Lebenszyklus beeinflusst.
Prüfen Sie die Umgebung zunächst mit einer zehnminütigen Testaufgabe, statt direkt einen produktiven Build für den ersten Versuch zu verwenden:
mkdir -p "$HOME/jobs/session-check"
cd "$HOME/jobs/session-check"
date -u +"start=%Y-%m-%dT%H:%M:%SZ" > run.log
sleep 600
date -u +"finish=%Y-%m-%dT%H:%M:%SZ" >> run.log
Trennen Sie anschließend bewusst die Verbindung, melden Sie sich erneut an und prüfen Sie run.log. Dieser Basistest bestätigt, ob der Knoten selbst weiterläuft, ersetzt aber keine Sitzungsverwaltung.
SSH-Keepalives regeln, wie schnell eine ausgefallene Verbindung erkannt wird. tmux sorgt dafür, dass nach einem Verbindungsabbruch weiterhin ein wiederherstellbares Terminal für die Aufgabe vorhanden ist. Beide Funktionen sind nicht austauschbar.
SSH-Keepalives und eindeutige Timeouts konfigurieren
Legen Sie in ~/.ssh/config auf dem lokalen Mac einen eigenen Eintrag für den Knoten an. Adresse und Benutzername müssen durch die tatsächlichen Werte aus der Verwaltungskonsole ersetzt werden:
Host minid-node
HostName <node-address>
User <system-user>
ServerAliveInterval 30
ServerAliveCountMax 3
TCPKeepAlive yes
ConnectTimeout 10
Mit ServerAliveInterval 30 sendet der Client alle 30 Sekunden eine Prüfung auf Anwendungsebene. Bleiben drei Prüfungen in Folge unbeantwortet, beendet SSH die ausgefallene Verbindung, statt das Terminal unbegrenzt hängen zu lassen. Dadurch wird weder automatisch eine neue Verbindung aufgebaut noch das Weiterlaufen eines Vordergrundprozesses garantiert.
Vor dem Verbindungsaufbau lässt sich die tatsächlich wirksame Konfiguration prüfen:
ssh -G minid-node | grep -E 'serveralive|tcpkeepalive|connecttimeout'
ssh minid-node
Bei häufigen Netzwerkwechseln sollten die Timeouts nicht auf mehrere zehn Minuten erhöht werden. Wird eine ausgefallene Verbindung schneller erkannt, kann man sich umgehend neu verbinden und den tatsächlichen Fortschritt in tmux prüfen.
Lang laufende Aufgaben mit tmux verwalten
Prüfen Sie zuerst, ob tmux verfügbar ist. Installieren Sie es nur bei Bedarf mit der Paketverwaltung der aktuellen Umgebung:
command -v tmux || brew install tmux
tmux new-session -s ios-build
Der Sitzungsname sollte den Zweck der Aufgabe erkennen lassen, etwa ios-build, integration-test oder asset-export. Ein nichtssagender Name wie work sollte nicht dauerhaft wiederverwendet werden. Erstellen Sie innerhalb der Sitzung ein eigenes Verzeichnis und leiten Sie die Ausgabe gleichzeitig an das Terminal und in eine Protokolldatei:
job_dir="$HOME/jobs/ios-build-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$job_dir"
cd "$job_dir"
set -o pipefail
caffeinate -i /path/to/run-build.sh 2>&1 | tee build.log
status=${PIPESTATUS[0]}
printf '%s
' "$status" > exit-code.txt
date -u +"%Y-%m-%dT%H:%M:%SZ" > finished-at.txt
Drücken Sie Control-b und anschließend d, um die Sitzung zu verlassen, ohne die Aufgabe zu beenden. Nach der erneuten Verbindung mit dem Knoten führen Sie Folgendes aus:
tmux list-sessions
tmux attach-session -t ios-build
caffeinate -i verhindert nur während der Ausführung des Befehls den Ruhezustand bei Inaktivität. Der Aufruf sollte an die konkrete Aufgabe gekoppelt und nicht aus Bequemlichkeit dauerhaft ausgeführt werden. Bei reinen Kommandozeilen-Builds muss das Display nicht künstlich aktiv gehalten werden.
Doppelte Starts vermeiden
Führen Sie nach einer Netzwerkunterbrechung zuerst tmux list-sessions und pgrep -fl run-build aus. Starten Sie die Aufgabe erst neu, wenn sicher feststeht, dass die vorherige Instanz nicht mehr vorhanden ist. Andernfalls könnten zwei Builds gleichzeitig in dasselbe Derived-Data-Verzeichnis, denselben Cache oder denselben Ausgabepfad schreiben und schwer reproduzierbare, vermischte Ergebnisse hinterlassen.
Protokolle und Exit-Code als Abnahmekriterien verwenden
Ein Terminal, dessen Ausgabe nach der erneuten Anmeldung weiterläuft, ist noch kein Erfolgsnachweis. Jede länger laufende Aufgabe sollte mindestens Startzeit, Endzeit, vollständiges Protokoll und Exit-Code hinterlassen. Nur der Exit-Code 0 zeigt an, dass das Skript wie vorgesehen erfolgreich beendet wurde. Ein bestimmtes Wort am Ende des Protokolls ist dafür kein Ersatz.
Mit der folgenden Prüfreihenfolge lässt sich der Status schnell feststellen:
| Prüfung | Befehl | Aussage |
|---|---|---|
| Ist die Sitzung vorhanden? | tmux list-sessions |
Eine vorhandene Sitzung bedeutet nicht, dass die Aufgabe noch läuft |
| Ist der Prozess vorhanden? | pgrep -fl run-build |
Bestätigt die aktuell ausgeführte Instanz |
| Wächst das Protokoll? | tail -n 30 build.log |
Zeigt Fortschritt oder eine mögliche Blockierung |
| Wurde die Aufgabe regulär beendet? | cat exit-code.txt |
0 bedeutet, dass das Skript erfolgreich war |
| Wann wurde die Aufgabe beendet? | cat finished-at.txt |
Zeigt, ob das Ergebnis zu diesem Lauf gehört |
Das Skript sollte für jeden Lauf ein neues Verzeichnis erstellen, statt die Protokolle des vorherigen Laufs zu überschreiben. Löschen Sie bei einer Bereinigung nur bereits geprüfte und archivierte Verzeichnisse nach Datum. Führen Sie keine rekursive Löschung für das gesamte Verzeichnis ~/jobs aus.
Vor dem Produktiveinsatz eine kontrollierte Unterbrechung testen
Starten Sie vor dem regulären Einsatz eine sicher wiederholbare Testaufgabe. Prüfen Sie anschließend nacheinander das Trennen der SSH-Verbindung, das Schließen des Remote-Desktops und einen Wechsel des lokalen Netzwerks. Kontrollieren Sie nach jeder erneuten Verbindung die tmux-Sitzung, den Zielprozess, das Wachstum des Protokolls und die Datei mit dem Exit-Code.
Hängt eine Aufgabe von einer grafischen Oberfläche ab, muss separat geprüft werden, ob sie nach dem Trennen des Remote-Desktops weiterläuft. Kommandozeilenwerkzeuge und grafische Anwendungen haben unterschiedliche Lebenszyklen. Wird eine Aufgabe vorzeitig beendet, prüfen Sie zuerst den Exit-Code und das Protokoll des Skripts, danach ein mögliches Schließen des Terminals und zuletzt den verfügbaren Speicherplatz sowie die Prozessressourcen. Nicht jeder Fehler ist auf das Netzwerk zurückzuführen.
Eine einsatzbereite Checkliste sollte folgende Punkte enthalten:
- Die SSH-Konfiguration lässt sich mit
ssh -Gverifizieren; - jede Art von Langzeitaufgabe verwendet eine eigene tmux-Sitzung;
- Aufgabenverzeichnisse werden mit Zeitstempel erstellt und überschreiben keine früheren Ergebnisse;
- Standardausgabe und Standardfehler werden in dasselbe durchsuchbare Protokoll geschrieben;
- Exit-Code und UTC-Endzeit werden separat gespeichert;
- nach einer Unterbrechung wird zuerst der vorhandene Zustand wiederhergestellt, ohne die Aufgabe doppelt zu starten;
- nicht mehr benötigte Sitzungen werden nach Abschluss gezielt beendet und die Ergebnisse archiviert.
Häufig gestellte Fragen
Wird eine Aufgabe bei einer unterbrochenen SSH-Verbindung immer beendet?
Nein. Ein direkt an das SSH-Terminal gebundener Prozess kann ein Abbruchsignal erhalten. Innerhalb von tmux läuft die Aufgabe normalerweise weiter und lässt sich nach der erneuten Anmeldung prüfen.
Reicht ServerAliveInterval aus, um einen langen Build abzusichern?
Nein. Die Einstellung erkennt nur eine nicht mehr reagierende Verbindung und schützt keinen Prozess. Der Build gehört in tmux; Ausgabe, Fehler und Exitcode sollten in Dateien geschrieben werden.
MiniD Cloud Mac
Dedizierten physischen Mac mini tage-, wochen- oder monatsweise mieten
Jeder Plan läuft auf einem dedizierten physischen Mac mini mit Remote-Desktop- und SSH-Zugang; aktuelle Modelle, Regionen und Laufzeiten stehen auf der Bestellseite.