Cómo suspender y poner en primer plano un proceso en segundo plano

167

Tengo un proceso que originalmente se ejecuta en primer plano. Suspendí por Ctrl+ Z, y luego reanudo su ejecución en segundo plano por bg <jobid>.

Me pregunto cómo suspender un proceso que se ejecuta en segundo plano.

¿Cómo puedo llevar un proceso en segundo plano a primer plano?

Editar:

El proceso sale a stderr, entonces, ¿cómo debo emitir el comando fg <jobid>mientras el proceso sale al terminal?

Tim
fuente
1
Todavía puede escribir comandos en un terminal que arroja errores. El texto arrojado en STDERR no cuenta como entrada, solo las claves que envía. Parece confuso en la pantalla pero funciona.
Caleb
@Caleb: ¿Incluso cuando el proceso sale a stdout, todavía puedo escribir fg <jobid>para ponerlo en primer plano?
Tim
@Tim: Sí, puedes.
Caleb

Respuestas:

216

Como dijo Tim, escriba fgpara volver a poner en primer plano el último proceso.

Si tiene más de un proceso ejecutándose en segundo plano, haga esto:

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

fg %3para volver a poner el vim 23proceso en primer plano.

Para suspender el proceso que se ejecuta en segundo plano, use:

kill -STOP %job_id

La señal SIGSTOP detiene (pausa) un proceso esencialmente de la misma manera que Ctrl+ lo Zhace.

ejemplo: kill -STOP %3.

fuentes: cómo enviar señales a procesos en Linux y Unix y cómo gestionar trabajos en segundo plano y en primer plano .

fromnaboo
fuente
23
la señal 19 es SIGCONTpara mí; Utilizo kill -STOPy prefiero kill -CONTrecordar los números de todos modos, pero puede verificar kill -lpara recordar los valores numéricos
inútil el
El proceso sale a stderr, entonces, ¿cómo debo emitir el comando joby fg <jobid>mientras el proceso sale al terminal?
Tim
1
@Tim Simplemente escriba el comando como lo haría normalmente. Mientras el trabajo esté en segundo plano, no está leyendo lo que escribe: su shell es. Lo que escribe puede parecer roto, pero el shell lo entenderá bien.
AlexWebr
@AlexWebr: ¡Gracias, funciona! (1) ¿Un trabajo en segundo plano no acepta ninguna entrada y salida incluyendo "Ctrl + Z", etc., correcto? (2) ¿Se puede suspender directamente un trabajo que se ejecuta en segundo plano? Si es así, ¿cómo? Si no, ¿se debe cambiar primero para que se ejecute en primer plano antes de que se pueda suspender?
Tim
2
¿Puede un trabajo en ejecución en segundo plano se suspenderá directamente sí: kill -STOP %job_id, como se explica
Inútil
31

Esto debería ser cierto para cualquier shell con control de trabajo, que (en su mayor parte) puede dar por sentado a menos que se trate de un shell verdaderamente antiguo. Está en el estándar POSIX , por lo que incluso dashadmite el control de trabajos (cuando se ejecuta de forma interactiva o con -m).

Interactivo

  • Ctrl+ zsuspenderá el programa actualmente en primer plano
  • bgpondrá en segundo plano el programa suspendido más recientemente
    (use bg %2con el número de trabajo, con el que puede verificar jobs)
  • fg pondrá en primer plano el programa suspendido más recientemente

En zsh, puede escribir un enlace de clave para ejecutar implícitamente fgdesde el indicador a través de otro Ctrl+ z:

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

Probablemente también haya una manera inteligente de correr implícitamente bgal suspender, pero parece poco sabio; al menos para mí, la mayoría de mi Ctrl+ zuso se debe a que Ctrl+ cestá fallando; Quiero seguir eso con, por ejemplo, en kill %1lugar de bg, ¡y ciertamente no quiero dejar de matar por defecto! (Esta lógica también se extiende a por qué ya no uso esta combinación de teclas: si estoy presionando Ctrl+ zpara detener un proceso, ¡lo último que quiero que haga es reanudar!)

No interactivo

Si está en una instancia de shell diferente (o un usuario diferente, a veces incluyendo sudocomandos), es probable que no pueda usar números de trabajo.

