2009-03-23 11:59:25 +0000 2009-03-23 11:59:25 +0000
311
311

Wie trenne ich einen Prozess vollständig vom Terminal?

Ich benutze Tilda (Drop-Down-Terminal) unter Ubuntu als meine “Kommandozentrale” - ziemlich genau so, wie andere GNOME Do, Quicksilver oder Launchy verwenden könnten.

Ich kämpfe jedoch damit, wie ich einen Prozess (z.B. Firefox) vollständig von dem Terminal trennen kann, von dem aus er gestartet wurde - d.h. verhindern, dass ein solcher (Nicht-)Kindprozess

  • beim Schließen des Ursprungs-Terminals beendet wird
  • das Ursprungs-Terminal über STDOUT/STDERR “verunreinigt”

Um Vim zum Beispiel in einem “richtigen” Terminal-Fenster zu starten, habe ich ein einfaches Skript wie das folgende versucht:

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

Das verursacht jedoch immer noch Verunreinigung (auch die Übergabe eines Dateinamens scheint nicht zu funktionieren).

Antworten (18)

355
355
355
2009-03-23 13:18:35 +0000

Wenn Sie einen Prozess gestartet haben, können Sie ihn im Hintergrund starten, indem Sie ihn zunächst stoppen (drücken Sie Strg-Z) und dann bg eingeben, damit er im Hintergrund fortgesetzt wird. Es handelt sich jetzt um einen “Job”, und seine stdout/stderr/stdin sind immer noch mit Ihrem Terminal verbunden.

Sie können einen Prozess sofort als Hintergrundprozess starten, indem Sie ein “&” an das Ende anhängen:

firefox &

Um ihn im Hintergrund stummzuschalten, verwenden Sie dies:

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

Einige zusätzliche Informationen:

nohup ist ein Programm, mit dem Sie Ihre Anwendung mit ausführen können, so dass ihr stdout/stderr stattdessen in eine Datei gesendet werden kann und das Schließen des Elternskripts das Kind nicht SIGHUPEN wird. Sie müssen jedoch die Voraussicht gehabt haben, es vor dem Start der Anwendung benutzt zu haben. Aufgrund der Art und Weise, wie nohup funktioniert, können Sie es nicht einfach auf einen laufenden Prozess anwenden.

disown ist eine eingebaute Bash, die einen Shell-Job aus der Jobliste der Shell entfernt. Das bedeutet im Grunde genommen, dass Sie fg, bg nicht mehr darauf verwenden können, aber was noch wichtiger ist, wenn Sie Ihre Shell schließen, wird sie nicht mehr hängen oder eine SIGHUP an dieses Kind senden. Im Gegensatz zu nohup wird disown nach dem Start des Prozesses und im Hintergrund verwendet.

Was Sie nicht tun können, ist, die stdout/stderr/stdin eines Prozesses zu ändern, nachdem Sie ihn gestartet haben. Zumindest nicht von der Shell aus. Wenn Sie Ihren Prozess starten und ihm sagen, dass sein stdout Ihr Terminal ist (was Sie standardmäßig tun), dann ist dieser Prozess so konfiguriert, dass er auf Ihr Terminal ausgibt. Ihre Shell hat mit dem FD-Setup des Prozesses nichts zu tun, das ist etwas, das der Prozess selbst verwaltet. Der Prozess selbst kann entscheiden, ob sein stdout/stderr/stdin geschlossen werden soll oder nicht, aber Sie können Ihre Shell nicht benutzen, um ihn dazu zu zwingen.

Um die Ausgabe eines Hintergrundprozesses zu verwalten, haben Sie viele Optionen von Skripten, wobei “nohup” wahrscheinlich das erste ist, was Ihnen in den Sinn kommt. Aber für interaktive Prozesse, die Sie starten, aber vergessen haben, sie zum Schweigen zu bringen (firefox < /dev/null &>/dev/null &), können Sie eigentlich nicht viel tun.

Ich empfehle Ihnen GNU screen. Mit screen 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, benutzen Sie “$@” nicht dort, wo Sie es benutzen.

$@ bedeutet, $1, $2, $3, $1 …, was Ihren Befehl in:

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

verwandeln würde. Das ist wahrscheinlich nicht das, was Sie wollen, denn -e benötigt nur ein Argument. Verwenden Sie gnome-terminal -e, um zu zeigen, dass Ihr Skript nur ein Argument verarbeiten kann.

Es ist wirklich schwierig, mehrere Argumente in dem Szenario, das Sie (mit dem -e) angegeben haben, richtig zum Funktionieren zu bringen, weil &007 nur ein Argument benötigt, nämlich eine Shell-Befehlszeichenfolge. Sie müssten Ihre Argumente in einem einzigen verschlüsseln. Der beste und robusteste, aber eher klobige Weg ist wie folgt:

