So setzen Sie einen Hintergrundprozess aus und rücken ihn in den Vordergrund

166

Ich habe einen Prozess ursprünglich im Vordergrund ausgeführt. Ich habe durch Ctrl+ suspendiert Zund setze dann seine Ausführung im Hintergrund durch fort bg <jobid>.

Ich frage mich, wie ich einen im Hintergrund laufenden Prozess anhalten kann.

Wie kann ich einen Hintergrundprozess in den Vordergrund bringen?

Bearbeiten:

Der Prozess gibt an stderr aus. Wie soll ich den Befehl fg <jobid>ausgeben, während der Prozess an das Terminal ausgegeben wird?

Tim
quelle
1
Sie können weiterhin Befehle in ein Terminal eingeben, in dem Fehler auftreten. Der auf STDERR ausgegebene Text zählt nicht als Eingabe, sondern nur die von Ihnen gesendeten Schlüssel. Auf dem Bildschirm sieht es verwirrend aus, aber es funktioniert.
Caleb
@Caleb: Auch wenn der Prozess stdout ausgibt, kann ich trotzdem tippen fg <jobid>, um ihn in den Vordergrund zu stellen?
Tim
@ Tim: Ja, das kannst du.
Caleb

Antworten:

214

Geben Sie, wie Tim sagte, ein fg, um den letzten Vorgang wieder in den Vordergrund zu stellen.

Wenn mehr als ein Prozess im Hintergrund ausgeführt wird, gehen Sie folgendermaßen vor:

$ jobs
[1]   Stopped                 vim
[2]-  Stopped                 bash
[3]+  Stopped                 vim 23

fg %3um den vim 23Prozess wieder in den Vordergrund zu bringen .

Um den im Hintergrund laufenden Prozess anzuhalten, verwenden Sie:

kill -STOP %job_id

Das SIGSTOP-Signal stoppt (pausiert) einen Prozess im Wesentlichen auf die gleiche Weise wie Ctrl+ Z.

Beispiel: kill -STOP %3.

Quellen: Senden von Signalen an Prozesse unter Linux und Unix und Verwalten von Hintergrund- und Vordergrundjobs .

fromnaboo
quelle
23
Signal 19 ist SIGCONTfür mich; Ich benutze kill -STOPund kill -CONTbevorzugt , um die Zahlen sowieso erinnern, aber Sie können überprüfen , kill -lsie die numerischen Werte erinnern an
Useless
Der Prozess wird an stderr ausgegeben. Wie soll ich den Befehl ausgeben jobund fg <jobid>während der Prozess an das Terminal ausgegeben wird?
Tim
1
@Tim Geben Sie den Befehl wie gewohnt ein. Solange der Job im Hintergrund ausgeführt wird, liest er nicht, was Sie eingeben - Ihre Shell ist. Was Sie eingeben, sieht für Sie vielleicht kaputt aus, aber die Shell wird es ganz gut verstehen.
AlexWebr
@AlexWebr: Danke, es funktioniert! (1) Akzeptiert ein Hintergrundjob keine Ein- und Ausgaben, einschließlich "Strg + Z" usw., richtig? (2) Kann ein im Hintergrund ausgeführter Job direkt angehalten werden? Wenn ja, wie? Wenn nein, muss es zuerst geändert werden, damit es im Vordergrund ausgeführt wird, bevor es angehalten werden kann?
Tim
2
Kann ein Job im Hintergrund läuft direkt ausgesetzt werden ja: kill -STOP %job_idwie erläutert
Useless
31

Dies sollte für jede Shell mit Job-Kontrolle zutreffen, die (größtenteils) als selbstverständlich angesehen werden kann, es sei denn, es handelt sich um eine wirklich alte Shell. Es ist im POSIX-Standard enthalten und dashunterstützt sogar die Auftragssteuerung (wenn es interaktiv oder mit ausgeführt wird -m).

Interaktiv

  • Ctrl+ zunterbricht das aktuell vordergründige Programm
  • bgHintergrund das zuletzt angehaltene Programm
    (verwenden Sie es bg %2mit der Auftragsnummer, die Sie überprüfen können jobs)
  • fg wird das zuletzt angehaltene Programm in den Vordergrund stellen

In zshkönnen Sie eine Schlüsselbindung schreiben, die implizit fgvon der Eingabeaufforderung über ein anderes Ctrl+ ausgeführt wird z:

_zsh_cli_fg() { fg; }
zle -N _zsh_cli_fg
bindkey '^Z' _zsh_cli_fg

Es gibt wahrscheinlich auch eine clevere Möglichkeit, bgbeim Suspendieren implizit zu rennen , aber es scheint unklug; Zumindest für mich ist der Großteil meiner Ctrl+ zNutzung darauf zurückzuführen, dass Ctrl+ ces nicht gelingt, auszubrechen. Ich möchte dem zB kill %1eher folgen als bgund ich möchte sicher nicht standardmäßig töten! (Diese Logik geht auch dahin, warum ich diese Tastenzuordnung nicht mehr verwende: Wenn ich Ctrl+ anklopfe z, um einen Prozess zu stoppen, möchte ich, dass er als letztes fortgesetzt wird!)

Nicht interaktiv

Wenn Sie sich in einer anderen Shell-Instanz befinden (oder einem anderen Benutzer, der manchmal auch sudoBefehle enthält), können Sie wahrscheinlich keine Jobnummern verwenden.

Sie können immer noch auf einen anderen Prozess einwirken, sobald Sie dessen Prozess-ID (PID) kennen. Sie können die PID mit pgrep …oder ps aux |grep …(oder von derselben Shell jobs -loder $!) abrufen und dann ausführen:

