it-swarm.com.de

Wie trenne ich einen Prozess vollständig vom Terminal?

Ich verwende Tilda (Dropdown-Terminal) unter Ubuntu als "Befehlszentrale" - 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 - d. H. Zu verhindern, dass ein solcher (nicht-) untergeordneter Prozess ausgeführt wird

  • wird beim Schließen des Ursprungs-Terminals beendet
  • "verschmutzt" das Ursprungsendgerät über STDOUT/STDERR

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

exec gnome-terminal -e "vim [email protected]" &> /dev/null &

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

297
AnC

Zuerst; Sobald Sie einen Prozess gestartet haben, können Sie ihn im Hintergrund anzeigen, indem Sie ihn zuerst anhalten (drücken Sie Ctrl-Z) und dann bg eingeben, damit es im Hintergrund fortgesetzt wird. Es ist jetzt ein "Job", und es ist immer noch stdout/stderr/stdin mit Ihrem Terminal verbunden.

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

firefox &

Verwenden Sie diese Option, um es im Hintergrund stumm zu schalten:

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

Einige zusätzliche Informationen:

Nohup ist ein Programm, mit dem Sie m Ihre Anwendung auszuführen verwenden können, sodass das stdout/stderr stattdessen an eine Datei gesendet werden kann und das Schließen des übergeordneten Skripts das untergeordnete Skript nicht SEHT. Sie müssen jedoch die Voraussicht gehabt haben, um es zu verwenden, bevor Sie die Anwendung gestartet haben. Aufgrund der Funktionsweise von Nohup können Sie es nicht einfach auf einen laufenden Prozess anwenden .

disown ist eine integrierte Bash, mit der ein Shell-Job aus der Jobliste der Shell entfernt wird. Dies bedeutet im Grunde genommen, dass Sie fg, bg nicht mehr verwenden können, aber was noch wichtiger ist: Wenn Sie Ihre Shell schließen, hängt sie nicht mehr oder sendet ein SIGHUP an dieses Kind. Im Gegensatz zu Nohup wird disown verwendet nach der Prozess wurde gestartet und im Hintergrund ausgeführt.

Was Sie nicht können , ist die Änderung von stdout/stderr/stdin eines Prozesses, nachdem dieser gestartet wurde. Zumindest nicht von der Shell. Wenn Sie Ihren Prozess starten und ihm mitteilen, dass seine Standardausgabe Ihr Terminal ist (was Sie standardmäßig tun), ist dieser Prozess für die Ausgabe auf Ihrem 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 stdout/stderr/stdin geschlossen werden soll oder nicht, aber Sie können Ihre Shell nicht verwenden, um dies zu erzwingen.

Um die Ausgabe eines Hintergrundprozesses zu verwalten, stehen Ihnen zahlreiche Optionen aus Skripten zur Verfügung, wobei "Nohup" wahrscheinlich als erstes in den Sinn kommt. Aber für interaktive Prozesse, die Sie starten, aber vergessen haben (firefox < /dev/null &>/dev/null &), können Sie nicht wirklich viel tun.

Ich empfehle dir GNU screen. Mit screen können Sie einfach Ihre laufende Shell schließen, wenn die Ausgabe des Prozesses störend wird, und eine neue öffnen (^Ac).


Übrigens, verwenden Sie "[email protected]" nicht dort, wo Sie es verwenden.

[email protected] bedeutet, $1, $2, $3 ..., was Ihren Befehl in Folgendes verwandeln würde:

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

Das ist wahrscheinlich nicht das, was Sie wollen, weil -e nur eins Argument nimmt. Verwenden Sie $1, um zu zeigen, dass Ihr Skript nur ein Argument verarbeiten kann.

In dem von Ihnen angegebenen Szenario (mit dem gnome-terminal -e) ist es wirklich schwierig, mehrere Argumente zum Funktionieren zu bringen, da -e nur ein Argument akzeptiert, nämlich eine Shell-Befehlszeichenfolge. Sie müssten Ihre Argumente zu einem zusammenfassen. Der beste und robusteste, aber ziemlich klobige Weg sieht so aus:

