Frage Wie kann ich einen Prozess vollständig vom Terminal trennen?


Ich benutze Tilda (Drop-Down-Terminal) auf Ubuntu als mein "Kommandozentrale" - so wie andere GNOME Do, Quicksilver oder Launchy verwenden.

Ich habe jedoch Probleme damit, einen Prozess (z. B. Firefox) vollständig von dem Terminal zu trennen, von dem aus er gestartet wurde - also einen solchen (Nicht-) Kind-Prozess zu verhindern

  • wird beendet, wenn das sendende Terminal geschlossen wird
  • "verschmutzt" das sendende Endgerät via STDOUT / STDERR

Um beispielsweise Vim in einem "richtigen" Terminalfenster zu starten, habe ich ein einfaches Skript wie das folgende versucht:

exec gnome-terminal -e "vim $@" &> /dev/null &

Dies führt jedoch immer noch zu Verschmutzung (auch das Übergeben eines Dateinamens scheint nicht zu funktionieren).


274
2018-03-23 11:59


Ursprung


Auch das ist eine gute Frage. Ich denke, es ist fair, Bash eine Programmiersprache zu nennen - obwohl der Umfang dieser Frage wahrscheinlich eher auf der Seite des Systemadministrators liegt ...
Dies ist ein Duplikat dieser Frage stackoverflow.com/questions/285015/... - Dana the Sane
dup von:superuser.com/questions/177218/ ... - behrooz
Ihr Anwendungsfall beschreibt keine vollständige Ablösung an sich. - jiggunjer


Antworten:


Als erstes; Sobald Sie einen Prozess gestartet haben, können Sie ihn im Hintergrund anzeigen, indem Sie ihn zuerst stoppen (hit) Strg-Z) und dann tippen bg um es im Hintergrund fortsetzen zu lassen. Es ist jetzt ein "Job" und seine stdout/stderr/stdin sind immer noch mit Ihrem Terminal verbunden.

Sie können einen Prozess sofort als Hintergrund starten, indem Sie an seinem Ende ein "&" anhängen:

firefox &

Um es im Hintergrund zum Schweigen zu bringen, benutze dies:

firefox </dev/null &>/dev/null &

Einige zusätzliche Informationen:

nohup ist ein Programm, das Sie verwenden können um deine Anwendung zu starten so dass sein stdout / stderr stattdessen an eine Datei gesendet werden kann und dass das Schließen des übergeordneten Skripts das Kind nicht SIGHUP wird. Sie müssen jedoch vorausschauend darauf geachtet haben, dass Sie es verwendet haben, bevor Sie die Anwendung gestartet haben. Wegen des Weges nohup funktioniert, du kannst nicht einfach wenden Sie es auf einen laufenden Prozess an.

disown ist ein Bash-Built-In, das einen Shell-Job aus der Job-Liste der Shell entfernt. Was das bedeutet, ist, dass Sie nicht verwenden können fg, bg darauf, aber noch wichtiger, wenn Sie Ihre Shell schließen, wird es nicht hängen oder senden SIGHUP zu diesem Kind mehr. nicht wie nohup, disown wird eingesetzt nach Der Prozess wurde gestartet und im Hintergrund ausgeführt.

Was du kippen do, ändert den stdout / stderr / stdin eines Prozesses, nachdem er gestartet wurde. Zumindest nicht aus der Schale. Wenn Sie Ihren Prozess starten und ihm mitteilen, dass es sich bei der Standardausgabe um Ihr Terminal handelt (was Sie standardmäßig tun), wird dieser Prozess für die Ausgabe an Ihr Terminal konfiguriert. Ihre Shell hat nichts mit dem FD-Setup der Prozesse zu tun, das ist nur etwas, was der Prozess selbst verwaltet. Der Prozess selbst kann entscheiden, ob er sein stdout / stderr / stdin schließt oder nicht, aber Sie können Ihre Shell nicht dazu zwingen, dies zu tun.

Um die Ausgabe eines Hintergrundprozesses zu verwalten, gibt es viele Optionen von Skripten, wobei "Nohup" wahrscheinlich der erste ist, der in den Sinn kommt. Aber für interaktive Prozesse fängt man an, aber vergisst zu schweigen (firefox < /dev/null &>/dev/null &) Du kannst nicht viel tun, wirklich.

Ich empfehle dir, GNU zu bekommen screen. Mit dem Bildschirm können Sie einfach Ihre laufende Shell schließen, wenn die Ausgabe des Prozesses lästig wird und eine neue öffnen (^Ac).


