Скажіть, чи дескриптор файлу вказує на термінальний пристрій
Програма може визначити, чи пов'язаний дескриптор файлу з пристроєм tty за допомогою isatty()стандартної функції C (яка, як правило, під ним виконує нешкідливий ioctl()системний виклик, який відповідає tty, який би повертався з помилкою, коли fd не вказує на tty пристрій) .
[/ testУтиліта може зробити це з -tоператором.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Відстеження функцій libc у системі GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Система відстеження викликів:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Скажіть, чи вказує він на трубу
Щоб визначити, чи пов'язаний fd з pipe / fifo, можна скористатися fstat()системним викликом , який повертає структуру, st_modeполе якої містить тип і дозволи файлу, відкритого на цьому fd. S_ISFIFO()Стандарт Сі макро може бути використано на цій st_modeобласті , щоб визначити , є чи ФД труба / FIFO.
Немає стандартної утиліти, яка може виконати fstat(), але є кілька несумісних реалізацій statкоманди, яка може це зробити. zsh's statвбудований, з stat -sf "$fd" +modeяким повертає режим у вигляді рядкового подання, перший символ якого представляє тип ( pдля труби). GNU statможе зробити те ж саме stat -c %A - <&"$fd", але також stat -c %F - <&"$fd"повинен повідомити про тип окремо. З BSD stat: stat -f %St <&"$fd"або stat -f %HT <&"$fd".
Скажіть, якщо це можна знайти
Зазвичай програми не хвилюються, якщо stdout - це труба. Вони можуть піклуватися про те, що це можна шукати (хоча, як правило, не вирішувати, чи буферне чи ні).
Щоб перевірити, чи можна шукати fd (труби, розетки, tty пристрої не шукаються, звичайні файли та більшість блокових пристроїв, як правило), можна спробувати відносний lseek()системний виклик зі зміщенням 0 (настільки нешкідливим). dd- це стандартна утиліта, яка є інтерфейсом, lseek()але її не можна використовувати для цього тесту, оскільки впровадження взагалі не закликає, lseek()якщо ви попросите зміщення 0.
В zshі ksh93оболонки мають вбудований пошук операторів , хоча:
$ 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
Вимкнення буферизації
scriptКоманда використовує псевдо-термінал пару , щоб захопити висновок програми, так що стандартний висновок програми (і STDIN і STDERR) буде псевдо-термінальне пристрій.
Коли stdout призначений для термінального пристрою, як правило, існує деяка буферизація, але це лінійна основа. printf/ putsі co не запише нічого, поки не буде виведений символ нового рядка. Для інших типів файлів буферизація здійснюється блоками (у кілька кілобайт).
Є кілька варіантів , щоб відключити буферизацію , які обговорюються в ряді Q & As тут (пошук unbuffer або stdbuf , Може не перенаправлення висновок крою дає кілька підходів) , або за допомогою псевдо-терміналу , як можна зробити socat/ script/ expect/ unbuffer( expectскрипт) / zsh' zptyабо шляхом введення коду у виконуваний файл, щоб відключити буферизацію, як це зроблено GNU або FreeBSD stdbuf.