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 [
/ test
peut le faire avec son -t
opé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_mode
champ 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_mode
champ 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 stat
commande qui peuvent le faire. zsh
est stat
intégré avec stat -sf "$fd" +mode
lequel retourne le mode comme une représentation sous forme de chaîne dont le premier caractère représente le type ( p
pour pipe). GNU stat
peut 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). dd
est 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 zsh
et ksh93
obus 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 script
commande 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
/ puts
et 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 expect
script) / zsh
« s zpty
ou 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
.