Oh, und übrigens, verwende nicht "$@"Wo du es benutzt.

$@meint, $1, $2, $3 ..., die dein Kommando in Folgendes verwandeln:

gnome-terminal -e "vim $1" "$2" "$3" ...

Das ist wahrscheinlich nicht das, was du willst, weil ... nur nötig ist ein Streit. Benutzen $1 um zu zeigen, dass Ihr Skript nur mit einem Argument umgehen kann.

Es ist wirklich schwierig, mehrere Argumente in dem von Ihnen vorgegebenen Szenario (mit dem gnome-terminal -e) weil -e nimmt nur ein Argument, das eine Shell-Befehlszeichenfolge ist. Sie müssten Ihre Argumente in einen kodieren. Die beste und robusteste, aber eher Clodgy, ist so:

gnome-terminal -e "vim $(printf "%q " "$@")"

308
2018-03-23 13:18



Vielen Dank dafür! Leider kann ich nur eine Antwort akzeptieren. Ich endete mit "nohup $ @ &> / dev / null &" und "alias wvim = 'launch.sh gnome-terminal -x vim'"
Was für eine fantastisch detaillierte und informative Antwort. +1 - Teekin
@ Hi-Angel, wenn Sie eine interaktive Bash-Shell schließen, schlägt bash alle aktiven Jobs. Wenn Sie einen Prozess bearbeiten, ist es immer noch ein Job, sei es ein Hintergrund. Um es als Job zu entfernen, verwenden Sie disown, dann wird der Prozess weiterleben, nachdem du die Shell geschlossen hast, da Bash es nicht mehr HUPEN wird. - lhunath
Wird nicht verwenden $* Anstatt von $@ das Problem der einzelnen Strings schon beheben? - sjas
Was Sie nicht tun können, ist das stdout / stderr / stdin eines Prozesses zu ändern, nachdem Sie es gestartet haben. - Nicht genau richtig. Benutzen reptyr dafür. - Stefan Seidel


nohup cmd &

nohup löst den Prozess komplett ab (dämonisiert ihn)


190
2018-03-23 12:17



Obwohl prägnant wertvoll ist, ist die Vollständigkeit wertvoller. Obwohl Nohup ein GNU-Coreutil ist, wäre hier eine Bash-Only-Antwort (oder eine Anmerkung, dass es keine gibt) angebracht. Gute Antwort trotzdem. - Limited Atonement
nohup ignoriert einfach die SIGHUP Signal. Es führt den Prozess normal aus. Keine Dämonisierung - nemo
@nemo Was bedeutet, dass der Prozess nicht losgelöst ist, sondern sich lösen würde (und ein Kind von init) wenn die Schale austritt ... oder? - Noldorin
@Noldorin Ja. Das Ignorieren von SIGHUP, das gesendet wird, wenn die Shell beendet wird, wird den untergeordneten Prozess ausführen und in Init verschoben werden. - nemo
@nemo nohup schaltet auch Standard-In / Outs aus. Follow-up mit verleugnen, um vollständig zu lösen. - jiggunjer


Wenn Sie verwenden bash, Versuchen disown [Jobspez]; sehen Bash (1).

Ein anderer Ansatz, den Sie versuchen können, ist at now. Wenn Sie kein Superuser sind, dürfen Sie Ihre Erlaubnis verwenden at kann eingeschränkt sein.


51
2018-03-23 12:05



"disown" scheint kein interner bash-Befehl zu sein (auf meinem Rechner nicht verfügbar, und ich benutze bash). "Nohup", wie Ben meinte, könnte ein viel besserer (und standardmäßiger) Weg sein, dies zu tun.
nie gedacht, "at" zu benutzen, danke für die Idee! - cadrian
at um die Ausführung an jemand anderen zu delegieren, mag ich es! +1 - Ninsuo
Als Bezugspunkt funktioniert das in zsh auch. - Coderer
Ebenfalls, disown scheint nicht den gewünschten Effekt zu haben gnome-terminal-disownEd-Prozesse werden immer noch beendet, wenn das Terminal beendet wird. Ich würde gerne wissen warum / wie. - Kyle Strand


Als ich diese Antworten las, hatte ich den ersten Eindruck, dass ich ausgestellt habe nohup <command> & wäre ausreichend. Ich habe zsh im gnome-terminal gefunden nohup <command> & hat meine Shell nicht daran gehindert, Child-Prozesse beim Beenden zu beenden. Obwohl nohup Dies ist insbesondere bei nicht interaktiven Shells hilfreich, da dieses Verhalten nur dann garantiert wird, wenn der untergeordnete Prozess seinen Handler für die Anwendung nicht zurücksetzt SIGHUP Signal.