kill -STOP $PID  # suspend
kill -CONT $PID  # continue (resume)

Wenn Sie die Prozess-ID nicht kennen und keine Bedenken haben, andere Instanzen des Prozesses nach Namen auszusetzen, können Sie Signale an eine der folgenden Adressen übergeben:

killall -STOP program_name
pkill -STOP program_name
pkill -f -STOP program_name_or_args

Ein CONTSignal für ein Programm, das mit Ctrl+ z(und nicht mit bg'd) gestoppt wurde, nimmt seinen Fortschritt wieder auf (im Vordergrund), so als ob Sie es gewesen wären fg.

Betreff: Standardfehler

Bei der Bearbeitung dieser Frage werden Sie nach Standardfehlern gefragt:

Der Prozess gibt an stderr aus. Wie soll ich den Befehl fg <jobid>ausgeben, während der Prozess an das Terminal ausgegeben wird?

Sofern der betreffende Job keine Komponenten im Hintergrund hat (oder der gesamte Job im Hintergrund kill -CONTist, z. B. über ), sollte die Ausgabe nicht angezeigt werden, während der Job angehalten ist.

Wenn immer noch Daten ausgegeben werden (Standardausgabe oder Standardfehler), wird Ihr Terminal zwar optisch überladen, die gesamte Ausgabe wird jedoch ignoriert, da sie nicht Teil Ihrer Eingabe ist. Dies könnte es schwieriger machen zu wissen, dass Sie keine Tippfehler eingegeben haben, aber (blind) fgEntersollte die Eingabe ausreichen (es sei denn, Sie haben mehrere Jobs und der betreffende ist nicht der neueste. In diesem Fall benötigen Sie tatsächlich den Jobdeskriptor ).

Wenn Sie den Jobdeskriptor suchen müssen, verwenden Sie ein anderes Terminal, um das STOPSignal über die oben beschriebenen nicht interaktiven Methoden zu senden . Dies sollte Ihre Anzeige freigeben (vielleicht Enterein paar Mal drücken oder ausführen clearoder Ctrl+ L), damit Sie dann ausführen können jobs, um den Jobdeskriptor zu finden, und dann ausführen, fg %Nwo Ndiese Nummer ist.

Adam Katz
quelle
Das einzige Problem beim Anhalten und Fortsetzen von Prozessen besteht darin, dass die Verbindung unterbrochen wird, wenn Sie Verbindungen zu einem anderen Programm herstellen (z. B. RabbitMQ).
Nav
@Nav - Das liegt daran, dass Sie es nicht kopflos laufen ließen. In bash und zsh, ich glaube , Sie nur brauchen disown einen backgrounded Prozess. Ich bevorzuge es, solche Aufgaben mit nohup oder einem Terminal-Multiplexer wie screen oder tmux auszuführen . Sie können keinen Nohup-Prozess abrufen (genau wie Sie einen Hintergrundprozess nicht von einer separaten Verbindung aus fortsetzen können), aber Sie können eine Verbindung zu einem Multiplexer herstellen.
Adam Katz
Es war ein Hintergrundprozess. Ich hatte das Terminal geschlossen und mich dann von einem anderen Terminal aus am Server angemeldet.
Nav
Ja, Sie können einen Prozess nicht von einer anderen Shell aus fortsetzen, es sei denn, er wurde in diesem Sinne gestartet. Ich empfehle dazu screen oder tmux.
Adam Katz
Ich glaube, wenn Sie ein CONTSignal an einen Prozess (Job / Pipeline) senden, der mit Strg + Z gestoppt wurde, wird es im Hintergrund fortgesetzt, auch wenn Sie es nicht bggetan haben.
G-Man
10

Geben Sie ein fg, um es in den Vordergrund zu bringen.

Tim
quelle
Vielen Dank! Der Prozess gibt an stderr aus. Wie soll ich den Befehl fg <jobid>ausgeben, während der Prozess an das Terminal ausgegeben wird?
Tim
1
  1. liste jobs mit jobsbefehl auf
  2. Bringen Sie Ihren Zieljob in den Vordergrund mit fg; z.B: fg %4
  3. Hit CTRL Zauszusetzen
  4. Verwenden Sie bg, um die Ausführung im Hintergrund zu starten. z.B:bg %4
kmiklas
quelle
0

Das Beenden eines Prozesses kann auf verschiedene Arten erfolgen. Bei einem konsolenbasierten Befehl wird der Befehl häufig durch Senden eines CtrlcTastenanschlags (dem Standardinterruptzeichen) beendet. Dies funktioniert, wenn der Prozess im Vordergrundmodus ausgeführt wird.

Wenn ein Prozess im Hintergrundmodus ausgeführt wird, müssen Sie zuerst die Job-ID mit dem psBefehl abrufen. Anschließend können Sie den Prozess mit dem Befehl kill wie folgt beenden:

$ps -f
UID      PID  PPID C STIME    TTY   TIME CMD
amrood   6738 3662 0 10:23:03 pts/6 0:00 first_one
amrood   6739 3662 0 10:22:54 pts/6 0:00 second_one
amrood   3662 3657 0 08:10:53 pts/6 0:00 -ksh
amrood   6892 3662 4 10:51:50 pts/6 0:00 ps -f
$kill 6738
Terminated

Hier würde der killBefehl den first_oneProzess beenden . Wenn ein Prozess einen regulären killBefehl ignoriert , können Sie kill -9die Prozess-ID wie folgt verwenden:

$kill -9 6738
Terminated
Lakshmi
quelle
1
Dies ist zwar wahr, aber es beantwortet nicht die Frage ...
JasonWryan