Thứ tự đầu ra với sự thay thế quá trình


11

Đây là những gì tôi thường làm để chạy grepwctrên một tệp mà không phải quét hai lần

<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null

Tuy nhiên, điều này mang lại

EXEC LITERAL
32

đôi khi và

32
EXEC LITERAL

vào những thời điểm khác. (Đầu ra từ greptrước đầu ra từ wctrong trường hợp đầu tiên và ngược lại trong lần thứ hai.)

Mặt khác, với các chuyển hướng và mô tả tệp

{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1 

Tôi dường như luôn luôn nhận được

EXEC LITERAL
32

Tôi thích thứ tự đầu ra có thể dự đoán được nhưng nó có được đảm bảo với cách tiếp cận thứ hai không?

Câu trả lời:


4

Ở 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, grepwcđược bắt đầu đồng thời. Điều quan trọng sau đó là những gì xảy ra ở cuối.

wcsẽ 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 teethoát ra, bởi vì sau đó teesẽ đó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 grepsẽ đọ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à wccó khả năng sẽ nhanh hơn grep)

Trong trường hợp thứ hai, wcsẽ 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/3và qua fd của nó 3) và greptrong đó cũng có nó fd3 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ó fd3 mở và sẽ chờ cho cả hai teegrep.

Điều đó có nghĩa là wcsẽ 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 ksh93nhưng ksh93sử 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ế grepbằ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

Cảm ơn. Trong "ví dụ thích hợp" của bạn, điều đó grep LITERAL >&4 3>&- 4>&-có nghĩa là gì , fd 4 dường như được sử dụng và đóng?
iruvar

@ 1_CR, sau khi >&4, viết tắt của 1>&4, grepcủa fd 1 và 4 điểm đến tài nguyên cùng (stdout ban đầu của vỏ). grepkhông cần mở fd 4 của nó cho bất cứ điều gì. Nó không làm gì với nó, vì vậy chúng tôi đóng nó với4>&-
Stéphane Chazelas

Dòng lệnh cuối cùng đó là ma thuật mật mã.

-1

Để có được một đơn đặt hàng dự đoán sử dụng

(<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null)|sort

Có lẽ tôi đã không đủ rõ ràng. Tôi có nghĩa là thứ tự dự đoán theo thứ tự của đầu ra lệnh (tức là đầu ra từ grep trước khi đầu ra từ wc). Tôi không cần kết quả đầu ra được sắp xếp
iruvar 19/12/13

vừa tìm thấy gnu.org/software/bash/manual/bashref.html#Command-Grouping , nó cho tôi biết rằng với các toán tử {} bạn đảm bảo (trong trường hợp này) trước tiên bạn phải làm <file.txt tee / dev / fd / 3 | grep LITITH> & 4; và khi điều này được thực hiện, bạn gọi wc, vì vậy để trả lời câu hỏi ban đầu của bạn, vâng, nó được đảm bảo theo sự hiểu biết của tôi
Thorsten Staerk

1
@ThorstenStaerk bạn có thể thêm thông tin bổ sung mà bạn tìm thấy vào câu trả lời của mình không?
terdon

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.