Ngoài các tài liệu mà jordanm chỉ ra, tôi muốn đảm bảo sửa một quan niệm sai lầm được minh họa trong câu hỏi của bạn. Chương trình thực thi không xử lý các chuyển hướng. Nó hầu như không nhận thức được chúng. Vỏ xử lý chuyển hướng.
Một chương trình được bắt đầu với ba tệp được mở: stdin (# 0), stdout (# 1) và stderr (# 2). Nếu bạn chỉ chạy một chương trình từ dấu nhắc shell của mình, chúng sẽ được kết nối với thiết bị đầu cuối của bạn, vì vậy chương trình sẽ đọc những gì bạn nhập (stdin) và in đầu ra (stdout) và lỗi (stderr) đến thiết bị đầu cuối của bạn.
Ví dụ, tôi chỉ chạy cat
trong một thiết bị đầu cuối (có nghĩa tty
là /dev/pts/31
). Tôi có thể kiểm tra tập tin nào đã mở bằng lsof
:
$ lsof -a -p `pidof cat` -d0,1,2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 21257 anthony 0u CHR 136,31 0t0 34 /dev/pts/31
cat 21257 anthony 1u CHR 136,31 0t0 34 /dev/pts/31
cat 21257 anthony 2u CHR 136,31 0t0 34 /dev/pts/31
Thật vậy, chúng ta có thể thấy rằng nó có thiết bị đầu cuối mở cho cả ba. Bây giờ, thay vào đó, chúng ta hãy thử một lời mời mèo khá ngớ ngẩn : cat < /dev/zero > /dev/null 2>/dev/full
, đó là chuyển hướng cả ba:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 21838 anthony 0r CHR 1,5 0t0 1030 /dev/zero
cat 21838 anthony 1w CHR 1,3 0t0 1028 /dev/null
cat 21838 anthony 2w CHR 1,7 0t0 1031 /dev/full
Shell đã thực hiện các chuyển hướng đó bằng cách chuyển ba thiết bị là stdin, stdout và stderr (thay vì terminal). Vỏ tương tự thực hiện các đường ống. Hãy thử cat | dd > /dev/null
(một đường ống khá ngớ ngẩn, thực sự):
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 22507 anthony 0u CHR 136,31 0t0 34 /dev/pts/31
cat 22507 anthony 1w FIFO 0,8 0t0 56081395 pipe
cat 22507 anthony 2u CHR 136,31 0t0 34 /dev/pts/31
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dd 22508 anthony 0r FIFO 0,8 0t0 56081395 pipe
dd 22508 anthony 1u CHR 136,31 0t0 34 /dev/null
dd 22508 anthony 2u CHR 136,31 0t0 34 /dev/pts/31
Lưu ý cách shell đã mở một đường ống và nó đã sử dụng nó để kết nối thiết bị xuất chuẩn của cat
stdin của dd
. Và hơn nữa làm thế nào nó đã kết nối dd
thiết bị xuất chuẩn /dev/null
.
Các lệnh đang chạy không thực sự nhận thức được các chuyển hướng. Họ chỉ sử dụng stdin, stdout, stderr như bình thường. Tất cả đều có thể là thiết bị đầu cuối hoặc chúng có thể được chuyển hướng đến / từ một tệp, thiết bị hoặc có thể là một đường ống đến một chương trình khác. Hoặc thậm chí là một ổ cắm mạng, nếu vỏ của bạn hỗ trợ điều đó.
Ngay cả các đường ống phức tạp nhất cũng thực sự chỉ là các hướng dẫn cho trình bao về cách kết nối ba tay cầm tệp đó trước khi thực hiện chương trình.
(Chú ý: Một số chương trình hành xử khác nhau trong trường hợp một trong những được gắn vào một thiết bị đầu cuối, nhưng đó là bình thường để có nhiều người dùng thân thiện trong sử dụng tương tác Ví dụ, ls
chuyển sang đầu ra duy nhất cột và không có màu sắc khi thiết bị xuất chuẩn không phải là một Thiết bị đầu cuối thường là thứ bạn muốn nếu bạn sắp chuyển nó sang chương trình khác. Một số chương trình xử lý nhắc nhở khác nhau nếu stdin không phải là thiết bị đầu cuối. V.v.)