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


313

Manchmal möchte ich einen Prozess starten und ihn vergessen. Wenn ich es von der Kommandozeile aus starte, so:

redshift

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


4
Keine Standardinstallation auf allen Distributionen, aber der Bildschirm ist dein Freund: en.wikipedia.org/wiki/GNU_Screen
Zayne S Halsall

Für alle, die mit demselben Problem konfrontiert sind: Denken Sie daran, dass Sie auch dann blind tippen und drücken , wenn Sie auf dem Bildschirm einen Bildlauf mit Ausgaben durchführen und nicht sehen können, was yourExecutable &auf dem Bildschirm angezeigt wird, auch wenn Sie weiterhin tippen und die Ausgaben auf dem Bildschirm angezeigt werden Sie tippen. Der Prozess wird abgelehnt und Sie können das Terminal schließen, ohne dass der Prozess zum Erliegen kommt. Ctrl+Cdisown;Enter
Nav

Sie können Screen-Multiplexer wie TMUX verwenden . Es ist über Apt-Get auf Ubuntu-Maschinen erhältlich
Himanshu

Antworten:


311

Eine der folgenden 2 sollte funktionieren:

$ nohup redshift &

oder

$ redshift &
$ disown

Weitere Informationen zur Funktionsweise finden Sie im Folgenden:


5
Die zweite ( redshift & disown) funktionierte für mich unter Ubuntu 10.10. Es scheint gut zu funktionieren, wenn man alles auf eine Linie bringt. Gibt es einen Grund, warum ich das nicht tun sollte?
Matthew

4
@Matthew Der erste sollte auch gut funktionieren, der Hintergrund ist einfach nicht so wie der zweite (Sie möchten möglicherweise, dass nohup redshift &es auch Hintergrund ist). Und die zweite Zeile in eine Zeile zu setzen ist in Ordnung, obwohl Sie normalerweise mit ;( redshift &; disown) trennen
Michael Mrozek

10
@Michael: Beide ;und &sind Befehlstrennzeichen und haben die gleiche Priorität. Der einzige Unterschied besteht in der synchronen bzw. asynchronen Ausführung. Es ist nicht erforderlich, &;nur zu verwenden &(es funktioniert, aber es ist ein bisschen redundant).
Chris Johnsen

4
Gute Antwort, man könnte hinzufügen, dass es eine gute Idee wäre, stdout und stderr umzuleiten, damit das Terminal nicht mit Debug-Ausgaben überflutet wird
Kim,

12
Außerdem redshift &!wird die Rotverschiebung sofort ausgeblendet.

143

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

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

3
wie kann ich nach disown den stdout des laufenden prozesses wieder auslesen?
Necktwi


1
Das hat aus irgendeinem Grund nicht funktioniert (Centos)
Ian

Wie kann ich den Vorgang nach diesem Vorgang abbrechen?
Palak Darji

2
@necktwi disowntrennt weder stdout noch stderr. Dies nohupgilt jedoch ebenso wie für >/dev/null(Standardausgang trennen) 2>/dev/null(Standardfehler trennen). Es ( disown) trennt die Jobsteuerung.
Strg-Alt-Delor

45

Eine gute Antwort wurde bereits von @StevenD gepostet, aber ich denke, das könnte es ein bisschen klarer machen.

Der Grund dafür, dass der Prozess beim Beenden des Terminals abgebrochen wird, ist, dass der Prozess, den Sie starten, ein untergeordneter Prozess des Terminals ist. Sobald Sie das Terminal schließen, werden auch diese untergeordneten Prozesse beendet. Sie können den Prozessbaum mit sehen pstree, zum Beispiel wenn Sie kate &in Konsole laufen:

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

Verwenden Sie mit dem Befehl Folgendes , um den kateProzess von der Verbindung zu trennen, konsolewenn Sie ihn beenden :konsolenohup

nohup kate &

Nach dem Schließen konsole, pstreewird wie folgt aussehen:

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

und katewird überleben. :)

Eine Alternative ist die Verwendung von screen/ tmux/ byobu, die die Schale am Laufen halten wird, unabhängig von dem Terminal.


Ich hatte Probleme mit den verweigerten Methoden. Das funktioniert momentan bei mir, also upvoting. Ich mag das auch, weil ich -f nohup.out Schwanz sehen kann, was passiert, aber keine Sorge, dass meine Sitzung fehlschlägt
Ian

27

