Cómo redirigir el resultado de un proceso ya en ejecución

Normalmente comenzaría un comando como

longcommand &; 

Sé que puedes redirigirlo haciendo algo como

 longcommand > /dev/null; 

por ejemplo, para deshacerse de la salida o

 longcommand 2>&1 > output.log 

para capturar salida

Pero a veces me olvido, y me preguntaba si hay una forma de capturar o redirigir después del hecho.

 longcommand ctrl-z bg 2>&1 > /dev/null 

o algo así para poder continuar usando el terminal sin que aparezcan mensajes en el terminal.

Consulte Redirigir la salida de un proceso en ejecución .

Primero ejecuto el comando cat > foo1 en una sesión y pruebo que los datos de stdin se copien en el archivo. Luego, en otra sesión, redirijo la salida.

Primero encuentra el PID del proceso:

 $ ps aux | grep cat rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat 

Ahora compruebe los manejadores de archivos que tiene abiertos:

 $ ls -l /proc/6760/fd total 3 lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5 l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1 lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5 

Ahora ejecute GDB:

 $ gdb -p 6760 /bin/cat GNU gdb 6.4.90-debian [license stuff snipped] Attaching to program: /bin/cat, process 6760 [snip other stuff that's not interesting now] (gdb) p close(1) $1 = 0 (gdb) p creat("/tmp/foo3", 0600) $2 = 1 (gdb) q The program is running. Quit anyway (and detach it)? (y or n) y Detaching from program: /bin/cat, process 6760 

El comando p en GDB imprimirá el valor de una expresión, una expresión puede ser una función para llamar, puede ser una llamada al sistema … Así que ejecuto una llamada al sistema close() y paso el identificador 1, luego ejecuto una creat() llamada al sistema para abrir un nuevo archivo. El resultado de creat() fue 1, lo que significa que reemplazó el manejador de archivo anterior. Si quería usar el mismo archivo para stdout y stderr o si quería reemplazar un manejador de archivo con algún otro número, entonces tendría que llamar a la llamada del sistema dup2() para lograr ese resultado.

Para este ejemplo, elegí usar creat() lugar de open() porque hay menos parámetros. Las macros C para las banderas no son utilizables desde GDB (no usa encabezados C) así que tendría que leer los archivos de encabezado para descubrir esto: no es tan difícil hacerlo, pero tomaría más tiempo. Tenga en cuenta que 0600 es el permiso octal para el propietario que tiene acceso de lectura / escritura y para el grupo y otros que no tienen acceso. También funcionaría usar 0 para ese parámetro y ejecutar chmod en el archivo más adelante.

Después de eso verifico el resultado:

 ls -l /proc/6760/fd/ total 3 lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5 l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 < ==== lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5 

Escribir más datos en cat resultados en el archivo /tmp/foo3 se adjunta.

Si desea cerrar la sesión original, debe cerrar todos los manejadores de archivos, abrir un nuevo dispositivo que pueda ser la setsid() control y luego llamar a setsid() .

Dupx

Dupx es una sencilla herramienta * nix para redirigir la salida / entrada / error estándar de un proceso ya en ejecución.

Motivación

A menudo me he encontrado en una situación en la que un proceso que comencé en un sistema remoto a través de SSH toma mucho más tiempo de lo que había anticipado. Necesito romper la conexión SSH, pero si lo hago, el proceso morirá si intenta escribir algo en stdout / error de una tubería rota. Desearía poder suspender el proceso con ^ Z y luego hacer una

 bg %1 >/tmp/stdout 2>/tmp/stderr 

Lamentablemente, esto no funcionará (en shells que conozco).

http://www.isi.edu/~yuri/dupx/

También puede hacerlo utilizando reredirect ( https://github.com/jerome-pouiller/reredirect/ ).

Tipo

 reredirect -m FILE PID 

y las salidas (estándar y error) se escribirán en ARCHIVO.

README reredirect también explica cómo restaurar el estado original del proceso, cómo redirigir a otro comando o redirigir solo stdout o stderr.

(Reredirect parece tener las mismas características que Dupx describió en otra respuesta pero, no depende de Gdb).

Pantalla

Si el proceso se está ejecutando en una sesión de pantalla, puede usar el comando de registro de la pantalla para registrar el resultado de esa ventana en un archivo:

Cambie a la ventana del script, Ca H para iniciar sesión.
Ahora usted puede :

 $ tail -f screenlog.2 | grep whatever 

Desde la página man de la pantalla:

log [on | off]

Inicie / deje de escribir la salida de la ventana actual en un archivo “screenlog.n” en el directorio predeterminado de la ventana, donde n es el número de la ventana actual. Este nombre de archivo se puede cambiar con el comando ‘logfile’. Si no se proporciona ningún parámetro, el estado del registro se alterna. El registro de la sesión se agrega al contenido anterior del archivo si ya existe. El contenido actual y el contenido del historial de desplazamiento no se incluyen en el registro de la sesión. El valor predeterminado es ‘off’.

Estoy seguro de que tmux tiene algo similar también.

Recopilé información en Internet y preparé el guión que no requiere ninguna herramienta externa: vea mi respuesta aquí . Espero que sea útil.