Dire si un descripteur de fichier pointe vers un terminal
Un programme peut dire si un descripteur de fichier est associé à un périphérique tty en utilisant la isatty()fonction C standard (qui généralement fait en dessous un ioctl()appel système inoffensif spécifique au tty qui retournerait avec une erreur lorsque le fd ne pointe pas vers un périphérique tty) .
L' utilitaire [/ testpeut le faire avec son -topérateur.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Tracer les appels de la fonction libc sur un système GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Suivi des appels système:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Dire s'il pointe vers un tuyau
Pour déterminer si un fd est associé à un tube / fifo, on peut utiliser l' fstat()appel système , qui renvoie une structure dont le st_modechamp contient le type et les autorisations du fichier ouvert sur ce fd. La S_ISFIFO()macro C standard peut être utilisée sur ce st_modechamp pour déterminer si le fd est un tube / fifo.
Il n'y a aucun utilitaire standard qui peut faire un fstat(), mais il existe plusieurs implémentations incompatibles d'une statcommande qui peuvent le faire. zshest statintégré avec stat -sf "$fd" +modelequel retourne le mode comme une représentation sous forme de chaîne dont le premier caractère représente le type ( ppour pipe). GNU statpeut faire de même avec stat -c %A - <&"$fd", mais doit également stat -c %F - <&"$fd"signaler le type seul. Avec BSD stat: stat -f %St <&"$fd"ou stat -f %HT <&"$fd".
Dire si c'est recherchable
Les applications ne se soucient généralement pas si stdout est un tuyau. Ils peuvent se soucier qu'il soit recherché (bien que généralement ne pas décider de mettre en mémoire tampon ou non).
Pour tester si un fd est recherchable (les tuyaux, les sockets, les périphériques tty ne sont pas recherchés, les fichiers normaux et la plupart des périphériques de bloc le sont généralement), on peut tenter un lseek()appel système relatif avec un décalage de 0 (donc inoffensif). ddest un utilitaire standard qui lseek()sert d' interface, mais il ne peut pas être utilisé pour ce test, car les implémentations n'appelleraient pas lseek()du tout si vous demandez un décalage de 0.
Les zshet ksh93obus ont builtin recherche opérateurs si:
$ 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
Désactiver la mise en mémoire tampon
La scriptcommande utilise une paire pseudo-terminale pour capturer la sortie d'un programme, donc stdout (et stdin et stderr) du programme sera un périphérique pseudo-terminal.
Lorsque la sortie standard est vers un périphérique terminal, il y a encore généralement une mise en mémoire tampon, mais elle est basée sur la ligne. printf/ putset co n'écriront rien tant qu'un caractère de nouvelle ligne ne sera pas sorti. Pour les autres types de fichiers, la mise en mémoire tampon se fait par blocs (de quelques kilo-octets).
Il y a plusieurs options pour désactiver la mise en mémoire tampon qui sont décrits dans un certain nombre de questions et réponses ici (recherche unbuffer ou stdbuf , ne peut pas sortie coupée redirect donne quelques approches) soit en utilisant un pseudo-terminal peut être fait par socat/ script/ expect/ unbuffer(e expectscript) / zsh« s zptyou en injectant du code dans l'exécutable pour désactiver la mise en mémoire tampon comme effectuée par GNU ou de FreeBSD stdbuf.