Tengo problemas para depurar un programa de segfaulting porque lo que necesito es la salida justo antes de la segfault, pero esto se pierde si estoy canalizando la salida a un archivo. De acuerdo con esta respuesta: /unix//a/17339/22615 , esto se debe a que el búfer de salida del programa se lava inmediatamente cuando se conecta a un terminal, pero solo en ciertos puntos cuando se conecta a una tubería. Algunas preguntas aquí:
¿Cómo determina un programa a qué está conectado su stdout?
¿Cómo produce el comando "script" el mismo comportamiento que cuando el programa escribe en un terminal?
¿Se puede lograr esto sin el comando de script?
Respuestas:
Indicar si un descriptor de archivo apunta a un dispositivo terminal
Un programa puede determinar si un descriptor de archivo está asociado con un dispositivo tty mediante el uso de la
isatty()
función C estándar (que generalmente hace unaioctl()
llamada de sistema específica de tty inocua que volvería con un error cuando el fd no apunta a un dispositivo tty) .La utilidad
[
/test
puede hacerlo con su-t
operador.Seguimiento de llamadas de función libc en un sistema GNU / Linux:
Sistema de rastreo de llamadas:
Decir si apunta a una tubería
Para determinar si un fd está asociado con un pipe / fifo, se puede usar la
fstat()
llamada al sistema , que devuelve una estructura cuyost_mode
campo contiene el tipo y los permisos del archivo abierto en ese fd. LaS_ISFIFO()
macro C estándar se puede usar en esest_mode
campo para determinar si el fd es una tubería / quince.No hay una utilidad estándar que pueda hacer un
fstat()
, pero hay varias implementaciones incompatibles de unstat
comando que puede hacerlo.zsh
'sstat
incorporado con elstat -sf "$fd" +mode
que devuelve el modo como una representación de cadena cuyo primer carácter representa el tipo (p
para tubería). GNUstat
puede hacer lo mismo constat -c %A - <&"$fd"
, pero también tienestat -c %F - <&"$fd"
que informar el tipo solo. Con BSDstat
:stat -f %St <&"$fd"
ostat -f %HT <&"$fd"
.Diciendo si es buscable
Sin embargo, a las aplicaciones generalmente no les importa si stdout es una tubería. Puede que les importe que sea buscable (aunque generalmente no para decidir si usar un búfer o no).
Para probar si un fd es buscable (las tuberías, los enchufes, los dispositivos tty no son buscables, los archivos normales y la mayoría de los dispositivos de bloque generalmente lo son), se puede intentar una
lseek()
llamada relativa al sistema con un desplazamiento de 0 (tan inocuo).dd
es una utilidad estándar que es una interfazlseek()
pero no se puede usar para esa prueba, ya que las implementaciones no llamaríanlseek()
en absoluto si solicita un desplazamiento de 0.Sin embargo, los proyectiles
zsh
yksh93
tienen operadores de búsqueda incorporados:Deshabilitar el almacenamiento en búfer
El
script
comando utiliza un par pseudo-terminal para capturar la salida de un programa, por lo que stdout (y stdin y stderr) del programa será un dispositivo pseudo-terminal.Cuando la salida estándar es para un dispositivo terminal, generalmente todavía hay algo de almacenamiento en búfer, pero se basa en líneas.
printf
/puts
y co no escribirán nada hasta que salga un carácter de nueva línea. Para otros tipos de archivos, el almacenamiento en búfer es por bloques (de unos pocos kilobytes).Hay varias opciones para desactivar el almacenamiento en búfer que se discuten en una serie de Q & A aquí (búsqueda de unbuffer o stdbuf , No se puede redirigir la salida de corte da algunos enfoques), ya sea mediante el uso de una pseudo-terminal como se puede hacer por
socat
/script
/expect
/unbuffer
(unexpect
script) /zsh
'szpty
o inyectando código en el ejecutable para deshabilitar el almacenamiento en búfer como lo hacen GNU o FreeBSDstdbuf
.fuente
/proc
directorio y para cada/proc/<integer>/
directorio buscar/proc/<integer>/fd/
y encontrar un descriptor de archivo que tenga el mismo número de inodo enpipefs
serverfault.com/q/48330/363611 Sin embargo, eso solo es útil en los scripts cuando no se pueden usar los syscalls descritos en la respuesta de Stephane, y es más una solución que una solución adecuada en mi humilde opiniónlseek
tendrá éxito en terminales y otros dispositivos de caracteres, y simplemente re / establecerá un contador que se incrementa en cada lectura exitosa (). No sé si esto los hace "buscables".