Befehl nach SSH-Trennung weiterlaufen lassen
Bei SSH-Abbruch beendet SIGHUP Ihren Prozess. Vergleichen Sie nohup, disown, tmux und systemd-run, und wählen Sie die passende Methode für Ihren Job.
Warum Ihr Befehl beendet wird, wenn die SSH-Verbindung getrennt wird
Damit ein Befehl nach einer getrennten SSH-Verbindung weiterläuft, muss er sich an einem Ort befinden, den das Hangup-Signal nicht erreichen kann. Jede der folgenden Methoden setzt dies anders um. Beginnen wir daher mit dem Mechanismus.
Ihre Anmeldung läuft auf einem pty (Pseudo-Terminal), einem virtuellen Terminalgerät, das sshd auf dem Server für Ihre Sitzung erstellt. Es ist das steuernde Terminal Ihrer Shell und jedes Befehls, den Sie aus dieser Shell starten. Wenn Sie den weiteren Ablauf nachvollziehen möchten, erklärt was SSH beim Anmelden einrichtet die Details. Wenn die TCP-Verbindung abbricht, schließt sshd seine Seite, und das pty wird zerstört. Der Kernel behandelt dies als Trennung des Terminals. Deshalb sendet er SIGHUP an die Vordergrund-Prozessgruppe dieses Terminals und an den Sitzungsleiter, also Ihre Shell. Die Standardaktion für SIGHUP besteht darin, den Prozess zu beenden. Ihr Befehl gehörte zur Vordergrund-Prozessgruppe. Daher wird Ihr Befehl beendet.
Auch Hintergrundjobs sind nicht automatisch sicher. Ein mit & gestarteter Job befindet sich in einer eigenen Prozessgruppe. Der Kernel signalisiert ihn daher nicht direkt. Das übernimmt Bash. Beim Empfang von SIGHUP sendet eine interaktive Bash-Shell SIGHUP erneut an jeden Job in ihrer Jobtabelle, bevor sie beendet wird. Das Ergebnis ist aus Ihrer Sicht identisch: Der Job ist verschwunden, und die Logdatei endet mitten in einer Zeile.
Hier gibt es eine Asymmetrie, die häufig zu Verwirrung führt. Die Eingabe von exit trennt Ihre Hintergrundjobs nicht, weil Bash dies nur ausführt, wenn die Option huponexit gesetzt ist. Standardmäßig ist sie deaktiviert. Eine abgebrochene Verbindung beendet die Jobs dagegen. Der Job, der das manuelle Schließen des Terminals ordnungsgemäß überlebt hat, kann dennoch beendet werden, wenn die WLAN-Verbindung abbricht.
Daraus ergeben sich zwei Konsequenzen, die den gesamten Sachverhalt erklären. Ein Prozess, der SIGHUP ignoriert oder überhaupt kein steuerndes Terminal besitzt, wird nicht durch ein Hangup beendet. Wenn seine Standardausgabe weiterhin auf das zerstörte pty zeigt, kann der Prozess jedoch nirgendwohin schreiben. Der Schreibvorgang schlägt mit EIO (Ein-/Ausgabefehler) fehl, und die meisten Programme werden an diesem Punkt beendet. Sie müssen daher beide Probleme lösen. Viele Anleitungen lösen nur das erste. Deshalb berichten manche Benutzer, dass „nohup nicht funktioniert hat“.
Wenn Ihre Verbindung mehrmals täglich abbricht, sollten Sie auch dieses Problem beheben. ServerAliveInterval 60 in ~/.ssh/config verhindert, dass eine inaktive Sitzung aufgrund eines NAT-Timeouts (Network Address Translation) irgendwo auf dem Übertragungsweg verworfen wird. Eine Sitzung, die überhaupt nicht geöffnet werden kann, weist auf ein anderes Problem mit anderen Ursachen hin. In diesem Fall ist der Unterschied zwischen „connection refused“ und „connection timed out“ relevant.
Welche Methode hält einen Befehl nach der Trennung der SSH-Verbindung am Laufen?
Vier Antworten, geordnet nach der Kritikalität des Jobs.
nohupodersetsid: ein einmaliger Vorgang, den Sie jetzt starten und dessen Log Sie anschließend lesen. Die Ausgabe leiten Sie selbst um.disown: der Job, den Sie bereits gestartet und nicht geschützt haben. Damit retten Sie den Prozess. Die Ausgabe lässt sich damit nicht nachträglich wiederherstellen.tmuxoderscreen: Arbeiten, die Sie über mehrere Tage beobachten, unterbrechen und später fortsetzen müssen.systemd-runoder eine echte Unit-Datei: alles, was Ihre Anmeldung überdauern muss, beispielsweise ein sechsstündigerrsyncoder ein Datenbankimport über Nacht.
Die wichtigste Regel lautet: Wenn es problematisch wäre, den Job zu vergessen, gehört er zu systemd und nicht zu tmux. Ein tmux-Fenster ist etwas, an das sich ein Mensch erinnern muss. Eine Unit hat einen Namen, einen Status, ein Log und eine Neustartregel, die die nächste Person ohne zusätzliche Hinweise finden kann.
nohup und setsid: Starten und die Sitzung verlassen
nohup ./import.sh > ~/import.log 2>&1 &
echo $! > ~/import.pidnohup setzt die Behandlung von SIGHUP auf Ignorieren und führt anschließend Ihren Befehl aus. Dadurch erreicht das Hangup-Signal des Kernels den Prozess, ohne eine Wirkung zu haben. Die Umleitung müssen Sie selbst angeben. Wenn die Standardausgabe weiterhin auf das Terminal zeigt, leitet nohup sie automatisch nach nohup.out im aktuellen Verzeichnis um. Falls das nicht möglich ist, verwendet es $HOME/nohup.out und gibt Folgendes aus:
nohup: ignoring input and appending output to 'nohup.out'Diese Datei ist leicht aus den Augen zu verlieren. Geben Sie ihr deshalb selbst einen Namen. $! enthält die PID (Prozess-ID) des letzten Hintergrundprozesses. Wenn Sie sie speichern, können Sie den Prozess nach der nächsten Anmeldung überprüfen.
setsid löst dasselbe Problem von der anderen Seite. Der Befehl wird in einer neuen Sitzung ohne steuerndes Terminal ausgeführt. Es gibt dann kein Terminal, das den Prozess beenden könnte.
setsid --fork ./import.sh > ~/import.log 2>&1Verwenden Sie --fork. Ohne diese Option ruft setsid setsid() direkt auf, sobald der Prozess noch kein Prozessgruppenleiter ist. Das ist in einem Shell-Skript der Fall. Ihr Skript bleibt dann blockiert. Mit --fork verhält sich der Befehl in einem Skript und an der Eingabeaufforderung gleich.
Prüfen Sie, was tatsächlich gestartet wurde:
ps -o pid,ppid,sid,tty,stat,cmd -p "$(cat ~/import.pid)"Ein TTY-Eintrag von ? bedeutet, dass der Prozess kein steuerndes Terminal besitzt. Nichts kann ihn daher beenden. Unter nohup zeigt die Spalte TTY weiterhin einen Wert wie pts/0, solange Sie verbunden bleiben. Nach dem Zerstören des PTY wird dort ? angezeigt. Beide Ergebnisse sind korrekt. Der Prozess wurde nicht beendet.
disown: Einen bereits gestarteten Job retten
Sie haben einen zweistündigen Job im Vordergrund gestartet und sich dann an dieses Problem erinnert. Beenden Sie ihn nicht, um ihn anschließend erneut zu starten.
# press Ctrl-Z to suspend the job first
bg
jobs -l
disown -h %1Ctrl-Z hält den Job an, bg setzt ihn im Hintergrund fort, und jobs -l gibt seine Jobnummer neben seiner PID aus. disown -h %1 markiert diesen Job, damit bash ihm SIGHUP nicht sendet. Das einfache disown %1 entfernt den Job vollständig aus der Jobtabelle von bash. Beim Hangup hat das denselben Effekt. jobs führt den Job dann jedoch nicht mehr auf.
disown kann die Ausgabe nicht umleiten. Der Prozess verwendet das pty weiterhin als Standardausgabe. Wenn das pty verschwindet, liefert der nächste Schreibvorgang EIO zurück. Deshalb rettet disown zuverlässig einen stillen Job, beispielsweise eine Kompilierung, die in eine Datei schreibt. Bei einem ausgabeintensiven Job scheitert es dagegen häufig. Der Job läuft entweder ohne Ausgabemöglichkeit weiter oder beendet sich bei der nächsten Ausgabezeile.
Für die Dateideskriptoren gibt es ein Rettungswerkzeug. reptyr verschiebt einen laufenden Prozess auf Ihr aktuelles Terminal. Installieren Sie es mit sudo apt install -y reptyr und führen Sie anschließend reptyr <pid> in einem tmux-Fenster aus. Es arbeitet über ptrace. Ubuntu liefert kernel.yama.ptrace_scope = 1 mit, das die Ablaufverfolgung auf Ihre eigenen Nachkommen beschränkt. Für einen geerbten Prozess benötigen Sie daher sudo reptyr <pid>. Verwenden Sie es nur als Notfallwerkzeug. Bauen Sie keinen regulären Ablauf darauf auf.
tmux: Arbeit, die Sie überwachen und später fortsetzen müssen
tmux (Terminal-Multiplexer) löst das Problem an einer anderen Stelle. Statt Ihren Prozess vor dem pty zu schützen, stellt tmux ihm ein pty bereit, das nicht zu Ihrer SSH-Sitzung gehört. Der tmux-Server läuft außerhalb dieser Sitzung und verwaltet die Terminals aller darin ausgeführten Prozesse. Ihre SSH-Verbindung ist lediglich ein daran angeschlossenes Anzeigefenster. Wird die Verbindung getrennt, bemerkt der Server dies nicht.
sudo apt update && sudo apt install -y tmux
tmux new -s importStarten Sie den Auftrag in diesem Fenster. Drücken Sie anschließend Ctrl-b und danach d, um die Verbindung zu trennen. Melden Sie sich später erneut an und setzen Sie die Arbeit fort:
tmux ls
tmux attach -t importtmux ls sollte eine Zeile ausgeben, die mit import: 1 windows beginnt. Wenn no server running on /tmp/tmux-1000/default ausgegeben wird, gibt es keine Sitzung, an die Sie sich anhängen können. Entweder wurde sie nie erstellt oder ein Prozess hat den Server beendet.
screen erledigt dieselbe Aufgabe mit einer anderen Tastenkombination. screen -S import erstellt eine Sitzung, und Ctrl-a trennt sie anschließend mit d. screen -ls listet vorhandene Sitzungen auf, und screen -r import stellt eine davon wieder her. Beide Werkzeuge sind hierfür geeignet. Die Tastenkombination zum Trennen wird häufig vergessen.
Ein Multiplexer ist auch der richtige Ort für interaktive Arbeiten, die einen Verbindungsabbruch überstehen müssen. Deshalb ist Claude Code auf einem VPS innerhalb von tmux auszuführen die übliche Einrichtung. Dadurch lässt sich außerdem eine Serversitzung von einem Telefon aus zu steuern in einem Mobilfunknetz verwenden, das sich alle paar Minuten neu verbindet.
systemd-run: Den Auftrag an PID 1 übergeben
Wenn ein Auftrag vollständig unabhängig von Ihnen laufen muss, übergeben Sie ihn an das Init-System.
sudo systemd-run --unit=bigsync --collect /usr/bin/rsync -aH --stats /srv/data/ /mnt/backup/Dadurch wird eine transiente Service-Unit mit dem Namen bigsync.service erstellt. Sie erhält eine eigene cgroup, kein steuerndes Terminal und keine Verbindung zu Ihrer Anmeldung. Der Befehl kehrt sofort zurück und gibt Running as unit: bigsync.service aus. Überwachen Sie den Auftrag mit einem der folgenden Befehle:
systemctl status bigsync
journalctl -u bigsync -f--collect weist systemd an, die Unit nach ihrem Ende zu entfernen, auch wenn sie fehlgeschlagen ist. Ohne diese Option bleibt eine fehlgeschlagene transiente Unit geladen und ihr Name bleibt belegt. Beim nächsten Aufruf schlägt der Start daher mit der Meldung fehl, dass die Unit bereits existiert. Die Ausgabe wird mit Zeitstempeln für jede Zeile in das Journal geschrieben. Journal-Einträge überdauern einen Reboot nur, wenn /var/log/journal existiert. Führen Sie deshalb sudo mkdir -p /var/log/journal aus und starten Sie systemd-journald neu, wenn Sie das benötigen.
Wenn Sie systemd-run als normaler Benutzer ohne sudo aufrufen, fordert polkit eine Autorisierung an und gibt ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units === aus. Verwenden Sie sudo für systemweite Units.
Sie können den Auftrag auch unter Ihrem eigenen User Manager ausführen:
systemd-run --user --unit=bigsync --collect /usr/bin/rsync -aH /srv/data/ /mnt/backup/Dabei gibt es eine wichtige Einschränkung. Ihr benutzerspezifischer Manager user@1000.service wird normalerweise beendet, sobald Ihre letzte Sitzung endet. Dadurch werden auch alle Units dieses Benutzers beendet. Aktivieren Sie daher einmalig das dauerhafte Ausführen:
loginctl enable-linger "$USER"
loginctl show-user "$USER" --property=LingerDer zweite Befehl sollte Linger=yes ausgeben. Bei aktiviertem dauerhaftem Ausführen startet Ihr User Manager beim Booten und bleibt unabhängig davon aktiv, ob Sie angemeldet sind. Ohne diese Einstellung bringt systemd-run --user gegenüber nohup keinen Vorteil.
systemd-run --scope ist etwas anderes. Der Befehl wird im Vordergrund und mit Verbindung zu Ihrem Terminal ausgeführt. Allein hilft er daher in diesem Fall nicht weiter.
Für Aufträge, die Sie mehr als einmal ausführen, sollten Sie die Unit als Datei anlegen, statt jedes Mal eine transiente Unit einzugeben.
Eine dauerhafte Unit für einen Auftrag, den Sie erneut ausführen
User=deploy ist der Benutzer, unter dem der Auftrag ausgeführt wird. Tragen Sie dort Ihren eigenen Anmeldenamen ein oder erstellen Sie einen eigenen Service-Benutzer für den Auftrag:
sudo useradd --system --shell /usr/sbin/nologin deploy[Unit]
Description=Nightly data sync
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
User=deploy
WorkingDirectory=/srv/data
ExecStart=/usr/local/bin/nightly-sync.shSpeichern Sie die Datei unter /etc/systemd/system/nightly-sync.service, führen Sie sudo systemctl daemon-reload aus und starten Sie die Unit anschließend mit sudo systemctl start nightly-sync. Lesen Sie sie mit journalctl -u nightly-sync wieder ein. Erstellen Sie eine passende Datei .timer, wenn der Auftrag nach einem Zeitplan statt manuell ausgeführt werden soll.
Eine systemd-Service-Unit und ihren Timer erstellen behandelt das Dateiformat und die Syntax für Zeitpläne vollständig.
Wohin die Ausgabe geht und warum sie verschwindet
Die Reihenfolge der Umleitungen ist wichtig. > file 2>&1 leitet die Standardausgabe in die Datei um und leitet anschließend die Standardfehlerausgabe an dieselbe Stelle. 2>&1 > file macht es umgekehrt: Die Standardfehlerausgabe bleibt am Terminal, und genau dieses Terminal wird gleich verschwinden. Bash akzeptiert außerdem &> file für beide Datenströme gleichzeitig.
Die zweite Überraschung ist das Puffern. Wenn die Standardausgabe ein Terminal ist, leert die C-Bibliothek den Puffer nach jeder Zeile. Wenn die Standardausgabe eine Datei ist, wechselt sie zu einem Blockpuffer von einigen Kilobyte. Dadurch zeigt tail -f ~/import.log minutenlang nichts an, und der Prozess wirkt beendet. Erzwingen Sie mit stdbuf -oL ./import.sh > ~/import.log 2>&1 die zeilenweise Pufferung. Das funktioniert bei Programmen, die über die Standarddatenströme der C-Bibliothek schreiben und ihre eigene Pufferung nicht ändern, aber nicht bei Programmen wie dd oder tee. Verwenden Sie andernfalls die programmspezifische Option, beispielsweise python3 -u oder grep --line-buffered.
Vermeiden Sie dieses Muster:
nohup ./import.sh 2>&1 | tee ~/import.log &nohup schützt import.sh und nichts anderes. tee ist ein separater Prozess in derselben Pipeline und wird bei einem Hangup weiterhin beendet. import.sh schreibt dann in eine Pipe ohne Leser, empfängt SIGPIPE und wird beendet. Stellen Sie die gesamte Pipeline in setsid bash -c '...', oder schreiben Sie direkt in die Datei und führen Sie bei der erneuten Verbindung tail -f darauf aus.
Ein weiteres Detail gilt speziell für rsync. --info=progress2 schreibt einen Datenstrom aus Wagenrückläufen, der auf einem Terminal korrekt aussieht, in einer Logdatei jedoch zu einer einzigen sehr langen Zeile wird. Das Journal trennt Datensätze nur an Zeilenumbrüchen. Deshalb kommt dieselbe Ausgabe dort als Folge von 48K-Fragmenten an (der Standardwert von LineMax=). Für einen unbeaufsichtigten Lauf lassen Sie es weg und verwenden stattdessen --stats.
Warum ein Job in Ihrer Shell funktioniert, aber unter systemd oder cron fehlschlägt
Ihre SSH-Login-Shell liest /etc/profile und anschließend die erste vorhandene Datei aus ~/.bash_profile, ~/.bash_login und ~/.profile. Eine interaktive Nicht-Login-Shell liest ~/.bashrc. Daher enthält Ihre Shell PATH, die Shims Ihres Versionsmanagers und Ihre exportierten Variablen. Eine systemd-Unit liest keine dieser Dateien. cron liest ebenfalls keine davon: Unter Debian und Ubuntu führt cron Jobs mit SHELL=/bin/sh und PATH=/usr/bin:/bin aus.
Unter systemd lautet das Symptom systemctl status mit (code=exited, status=203/EXEC). Das bedeutet, dass systemd die Datei überhaupt nicht ausführen konnte, weil der Pfad falsch war oder die Datei nicht als ausführbar markiert ist. Unter cron lautet es meist command not found. Die Meldung wird per lokaler E-Mail zugestellt oder überhaupt nicht, wenn kein E-Mail-System installiert ist.
Ermitteln Sie die Umgebung, bevor Sie eine Stunde lang vermuten:
sudo systemd-run --collect --wait --unit=envtest /usr/bin/env
journalctl -u envtest --no-pagerDamit wird die genaue Umgebung ausgegeben, in der Ihr Job ausgeführt wird. Beheben Sie anschließend die Abweichung. Verwenden Sie für eigene Dateien absolute Pfade, weil systemd einen nicht qualifizierten rsync anhand einer festen Systempfadliste auflöst und niemals anhand von PATH Ihrer Shell. Übergeben Sie die benötigten Variablen mit -p Environment="KEY=value" in der Befehlszeile oder mit EnvironmentFile=/etc/default/myjob in einer Unit-Datei. Wenn ein Job tatsächlich Ihre Login-Umgebung benötigt, führen Sie ihn mit /bin/bash -lc 'my-command' aus. Akzeptieren Sie dabei, dass der Job nun von Ihren Dotfiles abhängt.
Was einen getrennten Job weiterhin beendet
- Ein Reboot. tmux bleibt dabei nicht erhalten, weil der Server ein gewöhnlicher Prozess ist und die Sitzungen seinen In-Memory-Zustand bilden. Kernel-Updates erfordern Reboots. Ein Job, den Sie nicht problemlos neu starten können, gehört daher in eine Unit, die Sie
systemctl enablekönnen. - Der Out-of-Memory-Killer.
dmesg -T | grep -i 'killed process'zeigt ihn einschließlich des Namens des ausgewählten Prozesses an. Ein großer Import auf einem kleinen VPS ist ein häufiges Ziel. - Die Bereinigung durch logind. Wenn
/etc/systemd/logind.confKillUserProcesses=yessetzt, werden die Prozesse im Scope einer Anmeldesitzung beendet, sobald Sie sich von dieser Sitzung abmelden. Dazu gehört auch ein daraus gestarteter tmux-Server. Prüfen Sie die aktuelle Einstellung mitloginctl show-session --property=KillUserProcesses. Lingering allein reicht nicht aus. Starten Sie tmux außerhalb des Sitzungsscope mitsystemd-run --scope --user tmux new -s importund lassen Sie Lingering mitloginctl enable-linger "$USER"aktiviert, oder bitten Sie einen Administrator, Ihren Benutzer zuKillExcludeUsers=hinzuzufügen. - Ein vollständig belegtes Dateisystem. Der Job wird beendet, weil das umgeleitete Log das Dateisystem gefüllt hat, nicht weil Sie sich abgemeldet haben. Führen Sie
df -haus, bevor Sie das Signal verantwortlich machen.
Einen Job über SSH starten, ohne verbunden zu bleiben
ssh vps 'sudo systemd-run --unit=import --collect /usr/local/bin/import.sh'systemd-run kehrt zurück, sobald die Unit gestartet wurde. Dadurch kehrt auch der Befehl ssh zurück, und der Job ist nicht mit der Sitzung verbunden, die ihn gestartet hat. Das ist die saubere Variante.
Die Variante mit nohup erfordert mehr Sorgfalt:
ssh vps 'nohup ./import.sh > ~/import.log 2>&1 < /dev/null &'Ohne die Umleitungen scheint der Befehl zu hängen. sshd hält den Kanal offen, solange noch ein Prozess die Standardausgabe oder den Standardfehlerausgabekanal des Remote-Befehls geöffnet hat. Ein im Hintergrund gestarteter Job übernimmt beide Dateideskriptoren. nohup allein behebt das Problem nicht, weil nohup die Ausgabe nur dann umleitet, wenn sie an ein Terminal geht. In diesem Fall ist sie jedoch eine Pipe zurück zu Ihrem Client. Mit < /dev/null wird auch die Eingabeseite geschlossen. ssh -n erfüllt dieselbe Aufgabe auf der Client-Seite.
FAQ
Warum wird mein Befehl beendet, wenn die SSH-Verbindung abbricht?
Das pty (Pseudo-Terminal), das Ihre Sitzung verwendet hat, wird zerstört. Der Kernel sendet dann SIGHUP an die Vordergrund-Prozessgruppe dieses Terminals. Die Standardaktion für SIGHUP besteht darin, den Prozess zu beenden. Auch Hintergrundaufträge werden beendet, weil bash SIGHUP vor dem Beenden an jeden Auftrag in seiner Tabelle erneut sendet. Ein Befehl, der SIGHUP ignoriert, beispielsweise ein mit nohup gestarteter Befehl, oder ein Prozess, der seine Sitzung nie gemeinsam genutzt hat, etwa eine systemd-Unit, bleibt davon unberührt.
Ist tmux oder systemd-run für einen sechs Stunden dauernden rsync besser?
systemd-run. Eine tmux-Sitzung hängt von einem von Ihnen gestarteten Serverprozess ab. Sie endet daher beim nächsten Reboot. Außerdem ist sie für Personen unsichtbar, die nicht wissen, dass sie tmux ls ausführen müssen. Wenn Sie sudo systemd-run --unit=bigsync --collect /usr/bin/rsync -aH --stats /srv/data/ /mnt/backup/ ausführen, erhalten Sie systemctl status bigsync für den Status und journalctl -u bigsync für die Ausgabe. Beides kann der nächste Administrator ohne zusätzliche Hinweise finden. Verwenden Sie tmux für Arbeiten, bei denen Sie den Bildschirm beobachten und Eingaben machen müssen.
Wie kann ich die Ausgabe eines Auftrags anzeigen, dessen Umleitung ich vergessen habe?
Normalerweise gar nicht, weil diese Ausgabe an ein Terminal ging, das nicht mehr existiert. Solange der Prozess noch läuft, können Sie seine geöffneten Dateien mit sudo ls -l /proc/<pid>/fd untersuchen oder seine Systemaufrufe mit sudo strace -p <pid> überwachen. Text, der bereits geschrieben wurde, ist jedoch verloren. Mit reptyr <pid> können Sie den Prozess an ein neues Terminal verschieben. Unter Ubuntu bedeutet kernel.yama.ptrace_scope = 1, dass Sie für einen Prozess, der nicht Ihr eigener Kindprozess ist, sudo benötigen. Die Vorgehensweise, die all das vermeidet, besteht darin, die Ausgabe von Anfang an in eine Datei umzuleiten und diese Datei mit tail -f zu überwachen.
Bleibt eine getrennte tmux-Sitzung nach einem Reboot erhalten?
Nein. Der tmux-Server ist ein gewöhnlicher Prozess, und die Sitzungen sind sein Zustand im Arbeitsspeicher. Ein Reboot beendet daher beides. Der Server wird außerdem beendet, wenn /etc/systemd/logind.conf KillUserProcesses=yes setzt und Sie sich aus der Sitzung abmelden, in der er gestartet wurde. Lingering allein verhindert das nicht. Starten Sie tmux mit systemd-run --scope --user tmux new -s import außerhalb des Sitzungsbereichs, während Lingering aktiviert ist, oder führen Sie Ihren Benutzer in KillExcludeUsers= auf. Für Arbeiten, die nach einem Reboot automatisch wieder aufgenommen werden müssen, erstellen Sie eine systemd-Unit und systemctl enable sie.
Warum läuft mein Skript in der Shell, schlägt aber als systemd-Unit fehl?
Eine Unit liest weder /etc/profile noch ~/.bashrc. Daher enthält sie weder Ihre Ergänzungen in PATH noch Ihre exportierten Variablen. Wenn systemctl status (code=exited, status=203/EXEC) anzeigt, konnte systemd die Datei überhaupt nicht ausführen. Verwenden Sie daher einen absoluten Pfad und prüfen Sie das Ausführungsrecht. Führen Sie sudo systemd-run --collect --wait --unit=envtest /usr/bin/env aus und lesen Sie die Ausgabe mit journalctl -u envtest erneut ein. Damit erhalten Sie exakt die Umgebung, die Ihr Auftrag erhält. Stellen Sie fehlende Werte mit Environment= oder EnvironmentFile= bereit.