tanto - ¿Cómo puede un proceso interceptar stdout y stderr de otro proceso en Linux?
stdin stdout stderr linux (8)
Tengo algunas secuencias de comandos que deberían haber dejado de funcionar, pero esperar por siempre.
¿Hay alguna manera de que pueda descubrir lo que están escribiendo en stdout y stderr de una manera legible?
Intenté, por ejemplo, hacer
tail -f /proc/(pid)/fd/1
pero eso realmente no funciona. De todos modos, era una posibilidad remota.
¿Alguna otra idea? Por sí solo es bastante detallado e ilegible para ver esto.
Nota: solo me interesa su salida, no en otra cosa. Soy capaz de descubrir las otras cosas por mi cuenta; esta pregunta solo se enfoca en obtener acceso a stdout y stderr del proceso en ejecución después de iniciarlo.
Como no puedo 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.
Por lo tanto, ejecute un script simple e infinito como este:
import time
while True:
print ''test''
time.sleep(1)
Guárdalo en test.py, ejecuta con
python test.py
Obtener el pid:
ps auxw | grep test.py
Ahora, adjunte gdb:
gdb -p (pid)
y haz la magia fd:
(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1
Ahora puede tail / tmp / stdout y ver la salida que solía ir a stdout.
El método Gdb parece mejor, pero también puedes hacerlo con strace:
strace -p -e write = 1 -s archivo 1024 -o
-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 imprime algo más de lo que necesita (la parte hexadecimal), pero puede extraerlo fácilmente.
Hay varias utilidades nuevas que envuelven el "método gdb" y agregan 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).
El mejor uso de esto 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 que pueda desconectarse de manera segura y regresar más tarde.
Está empaquetado en distros populares (por ejemplo, ''apt-get install reptyr'').
No declaras tu sistema operativo, pero voy a apuñalar 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 haga que descargue el núcleo, y luego use el depurador y el archivo central para obtener un seguimiento de la pila.
No estoy seguro si funcionará para usted, pero leí una página hace un tiempo describiendo un método que usa gdb
Puede usar 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.
Strace produce mucho menos con solo -ewrite (y no con el sufijo = 1). Y es un poco más simple que el método gdb, imo.
Lo usé para ver el progreso de un trabajo de codificación MythTV existente (sudo porque no poseo el 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
Usé strace y codifiqué la salida hexadecimal para borrar el 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.