Nói nếu một bộ mô tả tập tin trỏ đến một thiết bị đầu cuối
Một chương trình có thể cho biết nếu một bộ mô tả tệp được liên kết với một thiết bị tty bằng cách sử dụng isatty()
chức năng C tiêu chuẩn (thường nằm bên dưới một ioctl()
cuộc gọi hệ thống cụ thể vô hại sẽ trả về lỗi khi fd không trỏ đến thiết bị tty) .
Các [
/ test
tiện ích có thể làm điều đó với mình -t
điều hành.
if [ -t 1 ]; then
echo stdout is open to a terminal
fi
Truy tìm hàm libc trên hệ thống GNU / Linux:
$ ltrace [ -t 1 ] | cat
[...]
isatty(1) = 0
[...]
Truy tìm hệ thống theo dõi:
$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010) = -1 ENOTTY (Inappropriate ioctl for device)
[...]
Nói nếu nó chỉ vào một đường ống
Để xác định xem fd có được liên kết với ống / fifo hay không, người ta có thể sử dụng lệnh fstat()
gọi hệ thống , trả về cấu trúc có st_mode
trường chứa loại và quyền của tệp được mở trên fd đó. Các S_ISFIFO()
C macro tiêu chuẩn có thể được sử dụng trên đó st_mode
lĩnh vực để xác định xem fd là một ống / FIFO.
Không có tiện ích tiêu chuẩn nào có thể làm được fstat()
, nhưng có một số cách triển khai stat
lệnh không tương thích có thể thực hiện được. zsh
Nội dung stat
dựng sẵn stat -sf "$fd" +mode
trả về chế độ dưới dạng chuỗi đại diện có ký tự đầu tiên đại diện cho loại ( p
đối với đường ống). GNU stat
có thể làm tương tự với stat -c %A - <&"$fd"
, nhưng cũng stat -c %F - <&"$fd"
phải báo cáo loại một mình. Với BSD stat
: stat -f %St <&"$fd"
hoặc stat -f %HT <&"$fd"
.
Nói nếu nó có thể tìm kiếm
Các ứng dụng thường không quan tâm nếu thiết bị xuất chuẩn là một đường ống. Họ có thể quan tâm rằng nó có thể tìm kiếm được (mặc dù thường không quyết định có đệm hay không).
Để kiểm tra xem fd có thể tìm kiếm được không (ống, ổ cắm, thiết bị tty không thể tìm kiếm, các tệp thông thường và hầu hết các thiết bị khối thường là), người ta có thể thử một lseek()
cuộc gọi hệ thống tương đối với độ lệch bằng 0 (rất vô hại). dd
là một tiện ích tiêu chuẩn có giao diện lseek()
nhưng nó không thể được sử dụng cho thử nghiệm đó, vì việc triển khai sẽ hoàn toàn không gọi lseek()
nếu bạn yêu cầu bù 0.
Các shell zsh
và ksh93
shell đã tích hợp sẵn các toán tử tìm kiếm:
$ 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
Vô hiệu hóa bộ đệm
Các script
lệnh sử dụng một cặp giả thiết bị đầu cuối để bắt đầu ra của một chương trình, do đó chương trình stdout (và stdin và stderr) sẽ là một thiết bị giả thiết bị đầu cuối.
Khi thiết bị xuất chuẩn là thiết bị đầu cuối, nhìn chung vẫn có một số bộ đệm, nhưng nó dựa trên dòng. printf
/ puts
và đồng sẽ không viết bất cứ điều gì cho đến khi một ký tự dòng mới được xuất ra. Đối với các loại tệp khác, bộ đệm là theo khối (của một vài kilo byte).
Có một số tùy chọn để vô hiệu hóa bộ đệm được thảo luận trong một số câu hỏi và hỏi đáp ở đây (tìm kiếm unbuffer hoặc stdbuf , không thể chuyển hướng cắt đầu ra đưa ra một vài cách tiếp cận) bằng cách sử dụng thiết bị đầu cuối giả như có thể được thực hiện bởi socat
/ script
/ expect
/ unbuffer
(một expect
tập lệnh) / zsh
's zpty
hoặc bằng cách tiêm mã vào tệp thực thi để vô hiệu hóa bộ đệm như được thực hiện bởi GNU hoặc FreeBSD stdbuf
.