In meinem Fall, nohup sollte verhindert haben, dass Aufhängungssignale die Anwendung erreichten, aber die untergeordnete Anwendung (in diesem Fall VMWare Player) wurde zurückgesetzt SIGHUP Handler. Wenn der Terminal-Emulator beendet wird, kann es Ihre Subprozesse daher weiterhin beenden. Dies kann meines Wissens nur dadurch gelöst werden, dass sichergestellt wird, dass der Prozess aus der Jobtabelle der Shell entfernt wird. Ob nohup Wird mit einer eingebauten Shell überschrieben, wie es manchmal der Fall ist, kann dies jedoch ausreichend sein, falls es nicht ...


disown ist eine eingebaute Shell bash, zsh, und ksh93,

<command> &
disown

oder

<command> &; disown

wenn Sie Einzeiler bevorzugen. Dies hat den allgemein wünschenswerten Effekt, den Unterprozess aus der Auftragstabelle zu entfernen. Dadurch können Sie den Terminalemulator beenden, ohne versehentlich den untergeordneten Prozess zu signalisieren. Egal was SIGHUP Handler sieht so aus, das sollte Ihren Kindprozess nicht töten.

Nach der Ablehnung ist der Prozess immer noch ein Kind Ihres Terminalemulators (spielen mit pstree Wenn Sie dies in Aktion sehen möchten, aber nachdem der Terminal-Emulator beendet wurde, sollten Sie ihn dem Init-Prozess beifügen. Mit anderen Worten, alles ist so, wie es sein sollte, und wie Sie es vermutlich wollen.

Was tun, wenn Ihre Shell das nicht unterstützt? disown? Ich würde mich sehr dafür einsetzen, zu einem solchen zu wechseln, aber ohne diese Option haben Sie ein paar Wahlmöglichkeiten.

  1. screen und tmux kann dieses Problem lösen, aber sie sind viel schwerer Gewicht Lösungen, und ich mag es nicht, sie für eine so einfache Aufgabe zu führen. Sie eignen sich viel besser für Situationen, in denen Sie eine tty pflegen möchten, normalerweise auf einem Remote-Computer.
  2. Für viele Benutzer kann es wünschenswert sein zu sehen, ob Ihre Shell eine Fähigkeit wie zsh unterstützt setopt nohup. Dies kann verwendet werden, um dies zu spezifizieren SIGHUPsollte nicht an die Jobs in der Jobtabelle gesendet werden, wenn die Shell beendet wird. Sie können dies entweder direkt vor dem Beenden der Shell anwenden oder es zur Shell-Konfiguration hinzufügen ~/.zshrc wenn du es immer willst.
  3. Suchen Sie nach einer Möglichkeit, die Jobtabelle zu bearbeiten. Ich konnte keinen Weg finden, dies zu tun tcsh oder cshDas ist etwas störend.
  4. Schreibe ein kleines C-Programm zum abzweigen und exec(). Dies ist eine sehr schlechte Lösung, aber die Quelle sollte nur aus ein paar Dutzend Zeilen bestehen. Sie können dann Befehle als Befehlszeilenargumente an das C-Programm übergeben und somit einen prozessspezifischen Eintrag in der Auftragstabelle vermeiden.

34
2018-01-22 17:08





  1. nohup $ BEFEHL &

  2. $ COMMAND & verleugnen

  3. Seid Befehl

Ich benutze sehr lange die Nummer 2, aber Nummer 3 funktioniert genauso gut. Außerdem hat disown eine 'nohup' Flagge von '-h', kann alle Prozesse mit '-a' ablehnen und kann alle laufenden Prozesse mit '-ar' abweisen.

Das Silencing wird durch '$ COMMAND &> / dev / null' erreicht.

Hoffe das hilft!


23
2017-08-25 14:39





Ich denke, Bildschirm könnte Ihr Problem lösen


9
2018-03-25 01:51





In tcsh (und vielleicht auch in anderen Shells) können Sie Klammern verwenden, um den Prozess zu lösen.

Vergleiche das:

> jobs # shows nothing
> firefox &
> jobs
[1]  + Running                       firefox

Zu diesem:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

Dies entfernt Firefox aus der Jobliste, ist aber immer noch an das Terminal gebunden; Wenn Sie sich über 'ssh' an diesem Knoten angemeldet haben, wird der ssh-Prozess immer noch unterbrochen, wenn Sie sich abmelden.


8
2018-03-23 14:55