Indicar si un descriptor de archivo apunta a un dispositivo terminal
Un programa puede determinar si un descriptor de archivo está asociado con un dispositivo tty mediante el uso de la isatty()
función C estándar (que generalmente hace una ioctl()
llamada de sistema específica de tty inocua que volvería con un error cuando el fd no apunta a un dispositivo tty) .
La utilidad [
/ test
puede hacerlo con su -t
operador.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Seguimiento de llamadas de función libc en un sistema GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Sistema de rastreo de llamadas:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Decir si apunta a una tubería
Para determinar si un fd está asociado con un pipe / fifo, se puede usar la fstat()
llamada al sistema , que devuelve una estructura cuyo st_mode
campo contiene el tipo y los permisos del archivo abierto en ese fd. La S_ISFIFO()
macro C estándar se puede usar en ese st_mode
campo para determinar si el fd es una tubería / quince.
No hay una utilidad estándar que pueda hacer un fstat()
, pero hay varias implementaciones incompatibles de un stat
comando que puede hacerlo. zsh
's stat
incorporado con el stat -sf "$fd" +mode
que devuelve el modo como una representación de cadena cuyo primer carácter representa el tipo ( p
para tubería). GNU stat
puede hacer lo mismo con stat -c %A - <&"$fd"
, pero también tiene stat -c %F - <&"$fd"
que informar el tipo solo. Con BSD stat
: stat -f %St <&"$fd"
o stat -f %HT <&"$fd"
.
Diciendo si es buscable
Sin embargo, a las aplicaciones generalmente no les importa si stdout es una tubería. Puede que les importe que sea buscable (aunque generalmente no para decidir si usar un búfer o no).
Para probar si un fd es buscable (las tuberías, los enchufes, los dispositivos tty no son buscables, los archivos normales y la mayoría de los dispositivos de bloque generalmente lo son), se puede intentar una lseek()
llamada relativa al sistema con un desplazamiento de 0 (tan inocuo). dd
es una utilidad estándar que es una interfaz lseek()
pero no se puede usar para esa prueba, ya que las implementaciones no llamarían lseek()
en absoluto si solicita un desplazamiento de 0.
Sin embargo, los proyectiles zsh
y ksh93
tienen operadores de búsqueda incorporados:
$ 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
Deshabilitar el almacenamiento en búfer
El script
comando utiliza un par pseudo-terminal para capturar la salida de un programa, por lo que stdout (y stdin y stderr) del programa será un dispositivo pseudo-terminal.
Cuando la salida estándar es para un dispositivo terminal, generalmente todavía hay algo de almacenamiento en búfer, pero se basa en líneas. printf
/ puts
y co no escribirán nada hasta que salga un carácter de nueva línea. Para otros tipos de archivos, el almacenamiento en búfer es por bloques (de unos pocos kilobytes).
Hay varias opciones para desactivar el almacenamiento en búfer que se discuten en una serie de Q & A aquí (búsqueda de unbuffer o stdbuf , No se puede redirigir la salida de corte da algunos enfoques), ya sea mediante el uso de una pseudo-terminal como se puede hacer por socat
/ script
/ expect
/ unbuffer
(un expect
script) / zsh
's zpty
o inyectando código en el ejecutable para deshabilitar el almacenamiento en búfer como lo hacen GNU o FreeBSD stdbuf
.