2008-10-30 20 views
39

Tengo algunas secuencias de comandos que deberían haber dejado de funcionar, pero esperar por siempre.¿Cómo puede un proceso interceptar stdout y stderr de otro proceso en Linux?

¿Hay alguna manera de que pueda entender lo que están escribiendo en stdout y stderr de una manera legible?

lo intentara, por ejemplo, para hacer

tail -f /proc/(pid)/fd/1 

pero que en realidad no funciona. De todos modos, era una posibilidad remota.

¿Alguna otra idea? Por sí solo es bastante detallado e ilegible para ver esto.

Nota: soy solo interesado en su salida, no en otra cosa. Soy capaz de descubrir las otras cosas por mi cuenta; esta pregunta solo se centra en obtener acceso a stdout y stderr del proceso en ejecución después de al iniciarlo.

+0

[reptyr] (https://github.com/nelhage/reptyr) – Louis

+0

Esto funcionó para mí cuando mi programa de destino estaba escribiendo en una tubería, – user666412

Respuesta

7

No estoy seguro de si va a trabajar para usted, pero he leído una página hace un tiempo que describe una method that uses gdb

1

Usted no se establece su sistema operativo, pero voy a tomar una puñalada y decir "Linux".

Ver lo que se escribe en stderr y stdout probablemente no ayude. Si es útil, puede usar tee (1) antes de comenzar la secuencia de comandos para tomar una copia de stderr y stdout.

Puede usar ps (1) para buscar wchan. Esto te dice lo que el proceso está esperando. Si observa la salida de strace, puede ignorar la mayor parte de la salida e identificar la última llamada al sistema (bloqueada). Si se trata de una operación en un identificador de archivo, puede retroceder en el resultado e identificar el objeto subyacente (archivo, socket, pipa, etc.). A partir de ahí, es probable que la respuesta sea clara.

También puede enviar al proceso una señal que hace que se descargue el núcleo, y luego usar el depurador y el archivo del núcleo para obtener un seguimiento de la pila.

40

Como no tengo permiso para editar la respuesta de Jauco, daré la respuesta completa que funcionó para mí (la página de Russell se basa en un comportamiento no garantizado que, si cierra fd 1 para stdout, la próxima llamada a creat se abrirá fd 1.

lo tanto, ejecuta un simple script sin fin como esto:

import time 

while True: 
    print 'test' 
    time.sleep(1) 

Guardar a test.py, correr con

python test.py 

obtener el PID:

ps auxw | grep test.py 

Ahora, adjuntar gdb:

gdb -p (pid) 

y hacer la magia fd:

(gdb) call creat("/tmp/stdout", 0600) 
$1 = 3 
(gdb) call dup2(3, 1) 
$2 = 1 

Ahora usted puede cola/tmp/salida estándar y ver la salida que utiliza para ir a la salida estándar.

+1

La solución de dup2 es mejor de todos modos, pero (con respecto a la devolución de creatina 1) es no está garantizado mientras se use 0 y nadie más esté creando descriptores de archivos: UNIX garantiza que se devuelve el número fd disponible más bajo. – ephemient

+0

Esto realmente no funciona. En el momento en que ejecuta todos estos comandos, cualquier stdout útil ya puede haberse perdido en el éter y este método no captura de forma retroactiva nada que ya esté impreso. – Cerin

8

método Gdb parece mejor, pero se puede hacer esto con strace, también:

strace -p -e = escritura -o archivo 1 -s 1024

-e write=set 
       Perform a full hexadecimal and ASCII dump of all the 
       data written to file descriptors listed in the spec- 
       ified set. For example, to see all output activity 
       on file descriptors 3 and 5 use -e write=3,5. Note 
       that this is independent from the normal tracing of 
       the write(2) system call which is controlled by the 
       option -e trace=write. 

Esto muestra algo más thanyou necesidad (la parte hexadecimal), pero puede sacar eso fácilmente.

2

strace produce mucho menos con solo -ewrite (y no con el = 1 sufijo). Y es un poco más simple que el método gdb, imo.

lo utilicé para ver el progreso de un trabajo MythTV codificación existente (sudo porque no es propietario del proceso de codificación):

$ ps -aef | grep -i handbrake 
mythtv 25089 25085 99 16:01 ?  00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720 
jward 25293 20229 0 16:30 pts/1 00:00:00 grep --color=auto -i handbr 

$ sudo strace -ewrite -p 25089 
Process 25089 attached - interrupt to quit 
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73 
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73 
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73 
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C 
3

Solía ​​strace y codificadas des la salida hexagonal para borrar texto :

PID=some_process_id 
sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p" 

Combiné este comando de otras respuestas.

9

Hay varias utilidades nuevas que envuelven el "método gdb" y añaden algunos toques adicionales. El que uso ahora se llama "reptyr" ("Re-PTY-er"). Además de tomar STDERR/STDOUT, realmente cambiará la terminal de control de un proceso (incluso si no estaba previamente conectado a un terminal).

Lo mejor que puede hacer es iniciar una sesión de pantalla y usarla para volver a conectar un proceso en ejecución al terminal dentro de la pantalla para poder desconectarlo con seguridad y regresar más tarde.

Está empaquetado en distribuciones populares (por ejemplo, 'apt-get install reptyr').

http://onethingwell.org/post/2924103615/reptyr

2

Puede utilizar reredirect (https://github.com/jerome-pouiller/reredirect/).

Tipo

reredirect -m FILE PID 

y salidas (estándar y de error) se escribirá en el archivo.

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

Cuestiones relacionadas