¿Cómo puedo rechazar un proceso en ejecución y asociarlo a un nuevo shell de pantalla?

159

Tengo un programa en ejecución en un shell SSH. Quiero pausarlo y poder deshacer su ejecución cuando regrese.

Una forma en que pensé en hacer eso fue transferir su propiedad a un shell de pantalla, manteniéndolo así en funcionamiento.

¿Hay una manera diferente de proceder?

levesco
fuente
8
Consulte también ¿Puedo nohup / screen un proceso ya iniciado? y el comando Reanudar que se ejecuta en una sesión SSH eliminada , que menciona varias soluciones basadas en ptrace que no se mencionan (actualmente) aquí.
Gilles
De preguntas como unix.stackexchange.com/a/4039/13496 , escucho sobre retty y neercs . Hmmm ... me pregunto si hay algo así como una capa de " pantalla aquí" antes de ejecutar un proceso la próxima vez si pierdo la terminal superior en el futuro, eso hará que sea fácil regresar a la entrada / salida / error
Marcos
El problema secundario / implícito en esta pregunta que no puedo entender es ... ¿por qué el shell eligió rechazar un trabajo suspendido cuando hay uno nuevo / recién lanzado en segundo plano que ni siquiera necesita / espera stdin? Este es el tratamiento al que me he acostumbrado, así que no sé qué fue diferente aquí ...
Marcos

Respuestas:

86

Usar GNU screenes tu mejor apuesta.

Pantalla de inicio de funcionamiento cuando la primera conexión - corro screen -D -R, ejecutar el comando, y, o bien desconectar o suspender con CTRL-Zy luego desconecto de pantalla pulsando CTRL-Aa continuación D.

Cuando vuelva a iniciar sesión en la máquina, vuelva a conectarse ejecutando screen -D -R. Estarás en el mismo caparazón que antes. Puede ejecutar jobspara ver el proceso suspendido si lo hizo, y ejecutar %1(o el trabajo correspondiente #) para ponerlo en primer plano nuevamente.

Andrew Yochum
fuente
2
Wow, no puedo creer que una respuesta de GNU Screen sea actualmente la más baja. ¿Me estoy perdiendo de algo?
Faheem Mitha
1
¡Quizás! Me parece lo mejor.
Andrew Yochum
1
Mirando hacia atrás, claramente parece ser la solución más sencilla, siempre que pueda planificar en consecuencia y ejecutar sus procesos desde un entorno de pantalla. De todos modos, ¡lo convertí en la respuesta oficial!
levesque
28
Creo que esto no responde la pregunta. La pregunta comienza con " Tengo un programa en ejecución ". Esta respuesta supone que aún no se está ejecutando ...
Anko
sí, claramente escribió que quiere llevarlo a una sesión de pantalla :-)
Florian Heigl
112

Puede revocar la "propiedad" del programa desde el shell con el disownincorporado:

# press Ctrl+Z to suspend the program
bg
disown

Sin embargo, esto solo le dice al shell que no envíe una SIGHUPseñal al programa cuando el shell salga. El programa retendrá cualquier conexión que tenga con el terminal, generalmente como flujos de entrada, salida y error estándar. No hay forma de volver a conectarlos a otra terminal. (La pantalla funciona emulando un terminal para cada ventana, por lo que los programas se adjuntan a la ventana de la pantalla).


Es posible volver a conectar los descriptores de archivo a un archivo diferente conectando el programa en un depurador (es decir, usando ptrace) y haciendo que llame open, dupy close. Hay algunas herramientas que hacen esto; Este es un proceso complicado, y a veces bloquean el proceso. Las posibilidades incluyen (enlaces recogidos de respuestas a ¿Cómo puedo renegar de un proceso en ejecución y asociarlo a un nuevo shell pantalla? Y ¿Puedo nohup / pantalla de un proceso iniciado ya-? ):

