Mówienie, jeśli deskryptor pliku wskazuje urządzenie końcowe
Program może stwierdzić, czy deskryptor pliku jest powiązany z urządzeniem tty, używając isatty()standardowej funkcji C (która ogólnie poniżej wykonuje niewinne ioctl()wywołanie systemowe specyficzne dla tty , które zwróci błąd z błędem, gdy fd nie wskaże urządzenia tty) .
Narzędzie [/ testmoże to zrobić za pomocą swojego -toperatora.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Śledzenie wywołań funkcji libc w systemie GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Śledzenie wywołań systemowych:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Mówienie, jeśli wskazuje na rurę
Aby ustalić, czy fd jest powiązany z potokiem / fifo, można użyć fstat()wywołania systemowego , które zwraca strukturę, której st_modepole zawiera typ i uprawnienia pliku otwartego na tym fd. W tym polu można użyć S_ISFIFO()standardowego makra C , st_modeaby ustalić, czy fd jest potokiem / fifo.
Nie ma standardowego narzędzia, które mogłoby to zrobić fstat(), ale istnieje kilka niekompatybilnych implementacji statpolecenia, które może to zrobić. zshjest statwbudowany w stat -sf "$fd" +modektóre powraca do trybu jako ciąg znaków, który pierwszy znak oznacza rodzaj ( pna rurę). GNU statmoże zrobić to samo stat -c %A - <&"$fd", ale musi również stat -c %F - <&"$fd"zgłosić ten typ sam. Z BSD stat: stat -f %St <&"$fd"lub stat -f %HT <&"$fd".
Mówienie, jeśli to możliwe
Aplikacje na ogół nie dbają o to, czy stdout jest fajką. Mogą się martwić, że jest to widoczne (choć ogólnie nie decyduje się na buforowanie, czy nie).
Aby sprawdzić, czy można zobaczyć fd (potoki, gniazda, urządzenia tty nie są widoczne, zwykłe pliki i większość urządzeń blokowych ogólnie jest), można spróbować wykonać względne lseek()wywołanie systemowe z przesunięciem 0 (tak nieszkodliwe). ddjest standardowym narzędziem, które jest interfejsem, lseek()ale nie można go użyć do tego testu, ponieważ implementacje nie zadzwoniłyby lseek()wcale, jeśli poprosiłbyś o przesunięcie 0.
Te zshi ksh93powłok posiada wbudowane poszukuje operatorów choć:
$ 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
Wyłączanie buforowania
scriptRozkaz wykorzystuje parę Pseudoterminal uchwycić wyjście programu, tak standardowe wyjście programu (i standardowe wejście i stderr) będzie urządzenie pseudoterminal.
Kiedy standardowe wyjście znajduje się na urządzeniu końcowym, nadal istnieje ogólne buforowanie, ale jest ono oparte na linii. printf/ putsi co nie napisze nic, dopóki nie zostanie wypisany znak nowej linii. W przypadku innych typów plików buforowanie odbywa się według bloków (o wielkości kilku kilogramów).
Istnieje kilka opcji, aby wyłączyć buforowanie, które zostały omówione w szeregu pytań i jak tutaj (szukaj unbuffer lub stdbuf , Nie można przekierować dane wyjściowe cięcie daje kilka podejść) albo za pomocą pseudo-terminal, jak można to zrobić przez socat/ script/ expect/ unbuffer( expectskrypt) / zsh” zptylub przez wstrzyknięcie kodu do pliku wykonywalnego, aby wyłączyć buforowanie, tak jak zrobiono to w GNU lub FreeBSD stdbuf.