gnome-terminal -e "vim $(printf "%q " "$@")"
202
202
202
2009-03-23 12:17:32 +0000
nohup cmd &

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

62
62
62
2009-03-23 12:05:02 +0000

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

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

41
41
41
2014-01-22 17:08:16 +0000

Als ich diese Antworten las, hatte ich zunächst den Eindruck, dass die Herausgabe von nohup <command> & ausreichen würde. Als ich zsh in gnome-terminal laufen ließ, stellte ich fest, dass nohup <command> & meine Shell nicht daran hinderte, Kindprozesse beim Beenden zu töten. Obwohl nohup nützlich ist, insbesondere bei nicht interaktiven Shells, garantiert es dieses Verhalten nur, wenn der Kindprozess seinen Handler für das Signal SIGHUP nicht zurücksetzt.

In meinem Fall hätte nohup verhindern sollen, dass Aufhängesignale die Anwendung erreichen, aber die Kindapplikation (in diesem Fall VMWare Player) setzte ihren Handler SIGHUP zurück. Infolgedessen konnte der Terminalemulator beim Beenden Ihre Unterprozesse immer noch beenden. Dies kann meines Wissens nur gelöst werden, indem sichergestellt wird, dass der Prozess aus der Job-Tabelle der Shell entfernt wird. Wenn nohup mit einer eingebauten Shell überschrieben wird, wie es manchmal der Fall ist, kann dies jedoch ausreichend sein…


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

<command> &
disown

oder

<command> &; disown

, wenn Sie Einzeiler bevorzugen. Dies hat den allgemein wünschenswerten Effekt, dass der Unterprozess aus der Jobtabelle entfernt wird. Auf diese Weise können Sie den Terminalemulator verlassen, ohne den Kindprozess versehentlich überhaupt zu signalisieren. Unabhängig davon, wie der Handler SIGHUP aussieht, sollte dies Ihren Kindprozess nicht töten.

Nach dem Verlassen ist der Prozess immer noch ein Kind Ihres Terminalemulators (spielen Sie mit pstree, wenn Sie dies in Aktion sehen wollen), aber nachdem der Terminalemulator beendet ist, sollten Sie ihn an den Init-Prozess angehängt sehen. 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 dafür plädieren, zu einer solchen zu wechseln, aber in Ermangelung dieser Option haben Sie einige Möglichkeiten.

  1. screen und tmux können dieses Problem lösen, aber sie sind viel schwergewichtigere Lösungen, und ich mag es nicht, sie für eine so einfache Aufgabe laufen lassen zu müssen. Sie eignen sich viel besser für Situationen, in denen Sie ein tty warten wollen, typischerweise auf einem entfernten Rechner.
  2. Für viele Benutzer mag es wünschenswert sein, zu prüfen, ob Ihre Shell eine Fähigkeit wie die von zsh setopt nohup unterstützt. Dies kann verwendet werden, um festzulegen, dass SIGHUP nicht an die Jobs in der Job-Tabelle gesendet werden soll, wenn die Shell beendet wird. Sie können dies entweder kurz vor dem Beenden der Shell anwenden oder es zur Shell-Konfiguration hinzufügen, wie z.B. ~/.zshrc, wenn Sie es immer eingeschaltet haben wollen.
  3. Finden Sie einen Weg, die Jobtabelle zu bearbeiten. Ich konnte keinen Weg finden, dies in tcsh oder csh zu tun, was etwas beunruhigend ist.
  4. Schreiben Sie ein kleines C-Programm, um exec() und &007 abzuzweigen. Das ist eine sehr schlechte Lösung, aber der Quelltext sollte nur aus ein paar Dutzend Zeilen bestehen. Sie können dann Befehle als Kommandozeilenargumente an das C-Programm übergeben und so einen prozessspezifischen Eintrag in der Job-Tabelle vermeiden.
30
30
30
2015-08-25 14:39:31 +0000
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Ich benutze Nummer 2 schon sehr lange, aber Nummer 3 funktioniert genauso gut. Außerdem hat disown ein nohup-Flag von -h, kann alle Prozesse mit -a verwerfen, und kann alle laufenden Prozesse mit -ar verwerfen.

Die Stummschaltung wird durch $COMMAND &>/dev/null erreicht.

Hoffentlich hilft das!

9
9
9
2017-05-05 11:55:05 +0000

Einfachste und einzig richtige Antwort für bash:

command & disown

Sie müssen den Prozess nicht vom Terminal, sondern von der Shell lösen.