gnome-terminal -e "vim $(printf "%q " "[email protected]")"
335
lhunath
Nohup cmd &

Nohup löscht den Prozess vollständig (daemonisiert ihn)

197
dsm

Wenn Sie bash verwenden, versuchen Sie es mit disown [jobspec]. siehe bash (1) .

Ein anderer Ansatz, den Sie ausprobieren können, ist at now. Wenn Sie kein Superuser sind, ist Ihre Berechtigung zur Verwendung von at möglicherweise eingeschränkt.

59
Randy Proctor

Als ich diese Antworten las, hatte ich den ersten Eindruck, dass die Ausgabe von Nohup <command> & ausreichen würde. Als ich zsh in gnome-terminal ausführte, stellte ich fest, dass Nohup <command> & meine Shell nicht daran hinderte, untergeordnete Prozesse beim Beenden zu beenden. Obwohl Nohup nützlich ist, vor allem mit nicht-interaktiven Shells garantiert es nur dieses Verhalten, wenn das Kind Prozess nicht seine Handler für das SIGHUP Signal nicht zurückgesetzt.

In meinem Fall hätte Nohup verhindern sollen, dass Aufhängesignale die Anwendung erreichen, aber die untergeordnete Anwendung (in diesem Fall VMWare Player) hat ihren Handler für SIGHUP zurückgesetzt. Wenn der Terminalemulator beendet wird, können Ihre Unterprozesse trotzdem abgebrochen werden. Dies kann meines Wissens nur gelöst werden, indem sichergestellt wird, dass der Prozess aus der Auftragstabelle der Shell entfernt wird. Wenn Nohup mit einer eingebauten Shell überschrieben wird, wie dies manchmal der Fall ist, kann dies jedoch ausreichen, falls dies nicht der Fall ist ...


disown ist eine in bash, zsh und ksh93 integrierte Shell.

<command> &
disown

oder

<command> &; disown

wenn Sie Einzeiler bevorzugen. Dies hat den im Allgemeinen wünschenswerten Effekt, dass der Unterprozess aus der Auftragstabelle entfernt wird. Auf diese Weise können Sie den Terminalemulator beenden, ohne den untergeordneten Prozess versehentlich zu signalisieren. Unabhängig davon, wie der Handler SIGHUP aussieht, sollte dies den untergeordneten Prozess nicht beenden.

Nach der Deaktivierung ist der Prozess noch ein untergeordnetes Element Ihres Terminal-Emulators (spielen Sie mit pstree, wenn Sie dies in Aktion verfolgen möchten). Nach dem Beenden des Terminal-Emulators sollte er jedoch an den Init-Prozess angehängt werden. Mit anderen Worten, alles ist so, wie es sein sollte und wie Sie es vermutlich wollen.

Was tun, wenn Ihre Shell disown nicht unterstützt? Ich würde nachdrücklich empfehlen, zu einem zu wechseln, der dies tut, aber da diese Option nicht verfügbar ist, haben Sie einige Möglichkeiten.

  1. screen und tmux können dieses Problem lösen, aber es sind viel schwerere Lösungen, und ich mag es nicht, sie für eine so einfache Aufgabe ausführen zu müssen. Sie eignen sich viel besser für Situationen, in denen Sie ein tty verwalten möchten, normalerweise auf einem Remotecomputer.
  2. Für viele Benutzer kann es wünschenswert sein, festzustellen, ob Ihre Shell eine Funktion wie zshs setopt Nohup unterstützt. Hiermit kann festgelegt werden, dass SIGHUP beim Beenden der Shell nicht an die Jobs in der Jobtabelle gesendet werden soll. Sie können dies entweder direkt vor dem Beenden der Shell anwenden oder der Shell-Konfiguration wie ~/.zshrc hinzufügen, wenn Sie dies immer möchten.
  3. Finden Sie eine Möglichkeit, die Jobtabelle zu bearbeiten. Ich konnte keinen Weg finden, dies in tcsh oder csh zu tun, was etwas störend ist.
  4. Schreiben Sie ein kleines C-Programm zum Verzweigen und für 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 so einen prozessspezifischen Eintrag in der Auftragstabelle vermeiden.
