2013-02-04 9 views
7

Voglio eseguire l'output di un programma tramite una pipe, ma apparentemente si comporta in modo diverso quando rileva che stdout non è una shell interattiva.Bash: programma di trucco in stdout di pensiero è un terminale interattivo

Come posso ingannarlo per scrivere attraverso la pipa proprio come farebbe in circostanze normali?

+1

ho sentito ' expect' è un buon programma per farlo – BeniBela

+0

Controlla anche il programma 'script' per quello scopo: http://stackoverflow.com/a/1402389/516188 –

risposta

12

Suppongo che il programma chiamerà la funzione glibc isatty() per verificare se stdout è un terminale o meno. Questo è comune per i programmi che utilizzano l'output colorato sui terminali o altre funzionalità di un terminale ANSI come il posizionamento del cursore o la cancellazione/ridisegno della linea.

È possibile ingannare il programma utilizzando la variabile di ambiente LD_PRELOAD. LD_PRELOAD è gestito dal linker ELF e indica che una libreria dinamica deve essere caricata prima di tutti gli altri. Usando questa funzione è possibile sovrascrivere le funzioni della libreria, nel tuo caso la funzione glibc isatty(). È possibile seguire questo article per esempio.

ho preparato un esempio per voi:

Innanzitutto creare il file libisatty.c:

/** 
* Overrides the glibc function. Will always return true. 
* 
* Note: Although this should be ok for most applications it can 
* lead to unwanted side effects. It depends on the question 
* why the programm calls isatty() 
*/ 
int isatty(int param) { 
    return 1; 
} 

e compilare come un lib comune:

gcc -shared -o libisatty.so libisatty.c 

E ' dovrebbe costruire bene.

Ora è il momento di testare la libreria. :) Ho usato il comando ls --color=auto per i test. ls chiama isatty() per decidere se colorarlo o meno. Se l'output viene reindirizzato a un file o a una pipe, non verrà colorato. È possibile verificare questo facilmente utilizzando i seguenti comandi:

ls --color=auto  # should give you colorized output 
ls --color=auto | cat # will give you monochrome output 

Ora cercheremo il secondo comando ancora una volta utilizzando l'ambiente LD_PRELOAD var:

LD_PRELOAD=./libisatty.so ls --color=auto | cat 

Dovreste visualizzare un output colorato.

btw fresco usename: uʍop ǝpısdn !!: D

+1

Solo ... wow! Risposta fantastica! – slezica

+0

Attenzione: creare una funzione di shell che faccia questo trucco 'LD_PRELOAD' non funzioni, dato che apparentemente altre cose sono altre differenze osservabili nella funzione di shell (non sono sicuro di cosa siano). Tuttavia, creando un alias 'trick_tty' con' alias trick_tty = "LD_PRELOAD = /libisatty.so" 'e quindi facendo' trick_tty | meno' funziona. – ntc2

+1

Per gli utenti MacOS, puoi fare la stessa cosa ma invece di impostare LD_PRELOAD, devi impostare DYLD_INSERT_LIBRARIES e DYLD_FORCE_FLAT_NAMESPACE, come segue: 'DYLD_INSERT_LIBRARIES =./Libisatty.so DYLD_FORCE_FLAT_NAMESPACE = y ls -G | cat' (nota che la flag --color non funziona su ls di mac) –

0

Si consiglia di provare questo:

./script.sh < `tty` > output 

Se il programma sta facendo qualcosa di simile isatty(0), questo può essere sufficiente.

+3

Nota che il programma in questio n eseguirà isatty() su stdout. Conduci il terminale allo stdin.Questo non risolverà il problema – hek2mgl

+0

In realtà potrebbe testare stdin e non stdout – arnaud576875

+1

Questo non ha senso. – hek2mgl

2

Utilizzando script opere per me:

script outputfile.txt yourcommand 
# any output ends up in outputfile.txt 

si potrebbe usare questo per tubo immagino:

script out.txt yourcommand ; cat out.txt | nextcommand 
+0

Esaminare il codice sorgente di 'script' dovrebbe rivelare quali altre cose, oltre a' isatty', sono usate dai programmi per capire se sono in esecuzione in modo interattivo. – ntc2

Problemi correlati