Dire se un descrittore di file punta a un dispositivo terminale
Un programma può dire se un descrittore di file è associato a un dispositivo tty usando la isatty()funzione C standard (che generalmente sotto fa una ioctl()chiamata di sistema specifica tty innocua che ritornerebbe con un errore quando il fd non punta a un dispositivo tty) .
L' utilità [/ testpuò farlo con il suo -toperatore.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Tracciare le chiamate della funzione libc su un sistema GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Traccia delle chiamate di sistema:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Dire se indica una pipa
Per determinare se un fd è associato a una pipe / fifo, è possibile utilizzare la fstat()chiamata di sistema , che restituisce una struttura il cui st_modecampo contiene il tipo e le autorizzazioni del file aperto su quel fd. La S_ISFIFO()macro C standard può essere utilizzata su quel st_modecampo per determinare se fd è una pipe / fifo.
Non esiste un'utilità standard in grado di eseguire una fstat(), ma ci sono diverse implementazioni incompatibili di un statcomando che può farlo. zshÈ statincorporato con il stat -sf "$fd" +modequale restituisce la modalità come rappresentazione di stringa il cui primo carattere rappresenta il tipo ( pper pipe). GNU statpuò fare lo stesso con stat -c %A - <&"$fd", ma deve anche stat -c %F - <&"$fd"riportare il tipo da solo. Con BSD stat: stat -f %St <&"$fd"o stat -f %HT <&"$fd".
Dire se è cercabile
In genere, alle applicazioni non importa se stdout è una pipe. A loro potrebbe interessare che sia cercabile (anche se generalmente non decidere se tamponare o meno).
Per verificare se un fd è ricercabile (pipe, socket, dispositivi tty non sono ricercabili, file regolari e la maggior parte dei dispositivi a blocchi lo sono in genere), si può tentare una lseek()chiamata di sistema relativa con un offset di 0 (così innocuo). ddè un'utilità standard che è un'interfaccia per lseek()ma non può essere utilizzata per quel test, poiché le implementazioni non chiamerebbero lseek()affatto se si chiedesse un offset di 0.
Le shell zshe ksh93hanno incorporato gli operatori alla ricerca di:
$ strace -e lseek ksh -c ': 1>#((CUR))' | cat
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
ksh: 1: not seekable
$ strace -e lseek zsh -c 'zmodload zsh/system; sysseek -w current -u 1 0 || syserror'
lseek(1, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
Illegal seek
Disabilitare il buffering
Il scriptcomando usa una coppia pseudo-terminale per catturare l'output di un programma, quindi lo stdout del programma (e stdin e stderr) sarà un dispositivo pseudo-terminale.
Quando lo stdout è su un dispositivo terminale, generalmente c'è ancora un po 'di buffering, ma è basato sulla linea. printf/ putse co non scriveranno nulla fino a quando non verrà emesso un carattere di nuova riga. Per altri tipi di file, il buffering è per blocchi (di qualche chilo byte).
Esistono diverse opzioni per disabilitare il buffering che sono discusse in un certo numero di domande e risposte qui (cercare unbuffer o stdbuf , Impossibile reindirizzare l'output di taglio fornisce alcuni approcci) utilizzando uno pseudo-terminale come può essere fatto da socat/ script/ expect/ unbuffer(uno expectscript) / zsh' zptyo iniettando codice nell'eseguibile per disabilitare il buffering come fatto da GNU o FreeBSD stdbuf.