2010-01-13 4 views
9

Ho un programma di origine chiuso che stampa l'output sullo standard output. ho bisogno di analizzare l'output. quindi reindirizzo l'output a un fifo (dal quale posso leggere il processo genitore che forca ed esegue il binario) usando dup2 e poi eseguo il programma. il problema è che le chiamate fprintf nel file vengono bufferizzate perché ora sta scrivendo su un file.forzare un programma per svuotare l'output standard quando viene reindirizzato

ho provato a chiamare setvbuf con _IONBF su stdout prima di chiamare exec. ma il problema esiste ancora.

perché setvbuf non è di aiuto nel mio caso?

come posso forzare l'uscita a essere scaricata?

risposta

5

setvbuf() non fa alcuna differenza perché cambia lo stato della parte della libreria di runtime C, non parte del sistema operativo. Quando il nuovo processo inizia a funzionare, la sua libreria runtime C verrà reinizializzata (ovvero se usa un CRT!)

L'unico modo per cui ho sentito parlare di questo è in qualche modo un terminale falso al processo. Questo perché la maggior parte delle librerie CRT eseguirà automaticamente solo il buffering di linea se ritengono di essere collegate a un terminale interattivo (nel mondo Unix: se isatty() restituisce true nel descrittore di file), mentre altrimenti bufferizzeranno in blocchi più grandi (in genere 8 KB o così).

This utility sembra un buon punto di partenza. (Preso in prestito da un commento su Trick an application into thinking its stdin is interactive, not a pipe, che ha altre informazioni utili.)

+0

il fork un processo, chiamare setvbuf nel processo figlio e poi exec uno script shell che exec altro script che finalmente exec binario. posso cambiare il comando exec finale (bash) in modo che disabiliti il ​​buffering in qualche modo. –

+1

Ripeto, è inutile chiamare setvbuf() prima dell'esecuzione - nessuno dello stato della libreria di runtime C è conservato su exec()! Il processo finale che esegui() potrebbe anche non * usare * il CRT! (Improbabile ma possibile.) –

+0

ok sto provando l'approccio pty vedere http://stackoverflow.com/questions/2056858/cannot-write-to-pty-linux –

2

Credo di avere qualcosa di simile nel vostro programma (è possibile riprodurre questo per i test, sto chiamando isatty qui)

#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); 
} 

per esempio, se lo si esegue

$ ./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 

Ora, se si crea un expect script di isatty.expect (installare expect per la vostra distribuzione, se non installato)

#! /usr/bin/expect -f 

spawn "./isatty" 
expect 

ed eseguirlo

$ ./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

Lo strumento unbuffer può aiutare con questo problema:

E 'parte del expect-dev e può essere installato in Ubuntu utilizzando

sudo apt-get install expect-dev 

per usarlo tipo:

unbuffer ls > log.txt