Todavía puede actuar en otro proceso una vez que conoce su ID de proceso (PID). Puede obtener el PID con pgrep …o ps aux |grep …(o desde el mismo shell jobs -l, o $!) y luego puede ejecutar:

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

Si no conoce el ID del proceso y no le preocupa suspender otras instancias del proceso por nombre, puede pasar señales a uno de estos:

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

Una CONTseñal a un programa detenido con Ctrl+ z(y no bg'd) reanudará su progreso (en primer plano), de la misma manera que si estuviera en fgél.

Re: Error estándar

La edición de esta pregunta pregunta sobre el error estándar:

El proceso sale a stderr, entonces, ¿cómo debo emitir el comando fg <jobid>mientras el proceso sale al terminal?

A menos que el trabajo en cuestión tenga componentes que estén en segundo plano (o que todo el trabajo esté en segundo plano, tal vez a través de kill -CONT), en realidad no debería ver la salida mientras está suspendido.

Si todavía está emitiendo datos (ya sea a la salida estándar o error estándar), ciertamente hará que su terminal esté desordenada visualmente, pero toda esa salida será ignorada ya que no es parte de su entrada. Esto podría hacer que sea más difícil saber que no ha ingresado ningún error tipográfico, pero la escritura (a ciegas) fgEnterdebería ser suficiente (a menos que tenga varios trabajos y el en cuestión no sea el más reciente, en cuyo caso necesitará el descriptor de trabajo )

Si necesita encontrar el descriptor de trabajo, use otro terminal para enviarle la STOPseñal a través de los métodos no interactivos anteriores. Esto debería liberar su pantalla (quizás presionar Enteralgunas veces o ejecutar clearo Ctrl+ L) para que pueda ejecutar jobspara encontrar el descriptor de trabajo y luego ejecutar fg %Ndónde Nestá ese número.

Adam Katz
fuente
El único problema con la pausa y la reanudación de los procesos es que si realizó alguna conexión con algún otro programa (como RabbitMQ, por ejemplo), la conexión se perdería cuando reanude.
Nav
@Nav - Eso es porque no lo ejecutaste sin cabeza. En bash y zsh, creo que simplemente necesita desconocer un proceso en segundo plano. Prefiero ejecutar tales tareas con nohup o un multiplexor de terminal como screen o tmux . No puede elegir un proceso de nohup (del mismo modo que no puede reanudar un proceso en segundo plano desde una conexión separada), pero puede conectarse a un multiplexor.
Adam Katz
Fue un proceso en segundo plano. Había cerrado la terminal y luego había iniciado sesión en el servidor desde otra terminal.
Nav
Sí, no puede reanudar un proceso desde otro shell a menos que se haya iniciado con eso en mente. Recomiendo screen o tmux para eso.
Adam Katz
Creo que si envía una CONTseñal a un proceso (trabajo / canalización) detenido con Ctrl + Z, se reanudará en segundo plano, incluso si no lo ha bghecho.
G-Man
10

Escriba fgpara ponerlo en primer plano.

Tim
fuente
¡Gracias! El proceso sale a stderr, entonces, ¿cómo debo emitir el comando fg <jobid>mientras el proceso sale al terminal?
Tim
1
  1. enumerar trabajos con jobscomando
  2. Trae tu trabajo objetivo al primer plano con fg; p.ej: fg %4
  3. Golpear CTRL Zpara suspender
  4. Para comenzar a ejecutarse en segundo plano, use bg; p.ej:bg %4
kmiklas
fuente
0

La finalización de un proceso se puede hacer de varias maneras diferentes. A menudo, desde un comando basado en consola, el envío de una Ctrlcpulsación de tecla (el carácter de interrupción predeterminado) saldrá del comando. Esto funciona cuando el proceso se ejecuta en modo de primer plano.

Si un proceso se está ejecutando en modo de segundo plano, primero deberá obtener su ID de trabajo con el pscomando y luego puede usar el comando kill para matar el proceso de la siguiente manera:

$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

Aquí el killcomando terminaría el first_oneproceso. Si un proceso ignora un killcomando regular , puede usar kill -9seguido del ID del proceso de la siguiente manera:

$kill -9 6738
Terminated
Lakshmi
fuente
1
Si bien esto es cierto, no responde la pregunta ...
jasonwryan