Gilles
fuente
disownelimina el proceso de la lista de control de trabajos.
ctrl-alt-delor
3
¿Por qué no disown -h?
Cees Timmerman
@CeesTimmerman Eso deja el trabajo en la tabla de trabajo del shell, pero ¿cuál es la ventaja de eso?
Gilles
@Gilles: para que puedas hacerlo fgo killno, y ver si termina por sí solo.
Peter Cordes
¿Qué utilidades mencionadas funcionan con un grupo de procesos (por ejemplo bzcat a.bz2 | grep text)? El hombre reptyrdice que no admite mover los procesos con niños.
dma_k
64

Para mover un proceso entre terminales o volver a conectar un desautorizado, puede usar, por ejemplo, reptyr .

jofel
fuente
1
Sí, eso lo salvó, gracias! Leí en el sitio web del autor cómo funciona mejor que herramientas similares o anteriores, por ejemplo. para programas ncurses.
Marcos
44
Esto es asombroso; debería resolver la situación de una amiga de perder constantemente su trabajo ejecutándolo directamente en ssh y luego necesitando subir a un tren. "Vaya, olvidé usar la pantalla. Otra vez".
Adam Katz
3
+1 Aunque la screenrespuesta aceptada es, por supuesto, ideal, en realidad no responde la pregunta, que específicamente solicita una forma de mover un proceso actualmente en ejecución screeno similar. También vea esta respuesta: serverfault.com/a/284795
toxefa
1
Absolute live saver. Me permitió volver a conectarme a ejecutar apt dist-upgrade que estaba esperando la confirmación del usuario.
andig
28

Mi solución favorita es usar tmux, podría separar la sesión y volver a conectarla en otro terminal.

Cuando se separó de la sesión anterior, puede cerrar la terminal de manera segura; luego use tmux attachpara volver a la sesión, incluso si ha cerrado la sesión.

margarita
fuente
1
¡también puedes compartir tu sesión con tu amigo y usar múltiples ventanas y paneles y mucho más! me encanta ^ _ ^
igor
ejemplo de uso por favor?
Vitaly Zdanevich
21

También hay una pequeña utilidad llamada retty que le permite volver a conectar los programas en ejecución a otro terminal.

adamg
fuente
19

No lo uso con regularidad, pero Neercs afirma apoyar esto. Es un screenprograma similar con varias características sofisticadas, como una mejor administración de paneles, pero lo principal que ofrece es la capacidad de importar un proceso en un panel

Michael Mrozek
fuente
2
Interesante. Se juega sucio ( ptrace), pero no solo manipula los descriptores de archivo, sino que bifurca el proceso. Es capaz de agarrar find /, pero bloqueó una fiesta interactiva.
Gilles
@Gilles No recuerdo cómo fue cuando lo intenté, pero no tiene una gran reputación, me dicen que falla con bastante frecuencia
Michael Mrozek
9

Si solo quieres pausarlo y reiniciarlo después, puedes usarlo killcon STOPo CONTseñal.

Primero descubra los procesos PID con

$ ps aux

Luego envíe las señales a ese PID listado en el proceso

$ kill -STOP <PID>

$ kill -CONT <PID>
Yunzen
fuente
9

"injcode" de ThomasHabets parece ser exactamente lo que necesito:

https://github.com/ThomasHabets/injcode

El programa injcode permite que se inyecte código arbitrario en un proceso en ejecución, ya sea que usted lo supiera de antemano o no y estuviera ejecutando screen o tmux

Desde el archivo Léame:

Ejemplo 1: mover irssi de una terminal a otra

Quizás moverlo a una pantalla.

Primero inicie irssi en una terminal.

Ejecute injcode en otra terminal: $ injcode -m retty

Irssi ahora debería ser trasladado a la segunda terminal, incluyendo tener una nueva terminal de control.

usuario2688272
fuente
1

Esto funcionó para mí:

  1. bg el proceso
  2. jobs -l encontrar número de proceso
  3. tmux iniciar el administrador de la ventana de shell
  4. reptyr -L PROCESSNUMBER

reptyr's -Lera necesario para conseguir que esto funcione:

-L Like '-l', but also redirect the child's stdio to the slave.

por este error:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

Y con -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
guaka
fuente