Sie können den Vorgang 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


1
Was sehen Sie als die Vorteile von setsid gegenüber nohup?
Itsbruce

1
1) Es wird keine störende Meldung über ausgegeben nohup.out. 2) Sie verbleibt nicht in der Jobliste Ihrer Shell, sodass die Ausgabe von nicht überladen wird jobs.
Mikel

Dies ist die einzige Lösung, die mit Skripten funktioniert, die in lxterminal ausgeführt werden, pcmanfm starten und beenden (mit setsid kann das Terminal geschlossen werden, während pcmanfm ausgeführt wird). Ich danke dir sehr!
Desgua

9

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

Sie könnten darüber nachdenken, es mit zu beginnen . Screen kann auf nahezu allen Linux- und Unix-Derivaten installiert werden. Wenn Sie + und (in Kleinbuchstaben) drücken, wird eine zweite Sitzung gestartet. Auf diese Weise können Sie zwischen der ersten Sitzung durch Drücken von + und oder der neueren Sitzung durch Drücken von + und hin- und herschalten . Sie können bis zu zehn Sitzungen in einem Terminal durchführen. Früher habe ich eine Sitzung bei der Arbeit begonnen, bin nach Hause gegangen, habe mich in meine Arbeitsmaschine eingemischt und habe dann aufgerufen . Dadurch werden Sie wieder mit dieser Remote-Sitzung verbunden.screen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name


screen -d -m commandIch starte es in einem bereits abgetrennten Bildschirm: ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x .... und du bist dabei.
Dr. Alexander

7

Die einzige Möglichkeit, dies alles in der Shell zu tun, besteht darin, stdin zu schließen und den Befehl im Hintergrund auszuführen:

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.


Ich habe es in Ubuntu versucht. Das Tötungsterminal schloss auch den eingeleiteten Prozess ab. Irgendeine Idee, warum dies der Fall sein könnte?
Ashok Koyi

7

Ich habe ein Skript für:

  • Führen Sie im Hintergrund beliebige Befehle aus

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

  • Unterdrücke ihre Ausgabe

  • Behandelt den Beendigungsstatus

Ich benutze es vor allem für die gedit, evince, inkscapeetc , die alle viel lästige Terminal Ausgang. Wenn der Befehl TIMEOUTvorzeitig beendet wird , wird der Beendigungsstatus 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

6

Ich bevorzuge:

(Anwendungsname &)

zum Beispiel: linux@linux-desktop:~$ (chromium-browser &)

Achten Sie darauf, Klammern zu verwenden, wenn Sie den Befehl eingeben!


1
Das Schließen des Terminals wird den Prozess
beenden

Wahrscheinlich haben Sie einen Eingabeaufforderungsbefehl, den ich in meiner Antwort ohne Klammern verwendet habe. Wenn Sie das Terminal schließen, wird der Prozess abgebrochen, andernfalls wird er NICHT ausgeführt. Ich habe die obige Lösung bereits bearbeitet, um dies zu verdeutlichen.
Dago

Arbeit für mich, TNX
Noadev

Ich frage mich, warum dies nicht mehr Stimmen bekam. nohupverhindert jede tty-Ausgabe und ich wollte eigentlich nur die Ausgabe in eine Datei umleiten und es hat verhindert, dass dies für mich die bessere Lösung ist.
Redanimalwar

4

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

3

Wohl ähnlich der Antwort von apolinsky verwende ich eine Variante von screen. Der Vanille-Befehl ist wie folgt

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

Die Sitzung kann mit getrennt Ctrl ACtrl Dund im einfachen Fall mit wieder verbunden werden screen -r. Ich habe dies in ein Skript mit dem Namen eingewickelt session, das in meinem PATHfür den bequemen Zugriff bereitsteht:

#!/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 "$@; 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 vorher wissen, dass Sie ein Programm trennen möchten. Es ist nicht vorgesehen, dass ein bereits ausgeführtes Programm getrennt wird.


2

Ähnlich wie bei anderen Antworten, die zuvor gepostet wurden, 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 . Die zu treffenden Schritte sind:

  1. Unterbrechen Sie den Vorgang
  2. Setzen Sie den Vorgang im Hintergrund fort
  3. Prozess ablehnen
  4. Starten Sie eine Bildschirmsitzung
  5. Finden Sie die PID des Prozesses
  6. Verwenden Sie Reptyr, um den Prozess zu übernehmen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.