GNU/Linux >> Tutoriales Linux >  >> Linux

Forzar el vaciado del búfer de salida en el programa en ejecución

SI uno realmente quería esos datos, sugeriría adjuntar el gdb depurador al intérprete de python, deteniendo momentáneamente la tarea, llamando a fsync(1) (salida estándar ), sepárelo (reanudando el proceso) y examine el archivo de salida.

Mira en /proc/$(pidof python)/fd para ver los descriptores de archivo válidos. $(pidof x) devuelve el PID del proceso llamado 'x '.

# your python script is running merrily over there.... with some PID you've determined.
#
# load gdb
gdb
#
# attach to python interpreter (use the number returned by $(pidof python))
attach 1234
#
# force a sync within the program's world (1 = stdout, which is redirected in your example)
call fsync(1)
#
# the call SHOULD have returned 0x0, sync successful.   If you get 0xffffffff (-1), perhaps that wasn't stdout.  0=stdin, 1=stdout, 2=stderr
#
# remove our claws from poor python
detach
#
# we're done!
quit

He usado este método para cambiar los directorios de trabajo, ajustar la configuración sobre la marcha... muchas cosas. Por desgracia, solo puede llamar a funciones que están definidas en el programa en ejecución, fsync aunque funciona bien.

(comando gdb 'info functions ' mostrará una lista de todas las funciones disponibles. Sin embargo, ten cuidado. Estás operando EN VIVO en un proceso).

También existe el comando peekfd (encontrado en psmisc paquete en Debian Jessie y otros) que le permitirá ver lo que se esconde en los búferes de un proceso. De nuevo, /proc/$(pidof python)/fd le mostrará descriptores de archivo válidos para dar como argumentos a peekfd.

Si no recuerda -u para python, siempre puede anteponer un comando con stdbuf (en coreutils , ya instalado) para establecer stdin/stdout/stderr en sin búfer, con búfer de línea o con búfer de bloque, según se desee:

stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output

Por supuesto, man pages son tus amigos, hey! quizás un alias podría ser útil aquí también.

alias python='python -u'

Ahora tu python siempre usa -u para todos sus esfuerzos de línea de comandos!


Primero asegúrese de tener los símbolos de depuración para Python (o al menos glibc). En Fedora puede instalarlos con:

dnf debuginfo-install python

Luego adjunte gdb al script en ejecución y ejecute los siguientes comandos:

[[email protected] ~]$ pidof python2
9219
[[email protected] ~]$ gdb python2 9219
GNU gdb (GDB) Fedora 7.7.1-13.fc20
...
0x00007fa934278780 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81  T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) call fflush(stdout)
$1 = 0
(gdb) call setvbuf(stdout, 0, 2, 0)
$2 = 0
(gdb) quit
A debugging session is active.

    Inferior 1 [process 9219] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2, process 9219

Esto vaciará stdout y también desactivar el almacenamiento en búfer. El 2 del setvbuf call es el valor de _IONBF en mi sistema Deberá averiguar qué hay en el suyo (un grep _IONBF /usr/include/stdio.h debería hacer el truco).

Basado en lo que he visto en la implementación de PyFile_SetBufSize y PyFile_WriteString en CPython 2.7, debería funcionar bastante bien, pero no puedo garantizar nada.


No hay solución a su problema inmediato. Si su secuencia de comandos ya comenzó, no puede cambiar el modo de almacenamiento en búfer después del hecho. Todos estos son búferes en memoria y todo eso se configura cuando se inicia el script, se abren los identificadores de archivos, se crean conductos, etc.

Como posibilidad remota, si y solo si parte o la totalidad del almacenamiento en búfer en cuestión se realiza en el nivel de IO en la salida, podría hacer un sync dominio; pero esto es generalmente poco probable en un caso como este.

En el futuro, puede usar -u de Python opción para ejecutar el script. En general, muchos comandos tienen opciones específicas de comando para deshabilitar el almacenamiento en búfer de stdin/stdout, y también puede tener cierto éxito genérico con el unbuffer comando desde el expect paquete.

Un Ctrl +C haría que los búferes a nivel del sistema se vaciaran cuando el programa se interrumpa a menos que el almacenamiento en búfer lo realiza Python mismo y no ha implementado la lógica para vaciar sus propios búferes con Ctrl +C . Una suspensión, bloqueo o eliminación no sería tan amable.

Obligar a stdin, stdout y stderr a estar totalmente sin búfer.


Linux
  1. ¿Cerrar la salida estándar (>&-)?

  2. ¿Cómo hacer nada para siempre de una manera elegante?

  3. redirección de salida sobre la marcha, viendo la salida de redirección de archivos mientras el programa aún se está ejecutando

  4. Ejecutando un comando de linux desde python

  5. pytest ejecutándose con otra versión de python

¿Puede Python detectar con qué sistema operativo se está ejecutando?

Salida de color del programa ejecutado bajo BASH

Programa de Python consumiendo RAM

Ejecutar un script de Python desde PHP

Determinar si la salida es stdout o stderr

Aumente el tamaño del búfer mientras ejecuta la pantalla