Ở cả hai
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Và:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Tất cả tee
, grep
và wc
được bắt đầu đồng thời. Điều quan trọng sau đó là những gì xảy ra ở cuối.
wc
sẽ chỉ in kết quả khi thấy tập tin cuối vào đầu vào tiêu chuẩn của nó. Trong trường hợp đầu tiên, đó là khi tee
thoát ra, bởi vì sau đó tee
sẽ đóng nó fd
ở đầu kia của ống wc
đang đọc (bắt đầu bằng quá trình thay thế quy trình). Không có gì đảm bảo rằng grep
sẽ đọc tất cả đầu vào của nó vào thời điểm đó, chứ đừng nói đến việc viết đầu ra của nó (với điều kiện là các đường ống có thể chứa một lượng dữ liệu khá lớn và wc
có khả năng sẽ nhanh hơn grep
)
Trong trường hợp thứ hai, wc
sẽ thấy phần cuối của tập tin khi tất cả các nhà văn đến đường ống mà nó đang đọc đã đóng đầu ống của họ. Trong trường hợp đó, có một số nhà văn. tee
(thông qua mở fd trên /dev/fd/3
và qua fd của nó 3) và grep
trong đó cũng có nó fd
3 mở cửa cho các đường ống để wc
(mặc dù nó không được thực hiện bất kỳ việc sử dụng nó, hãy để một mình ghi vào nó). Phần bên trong {
có thể sẽ gây ra một quá trình subshell thêm cũng sẽ có fd
3 mở và sẽ chờ cho cả hai tee
và grep
.
Điều đó có nghĩa là wc
sẽ chỉ viết số dòng của nó sau khi grep
đã thoát.
Nếu bạn đã viết nó theo cách thích hợp, đó là bằng cách đóng các fds không cần mở:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
Sau đó, thứ tự sẽ không được đảm bảo trong các vỏ tối ưu hóa quá trình subshell. Tuy nhiên, lớp vỏ duy nhất mà tôi biết là vậy ksh93
nhưng ksh93
sử dụng các cặp ổ cắm cho các đường ống, vì vậy /dev/fd/3
ít nhất sẽ không hoạt động trên Linux.
Để xem những tiến trình nào đang chạy, bạn có thể thay thế grep
bằng ps
:
$ { { <file.txt tee /dev/fd/3 4>&- | ps -H >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
PID TTY TIME CMD
8727 pts/5 00:00:00 bash
8815 pts/5 00:00:00 bash
8817 pts/5 00:00:00 tee
8818 pts/5 00:00:00 ps
8816 pts/5 00:00:00 wc
Với bash
, bạn có thể thấy quá trình shell bổ sung đó và bạn có thể thấy nó cũng có đường ống được mở trên fd 3 với:
$ (p=$BASHPID; { { <file.txt tee /dev/fd/3 4>&- | lsof -ag "$p" -d3 >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1)
COMMAND PID PGID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 9843 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
tee 9845 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
lsof 9846 9842 chazelas 3r DIR 0,3 0 1 /proc
grep LITERAL >&4 3>&- 4>&-
có nghĩa là gì , fd 4 dường như được sử dụng và đóng?