Angeben, ob ein Dateideskriptor auf ein Endgerät verweist
Ein Programm kann mithilfe der isatty()
Standard-C-Funktion feststellen, ob einem tty-Gerät ein Dateideskriptor zugeordnet ist (darunter befindet sich im Allgemeinen ein harmloser tty-spezifischer ioctl()
Systemaufruf, der mit einem Fehler zurückgegeben würde, wenn der fd nicht auf ein tty-Gerät verweist). .
Das Dienstprogramm [
/ test
kann dies mit seinem -t
Operator tun .
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Libc-Funktionsaufrufe auf einem GNU / Linux-System verfolgen:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Systemaufrufe verfolgen:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Sagen, ob es auf eine Pfeife zeigt
Um festzustellen, ob ein fd mit einer Pipe / einem fifo verknüpft ist, können Sie den fstat()
Systemaufruf verwenden , der eine Struktur zurückgibt, deren st_mode
Feld den Typ und die Berechtigungen der auf diesem fd geöffneten Datei enthält. Das S_ISFIFO()
Standard-C-Makro kann in diesem st_mode
Feld verwendet werden, um zu bestimmen, ob es sich bei dem FD um eine Pipe / FIFO handelt.
Es gibt kein Standarddienstprogramm, das a ausführen kann fstat()
, aber es gibt mehrere inkompatible Implementierungen eines stat
Befehls, die dies ausführen können. zsh
's stat
builtin, mit stat -sf "$fd" +mode
dem der Modus als Zeichenfolgendarstellung zurückgegeben wird, deren erstes Zeichen den Typ darstellt ( p
für Pipe). GNU stat
kann dasselbe tun stat -c %A - <&"$fd"
, muss aber auch stat -c %F - <&"$fd"
den Typ alleine melden . Mit BSD stat
: stat -f %St <&"$fd"
oder stat -f %HT <&"$fd"
.
Sagen, ob es suchbar ist
Anwendungen interessieren sich im Allgemeinen nicht dafür, ob stdout eine Pipe ist. Sie können sich darum kümmern, dass es suchbar ist (obwohl sie im Allgemeinen nicht entscheiden, ob sie puffern wollen oder nicht).
Um zu testen, ob ein fd suchbar ist (Pipes, Sockets, tty-Geräte sind nicht suchbar, reguläre Dateien und die meisten Blockgeräte im Allgemeinen), kann ein relativer lseek()
Systemaufruf mit einem Offset von 0 (also harmlos) versucht werden . dd
ist ein Standarddienstprogramm, zu dem eine Schnittstelle gehört, das lseek()
jedoch für diesen Test nicht verwendet werden kann, da Implementierungen überhaupt nicht aufgerufen würden, lseek()
wenn Sie nach einem Offset von 0 fragen.
Die zsh
und ksh93
Shells haben jedoch nach Operatoren gesucht:
$ 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
Pufferung deaktivieren
Der script
Befehl verwendet ein Pseudo-Terminal-Paar, um die Ausgabe eines Programms zu erfassen, sodass das stdout (und stdin und stderr) des Programms ein Pseudo-Terminal-Gerät ist.
Wenn sich die Standardausgabe auf ein Endgerät bezieht, ist im Allgemeinen noch eine gewisse Pufferung vorhanden, die jedoch zeilenbasiert ist. printf
/ puts
und co schreiben erst etwas, wenn ein Zeilenumbruch ausgegeben werden soll. Bei anderen Dateitypen erfolgt die Pufferung in Blöcken (von wenigen Kilobytes).
Es gibt mehrere Optionen , um die Pufferung zu deaktivieren , die in einer Reihe von Fragen und Antworten hier diskutiert werden (Suche nach unbuffer oder STDBUF , kann nicht Redirect Schnitt Ausgabe einige Ansätze gibt) entweder durch einen Pseudo-Terminal wie die Verwendung kann erfolgen durch socat
/ script
/ expect
/ unbuffer
(ein expect
Skript) / zsh
's zpty
oder durch Einfügen von Code in die ausführbare Datei, um die Pufferung durch GNUs oder FreeBSDs zu deaktivieren stdbuf
.