2010-01-13 7 views
9

tengo un programa de fuente cerrada que imprime la salida a la salida estándar. necesito analizar la salida. así que redirijo la salida a una fifo (desde la cual puedo leer en el proceso padre que bifurca y ejecuta el binario) usando dup2 y luego ejecuté el programa. el problema es que las llamadas fprintf en el archivo se almacenan en búfer porque ahora está escribiendo en un archivo.forzando a un programa a purgar su salida estándar cuando se redirige

intenté llamar a setvbuf con _IONBF en stdout antes de llamar a exec. pero el problema todavía existe

¿por qué no funciona el setvbuf en mi caso?

¿Cómo puedo forzar la salida para que se vacíe?

Respuesta

5

setvbuf() no hace ninguna diferencia porque cambia el estado de una parte de la biblioteca C runtime, no es parte del sistema operativo. Cuando el nuevo proceso comience a ejecutarse, su biblioteca C runtime se reinicializará (¡eso es si usa un CRT!)

La única forma en que he oído hablar para evitar esto es de alguna manera falsificar un terminal al proceso. Esto se debe a que la mayoría de las bibliotecas CRT realizarán solo buffering de línea si creen que están conectadas a un terminal interactivo (en el mundo Unix: si isatty() devuelve verdadero en el descriptor de archivo), de lo contrario almacenarán en bloques más grandes (típicamente 8Kb o asi que).

This utility parece un muy buen lugar para comenzar. (Tomado de un comentario en Trick an application into thinking its stdin is interactive, not a pipe, que tiene otra información útil.)

+0

i tenedor a cabo un proceso, llame setvbuf en el proceso de niño y luego exec una secuencia de comandos shell que los ejecutivos otro script que finalmente ejecutivos de TI el binario. ¿Puedo cambiar el comando ejecutivo final (bash) para que deshabilite el almacenamiento en búfer de alguna manera? –

+1

Repito, es inútil llamar a setvbuf() antes de la ejecución: ¡ninguno de los estados de la biblioteca C runtime se conserva en exec()! ¡El proceso final en el que exec() ni siquiera * usa * el CRT! (Improbable pero posible.) –

+0

bien, estoy probando el enfoque pty ver http://stackoverflow.com/questions/2056858/cannot-write-to-pty-linux –

2

supongo que hay algo como esto en su programa (se puede reproducir este para sus pruebas, yo estoy llamando isatty aquí)

#include <stdio.h> 
#include <unistd.h> 

const char* m1 = "%d: %s a TTY\n"; 

void isTty(FILE* f) { 
    int fno = fileno(f); 
    printf(m1, fno, (isatty(fno)) ? "is" : "is NOT"); 
} 

int main(int argc, char* argv[]) { 
    isTty(stdin); 
    isTty(stdout); 
} 

por ejemplo, si se ejecuta

$ ./isatty 
0: is a TTY 
1: is a TTY 

$ ./isatty > isatty.out 
$ cat isatty.out 
0: is a TTY 
1: is NOT a TTY 

$ ./isatty > isatty.out < /dev/null 
$ cat isatty.out 
0: is NOT a TTY 
1: is NOT a TTY 

Ahora bien, si se crea una secuencia de comandos expectisatty.expect (expect instalar para su distribución si no se instala)

#! /usr/bin/expect -f 

spawn "./isatty" 
expect 

y ejecutarlo

$ ./isatty.expect 
spawn ./isatty 
0: is a TTY 
1: is a TTY 

o

$ ./isatty.expect > isatty.out 
$ cat isatty.out 
spawn ./isatty 
0: is a TTY 
1: is a TTY 
2

La herramienta unbuffer puede ayudar con este problema:

Es parte de la expect-dev y se puede instalar en Ubuntu utilizando

sudo apt-get install expect-dev 

de usar que escriba:

unbuffer ls > log.txt 
Cuestiones relacionadas