¿Cómo conecto un terminal a un proceso separado?


99

He separado un proceso de mi terminal, así:

$ process &

Ese terminal ahora está cerrado desde hace mucho tiempo, pero processtodavía se está ejecutando, y quiero enviar algunos comandos al stdin de ese proceso. ¿Es eso posible?



1
Buscar retty, neercs, etc, y ver también serverfault.com/questions/24425 , serverfault.com/questions/115998
Gilles

Respuestas:


112

Sí lo es. En primer lugar, crear una tubería: mkfifo /tmp/fifo. Use gdb para adjuntar al proceso: gdb -p PID

A continuación, cierre la entrada estándar: call close (0); y ábrelo de nuevo:call open ("/tmp/fifo", 0600)

Finalmente, escriba (desde un terminal diferente, ya que gdb probablemente se bloqueará):

echo blah > /tmp/fifo


66
¡Muy impresionante!
Samuel Edwin Ward,

1
¿Puedo hacer algo similar para redireccionar el proceso stdout a un archivo?
rustyx

@rustyx: No probado, pero esto debería funcionar: crear un archivo en lugar de un tubo, touch /tmp/thefile. Stdout es 1, entonces call close (1); También, utilizar los permisos correctos para escribir: call open ("/tmp/thefile", 0400). El echo…, por supuesto, no es necesario.
Ansgar Esztermann

¡Esto es genial! Estoy usando esto para enviar respuestas "y" o "n" a ciertos procesos que se han separado por completo. El proceso separado tiene su stdout en una ventana separada. Sin embargo, cuando hago este truco, puedo ver que no "recibe" la 'y' o 'n' tan pronto como hago eco, debo salir de gdb y separarlo y luego recibe todos los ecos en consecuencia, así que ¿Hay alguna manera de realizar esto sin necesidad de salir de gdb antes de que el proceso reciba la entrada del fifo?
krb686

Desafortunadamente, parece que no le gusta call open("/tmp/fifo", 0600). cualquier ayuda sería muy apreciada
arquero

27

Cuando el terminal original ya no es accesible ...

reptyrpuede ser lo que desea, consulte https://serverfault.com/a/284795/187998

Cita a partir de ahí:

Echa un vistazo a reptyr , que hace exactamente eso. La página de github tiene toda la información.

reptyr: una herramienta para "volver a poner" programas.

reptyr es una utilidad para tomar un programa en ejecución existente y adjuntarlo a una nueva terminal. ¿Comenzó un proceso de larga duración sobre ssh, pero tiene que irse y no quiere interrumpirlo? Simplemente inicie una pantalla, use reptyr para tomarla, y luego cierre la sesión ssh y diríjase a casa.

USO

reptyr PID

"reptyr PID" tomará el proceso con ID PID y lo conectará a su terminal actual.

Después de adjuntar, el proceso tomará la entrada y escribirá la salida en el nuevo terminal, incluidos ^ C y ^ Z. (Desafortunadamente, si lo pone en segundo plano, aún tendrá que ejecutar "bg" o "fg" en la terminal anterior. Es probable que esto sea imposible de solucionar de manera razonable sin reparar su shell).


12

Estoy bastante seguro de que no puedes.

Comprueba usando ps x. Si un proceso tiene una ?como terminal controlada , no se puede enviar de entrada a ella nunca más.

9942 ?        S      0:00 tail -F /var/log/messages
9947 pts/1    S      0:00 tail -F /var/log/messages

En este ejemplo, puede enviar información para 9947hacer algo como echo "test" > /dev/pts/1. El otro proceso ( 9942) no es accesible.

La próxima vez, puede usar screen o tmux para evitar esta situación.


55
O dtachsi no necesitas un todo screen.
manatwork

44
No hay forma en los estándares (POSIX, SUS), pero en muchos sistemas (¿la mayoría?) Es posible usar los mecanismos que usan los depuradores. Ver la respuesta de Ansgar . Con rootusted podría incluso hacer esto a los procesos de otros usuarios.
dmckee

3
Hacer echo "test" > /dev/pts/1no enviará información al proceso 9947; generará la palabra "prueba" en el terminal de ese proceso.
psmears

6

EDITAR : Como dijo Stephane Gimenez, no es tan simple. Solo le permite imprimir en un terminal diferente.

Puedes intentar escribir en este proceso usando / proc . Debe ubicarse en / proc / pid / fd / 0 , así que un simple:

echo "hello" > /proc/PID/fd/0

Deberías hacerlo. No lo he probado, pero debería funcionar, siempre y cuando este proceso todavía tenga un descriptor de archivo stdin válido . Puede verificarlo con ls -lon / proc / pid / fd / .

  • si es un enlace a / dev / null => está cerrado
  • si es un enlace a / dev / pts / X o un socket => está abierto

Consulte nohup para obtener más detalles sobre cómo mantener los procesos en ejecución.


2
No es tan simple. Por ejemplo, si stdin está vinculado a un terminal, al echoingresar algo en el dispositivo terminal solo se imprimirá lo que escribió en el terminal, no se transmitirá al proceso.
Stéphane Gimenez

5

Simplemente terminar la línea de comando con &no separará completamente el proceso, solo lo ejecutará en segundo plano. (Con zshusted puede usar &!para separarlo, de lo contrario debe hacerlo disownmás tarde).

Cuando un proceso se ejecuta en segundo plano, ya no recibirá información de su terminal de control. Pero puede volver a enviarlo al primer plano fgy luego leerá la entrada nuevamente.

De lo contrario, no es posible cambiar externamente sus descriptores de archivo (incluido stdin) o volver a conectar un terminal de control perdido ... a menos que use herramientas de depuración (vea la respuesta de Ansgar o eche un vistazo al rettycomando).


Y hay una pregunta relacionada aquí: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez

@Rogach declaró "Esa terminal está cerrada por mucho tiempo".
andcoz

1
@andcoz: Sí, pero ha tenido suerte de que el programa no haya sido VISITADO. Estaba sugiriendo un método más seguro.
Stéphane Gimenez

aquí, disown solo funciona realmente si primero redirijo stdout como con >>/dev/stderr, de lo contrario, cuando cierro la terminal, el proceso "repudiado" también terminará ... Realmente nunca entendí esto ...
Aquarius Power
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.