9
9
9
2009-03-23 14:55:15 +0000

in tcsh (und vielleicht 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

Damit wird Firefox aus der Liste der Jobs entfernt, ist aber immer noch an das Terminal gebunden; wenn Sie sich an diesem Knoten über ‘ssh’ eingeloggt haben, wird beim Versuch, sich auszuloggen, der ssh-Prozess immer noch hängen bleiben.

7
7
7
2012-08-07 05:18:25 +0000

Um die tty-Shell zu dissoziieren, führen Sie den Befehl durch die Sub-Shell aus, z.B.

(Befehl)&

When exit used terminal closed but process is still alive.

check -

(sleep 100) & exit

Open other terminal

ps aux | grep sleep

Process is still alive.

5
5
5
2013-05-22 23:00:56 +0000

Das Hinter- und Vordergründigmachen eines Jobs ist wahrscheinlich eines der allerersten Dinge, die jeder Unix-Sys-Admin wissen sollte.

So wird es mit der bash gemacht:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
4
4
4
2009-03-23 12:03:50 +0000

Sie können Ihren Befehl mit dem nohup-Befehl ausführen, dies löst Ihren Prozess ab und leitet Ausgaben in eine bestimmte Datei um … aber ich bin nicht sicher, ob das genau das ist, was Sie brauchen …

2
2
2
2018-02-05 16:14:17 +0000

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

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

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

detach gedit ~/.zshrc
2
2
2
2009-03-23 12:10:49 +0000

Versuchen Sie daemon – sollte bei Ihrem freundlichen Paketmanager verfügbar sein und sich umfassend um jede Art der Abgrenzung zum Terminal kümmern.

1
1
1
2015-06-14 17:53:47 +0000

In meiner .bashrc habe ich genau zu diesem Zweck diese Funktionen:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Einem Befehl wird dos vorangestellt, um ihn losgelöst vom Terminal auszuführen.

Die Funktion ist so geschrieben, dass sie mit bash und zsh funktioniert.

0
0
0
2010-06-19 16:46:44 +0000

Ich habe unter Mac OS X festgestellt, dass ich sowohl nohup UND disown verwenden muss, um sicherzustellen, dass der Kindprozess nicht mit dem Terminal abgerissen wird.

0
0
0
2014-09-21 04:42:43 +0000

Dazu verwende ich das folgende Skript. Es hält den Prozess an, der an das Terminal druckt, löst sich mit nohup ab und beendet sich mit dem Rückgabestatus, wenn der Befehl innerhalb der TIMEOUT endet.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#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

Verwendungsbeispiel:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
0
0
0
2019-06-21 07:14:46 +0000

sudo apt install ucommon-utils

pdetach command

Bitte sehr :)

-1
-1
-1
2017-02-15 04:16:48 +0000

Viele Antworten schlugen die Verwendung von nohup vor. Ich würde eher vorschlagen, pm2 zu verwenden. Die Verwendung von pm2 gegenüber nohup hat viele Vorteile, wie z.B. die Aufrechterhaltung der Anwendung, das Führen von Protokolldateien für die Anwendung und viele andere Funktionen. Für weitere Einzelheiten sehen Sie sich das hier an .

Um pm2 zu installieren, müssen Sie npm herunterladen. Für Debian-basierte Systeme

sudo apt-get install npm

und für Redhat

sudo yum install npm

Oder Sie können diese Anleitung befolgen. Nach der Installation von npm installieren Sie damit pm2

npm install pm2@latest -g

Sobald es fertig ist, können Sie Ihre Anwendung mit

$ pm2 start app.js # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py # Start, Daemonize and auto-restart application (Python)

Zur Prozessüberwachung verwenden Sie folgende Befehle:

$ pm2 list # List all processes started with PM2
$ pm2 monit # Display memory and cpu usage of each app
$ pm2 show [app-name] # Show all informations about application

Verwalten Sie Prozesse entweder unter Verwendung des Anwendungsnamens oder der Prozess-ID oder verwalten Sie alle Prozesse zusammen:

$ pm2 stop <app_name|id|'all'|json_conf>
$ pm2 restart <app_name|id|'all'|json_conf>
$ pm2 delete <app_name|id|'all'|json_conf>

Log-Dateien finden Sie in

$HOME/.pm2/logs #contain all applications logs
-1
-1
-1
2017-04-05 13:47:37 +0000

Wenn Ihr Ziel darin besteht, einfach eine Befehlszeilenanwendung zu starten, ohne das Terminalfenster in der Nähe zu lassen, dann können Sie versuchen, die Anwendung nach dem Start des Terminals mit Alt-F2 auszuführen.