it-swarm.com.de

Wie kann ich einen Befehl ausführen, der das Schließen des Terminals überlebt?

Manchmal möchte ich einen Prozess starten und ihn vergessen. Wenn ich es über die Befehlszeile starte, so:

redshift

Ich kann das Terminal nicht schließen, sonst wird der Prozess abgebrochen. Kann ich einen Befehl so ausführen, dass ich das Terminal schließen kann, ohne den Prozess abzubrechen?

339
Matthew

Eine der folgenden 2 sollte funktionieren:

$ Nohup redshift &

oder

$ redshift &
$ disown

Weitere Informationen zur Funktionsweise finden Sie im Folgenden:

342
Steven D

Wenn Ihr Programm läuft bereits ist, können Sie es mit Ctrl-Z Anhalten, es mit bg in den Hintergrund ziehen und dann disown wie folgt:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
147
Stefan

Gute Antwort wird bereits von @StevenD gepostet, aber ich denke, dies könnte es ein bisschen klarer machen.

Der Grund dafür, dass der Prozess beim Beenden des Terminals abgebrochen wird, ist, dass der von Ihnen gestartete Prozess ein untergeordneter Prozess des Terminals ist. Sobald Sie das Terminal schließen, werden auch diese untergeordneten Prozesse beendet. Sie können den Prozessbaum mit pstree sehen, beispielsweise wenn Sie kate & In Konsole ausführen:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

Verwenden Sie kate mit dem folgenden Befehl, um den Prozess konsole von konsole zu trennen, wenn Sie Nohup beenden:

Nohup kate &

Nach dem Schließen von konsole sieht pstree folgendermaßen aus:

init-+
     |-kate---2*[{kate}]

und kate wird überleben. :) :)

Eine Alternative ist die Verwendung von screen/tmux/byobu, wodurch die Shell unabhängig vom Terminal ausgeführt wird.

50
gertvdijk

Sie können den Prozess wie folgt im Terminal ausführen

setsid process

Dadurch wird das Programm in einer neuen Sitzung ausgeführt. Wie erklärt http://hanoo.org/index.php?article=run-program-in-new-session-linux

31
hanoo

Obwohl alle Vorschläge gut funktionieren, habe ich festgestellt, dass meine Alternative darin besteht, screen zu verwenden, ein Programm, das ein virtuelles Terminal auf Ihrem Bildschirm einrichtet.

Sie können es mit screen -S session_name Starten. Screen kann auf praktisch allen Linux- und Unix-Derivaten installiert werden. Schlagen Ctrl+A und (Kleinbuchstaben) C startet eine zweite Sitzung. Auf diese Weise können Sie zwischen den ersten Sitzungen durch Drücken hin und her wechseln Ctrl+A und  oder die neuere Sitzung durch Schlagen Ctrl+A und 1. Sie können bis zu zehn Sitzungen in einem Terminal abhalten. Ich habe eine Sitzung bei der Arbeit gestartet, bin nach Hause gegangen, habe in meine Arbeitsmaschine ssh und dann screen -d -R session_name Aufgerufen. Dadurch werden Sie wieder mit dieser Remote-Sitzung verbunden.

10
apolinsky

Ich bevorzuge:

(Name der Anwendung und)

zum Beispiel: [email protected]:~$ (chromium-browser &)

Stellen Sie sicher, dass Sie Klammern verwenden, wenn Sie den Befehl eingeben!

8
daGo

Ich habe ein Skript für:

  • Führen Sie beliebige Befehle im Hintergrund aus

  • Verhindern Sie, dass sie mit dem Terminalfenster getötet werden

  • Unterdrücken Sie ihre Ausgabe

  • Behandelt den Exit-Status

Ich benutze es hauptsächlich für gedit, evince, inkscape usw., die alle viele nervige Terminalausgaben haben. Wenn der Befehl vor TIMEOUT beendet wird, wird der Exit-Status von Nohup anstelle von Null zurückgegeben.

#!/bin/bash

TIMEOUT=0.1

#use Nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send Nohup's output to /dev/null, supressing Nohup.out
#run Nohup in the background so this script doesn't block
Nohup "${@}" >/dev/null 2>&1 &
Nohup_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $Nohup_PID
Nohup_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $Nohup_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS

beispiele ...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
7
jozxyqk

Die einzige Möglichkeit, dies nur über die Shell zu tun, besteht darin, stdin zu schließen und den Befehl als Hintergrund zu verwenden:

command <&- & 

Dann wird es nicht beendet, wenn Sie die Shell beenden. Das Umleiten von stdout ist eine nette optionale Sache.

Nachteil ist, dass Sie dies nicht nachträglich tun können.

7
w00t

Sie können einen Prozess (PID) so einstellen, dass beim Abmelden und Schließen der Terminalsitzung kein HUP-Signal empfangen wird. Verwenden Sie den folgenden Befehl:

Nohup -p PID
4
tony

Vermutlich ähnlich dem Antwort von apolinsky verwende ich eine Variante für screen. Der Vanilla-Befehl ist so

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

Die Sitzung kann mit getrennt werden Ctrl ACtrl D und im einfachen Fall wieder mit screen -r verbunden. Ich habe dies in ein Skript namens session eingewickelt, das in meinem PATH lebt und für den bequemen Zugriff bereit ist:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "[email protected]; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Dies funktioniert nur, wenn Sie im Voraus wissen, dass Sie ein Programm trennen möchten. Es ist nicht vorgesehen, dass ein bereits laufendes Programm getrennt wird.

3
roaima

Ähnlich wie bei anderen zuvor veröffentlichten Antworten kann man dank reptyr einen laufenden Prozess übertragen, um "screen" nachträglich zu verwenden, und dann das Terminal schließen. Die Schritte werden in diesem Beitrag beschrieben. Folgende Schritte sind zu unternehmen:

  1. Unterbrechen Sie den Vorgang
  2. Setzen Sie den Vorgang im Hintergrund fort
  3. Den Prozess ablehnen
  4. Starten Sie eine Bildschirmsitzung
  5. Finden Sie die PID des Prozesses
  6. Verwenden Sie Reptyr, um den Prozess zu übernehmen
2
user308879