38
Stephen Rosen
  1. Nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Ich benutze schon sehr lange Nummer 2, aber Nummer 3 funktioniert genauso gut. Außerdem verfügt disown über das Nohup-Flag -h, kann alle Prozesse mit -a und alle ausgeführten Prozesse mit -ar deaktivieren.

Die Stummschaltung erfolgt durch $COMMAND &>/dev/null.

Hoffe das hilft!

26
Mr. Minty Fresh

in tcsh (und möglicherweise auch in anderen Shells) können Sie Klammern verwenden, um den Prozess zu trennen.

Vergleichen Sie dies:

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

Dazu:

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

Dadurch wird Firefox aus der Jobliste entfernt, es ist jedoch weiterhin mit dem Terminal verbunden. Wenn Sie sich über 'ssh' an diesem Knoten angemeldet haben, wird der ssh-Prozess beim Versuch, sich abzumelden, immer noch hängen bleiben.

9
Nathan Fellman

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

9
dunkyp

Einfachste und einzig richtige Antwort für bash:

command & disown

Sie müssen den Prozess nicht vom Terminal trennen, sondern von der Shell.

7
ManuelSchneid3r

Um die Zuordnung von tty Shell aufzuheben, führen Sie den Befehl über die Sub-Shell aus, z.

(Befehl)&

Beim Beenden wird das verwendete Terminal geschlossen, der Prozess ist jedoch noch aktiv.

prüfen -

(sleep 100) & exit

Anderes Terminal öffnen

ps aux | grep sleep

Prozess ist noch am Leben.

7
jitendra

Hintergründe und Vordergrund eines Jobs sind wahrscheinlich die allerersten Dinge, die jeder Unix-Systemadministrator wissen sollte.

So wird es mit bash gemacht:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
6
djangofan

Sie können Ihren Befehl mit dem Befehl Nohup ausführen. Dadurch wird der Prozess getrennt und die Ausgabe in eine bestimmte Datei umgeleitet. Ich bin mir jedoch nicht sicher, ob das genau das ist, was Sie benötigen.

4
Ben

Try daemon - sollte bei Ihrem freundlichen Paketmanager erhältlich sein und sich umfassend darum kümmern, sich vom Terminal zu trennen.

2
ShiDoiSi

Fügen Sie dies einfach in Ihren bashrc/zshrc ein:

detach() {
  "[email protected]" 1>/dev/null 2>/dev/null &; disown
}

Dann können Sie abgelehnte Befehle wie folgt ausführen:

detach gedit ~/.zshrc
2
B. Branchard

In meinem .bashrc habe ich genau zu diesem Zweck folgende Funktionen:

function run_disowned() {
    "[email protected]" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "[email protected]" 1>/dev/null 2>/dev/null
}

Stellen Sie einem Befehl dos als Präfix voran, um ihn vom Terminal getrennt auszuführen.

Die Funktion ist für die Arbeit mit bash und zsh geschrieben.

1
mic_e

Ich habe unter Mac OS X festgestellt, dass ich sowohl Nohup als auch Disown verwenden muss, um sicherzustellen, dass der untergeordnete Prozess nicht mit dem Terminal abgerissen wird.

0
aaron

Ich benutze das folgende Skript, um dies zu tun. Es stoppt den Prozessdruck auf dem Terminal, löst sich mit Nohup und beendet sich mit dem Rückgabestatus, wenn der Befehl innerhalb der TIMEOUT beendet wird.

#!/bin/bash

TIMEOUT=0.1

CMD=( "[email protected]" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#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
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
Nohup "${CMD[@]}" >/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: $CMD"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS

Anwendungsbeispiel:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
0
jozxyqk