¿Cómo iniciar correctamente un programa y hacer posible redirigir su salida en ejecución (stdout y stderr) en una etapa posterior?

¿Cómo iniciar correctamente un programa y hacer posible redirigir su salida en ejecución (stdout y stderr) en una etapa posterior?

El problema es bastante simple: me resulta útil tener la posibilidad deencender (y apagar)la salida de algún programa en ejecución en cada momento que necesito. Para ser más preciso, quiero tener la libertad de redirigir su salida estándar (y error) desde el shell actual a otro, a /dev/nullun archivo o de regreso al shell original.

Busco algo directo (y seguro) que aproveche el hecho de que sépor adelantadoque encenderé y apagaré las salidas. También publico una respuesta.


Debajo de mi primer intento. Supongamos que trabajo en el caparazón número 35.

$ who am I                     # the command line to ask where am I
myuser  pts/35  ...            # The answer 

Mi intento comienza con un enlace simbólico a esa terminal.

ln -s /dev/pts/35  MyOutput  # The command to link

La idea es iniciar el programa con la redirección configurada a ese enlace.

./Execute_program > MyOutput

Funciona, redirige la salida a mi terminal, pero cuando doy el comando para cambiar el enlace,

ln -sf  /dev/null  MyOutput

el enlace cambia,pero la redirección no cambiacomo esperaba. No cambia durante el proceso en ejecución. Si lanzo un nuevo programa de la misma manera, la redirección sigue la nueva prescripción del enlace.
Si empiezo de nuevo y configuro el enlace a /dev/nullla salida se suprime como se esperaba, pero nuevamente, cuando cambio el enlace, la redirección no cambia.
Si hago un enlace a un enlace obtengo el mismo resultado. El uso de hard linkno cambia la situación.

Desafortunadamenteel shell expande la línea de comando en el momento del lanzamiento.

¿Existe alguna posibilidad de hacer el trabajo de manera similar o tengo que encontrar cómo comunicar al proceso (o a los PPID) que se cambia el enlace?


Notas:

Esta es una pregunta de la serie "¿Cómo redirigir la salida de un proceso en ejecución?", pero no comienza desde el punto"Ops, lancé el programa y olvidé redirigir la salida. Ahora quiero hacerlo", sino por el contrario: "¿Cómo puedo iniciar un programa con el objetivo explícito de redirigir la salida a otra parte en una etapa posterior?".

Tengo la intención de utilizar dicho procedimiento cuando no sea posible (o conveniente) modificar el código fuente del programa.
Ileerque es posible disownprocesar, usar screeny transferir de una pantalla a otra... o usar un depurador, interceptar el proceso... Todas esas soluciones podrían funcionar con una buena cantidad de experiencia y esfuerzo, pero algunas de ellas presentan un porcentaje de riesgo también.

Respuesta1

Encuentro una solución a través de mkfifo, que crea una tubería con nombre, oFIFO.
Sencillo como crear un enlace simbólico y es posible utilizar todas las redirecciones permitidas desde el shell.

mkfifo MyOutput

ls -lda

0 prw-r--r-- 1 My_username My_username  0 May 11 17:45 MyOut|

Puedo iniciar el programa con redirección a ese enlace.

./Execute_program > MyOutput  &  cat MyOutput 

y la salida comienza a fluir en el terminal.

Si presiono ctrl+ cinterrumpo el flujo pero no el proceso en ejecución (tengo que usar algo como kill pido kill %1para hacerlo).
Cuando por segunda vez le preguntaré alFIFOpara volcar en la terminal (nuevamente con cat MyOutput) comenzará a volcar la salida a partir de ese momento.

Notas y advertencias:

  • Hasta que no le pida un volcado, FIFOscontendrá toda la salida.
    Como preguntaré la primera vez, seráEnjuagartodo.
  • Puedo redirigir (o agregar) a otro archivocat MyOutput >> NewRealFile
  • ¡Puedo usarlo cat MyOutputdesde otro terminal también!
  • Advertencia: Si le pido a 2 programas (o instancias) diferentes que redirijan la salida al mismo, FIFOsel flujo se fusionará (noa prioriforma de distinguir de qué programas proviene esa línea).
  • Advertencia: Si pregunto 2 o más veces (tal vez desde diferentes terminales), le dará una línea para cada solicitud, dividiendo la salida para el solicitante. Tal vez haya una solución segura...

Respuesta2

Si entiendo tu pregunta correctamente:

script 1>>~/out.fifo 2>>~/error.fifo 

luego para monitorear puedes hacer algo como:

watch cat ~/out.fifo

Podrías usar archivos reales en lugar de Fifos.

script 1>/tmp/$0-out 2>/tmp/$0-error

luego tail -f ellos, serán reemplazados cuando ejecute los scripts nuevamente.

Prefiero el segundo método, o simplemente usar un multiplexor (es decir, pantalla o cualquiera que sea la reencarnación popular de esta semana)

screen -t "name" bash -c 'script'

entonces

screen -r

para "monitorear" y ctrl+ad para desconectar.

Asegúrese de hacer una pausa al final de su script si desea ver el resultado después de ejecutarlo.

Respuesta3

Si yo fuera usted, simplemente redirigiría la salida a un archivo, luego seguiría ese archivo cuando quisiera ver la salida... también es posible que desee limitar el tamaño de ese archivo si cree que la salida va a ser bastante larga, o escriba el archivo en la RAM en lugar de en el disco si cree que la salida será bastante rápida, pero cómo hacer esas cosas es otra cuestión, no lo sé.

información relacionada