Có, bashgiống như trong ksh(tính năng đến từ đâu), các quy trình bên trong quy trình thay thế không được chờ đợi (trước khi chạy lệnh tiếp theo trong tập lệnh).
đối với một <(...), điều đó thường tốt như trong:
cmd1 <(cmd2)
Shell sẽ chờ đợi cmd1và cmd1thường sẽ chờ đợi cho cmd2đến khi nó đọc cho đến khi hết tập tin trên đường ống được thay thế, và việc kết thúc tập tin đó thường xảy ra khi cmd2chết. Đó là lý do cùng nhiều vỏ (không bash) không bận tâm chờ đợi cmd2trong cmd2 | cmd1.
Đối cmd1 >(cmd2)Tuy nhiên,, đó là thường không phải như vậy, vì nó là nhiều cmd2mà thường chờ cmd1có như vậy sẽ thường thoát sau đó.
Điều đó đã được sửa trong zshđó chờ cmd2ở đó (nhưng không phải nếu bạn viết nó dưới dạng cmd1 > >(cmd2)và cmd1không được dựng sẵn, {cmd1} > >(cmd2)thay vào đó hãy sử dụng như tài liệu ).
kshkhông chờ đợi theo mặc định, nhưng cho phép bạn chờ nó với waitnội trang (nó cũng làm cho pid có sẵn $!, mặc dù điều đó không giúp ích gì nếu bạn làm vậy cmd1 >(cmd2) >(cmd3))
rc(với cmd1 >{cmd2}cú pháp), giống như kshngoại trừ bạn có thể nhận được các pids của tất cả các quy trình nền với $apids.
es(cũng với cmd1 >{cmd2}) chờ đợi cmd2như trong zshvà cũng chờ cmd2trong <{cmd2}quá trình chuyển hướng.
bashkhông làm cho pid của cmd2(hoặc chính xác hơn là lớp con như nó chạy cmd2trong một tiến trình con của lớp con đó mặc dù đó là lệnh cuối cùng ở đó) có sẵn $!, nhưng không cho phép bạn chờ đợi.
Nếu bạn phải sử dụng bash, bạn có thể giải quyết vấn đề bằng cách sử dụng lệnh sẽ chờ cả hai lệnh với:
{ { cmd1 >(cmd2); } 3>&1 >&4 4>&- | cat; } 4>&1
Điều đó làm cho cả hai cmd1và cmd2có fd 3 của họ mở ra một đường ống. catsẽ chờ kết thúc tập tin ở đầu kia, vì vậy thường sẽ chỉ thoát khi cả hai cmd1và cmd2đã chết. Và shell sẽ chờ catlệnh đó . Bạn có thể thấy rằng như một mạng lưới để bắt đầu chấm dứt tất cả các quy trình nền (bạn có thể sử dụng nó cho những thứ khác bắt đầu trong nền như với &, coprocs hoặc thậm chí các lệnh mà nền đó cung cấp, chúng không đóng tất cả các mô tả tệp của chúng như daemon thường làm ).
Lưu ý rằng nhờ quy trình chia nhỏ bị lãng phí đã đề cập ở trên, nó hoạt động ngay cả khi cmd2đóng fd 3 của nó (các lệnh thường không làm điều đó, nhưng một số thích sudohoặc sshlàm). Các phiên bản trong tương lai bashcuối cùng có thể thực hiện tối ưu hóa như trong các shell khác. Sau đó, bạn cần một cái gì đó như:
{ { cmd1 >(sudo cmd2; exit); } 3>&1 >&4 4>&- | cat; } 4>&1
Để đảm bảo vẫn còn một quá trình shell bổ sung với fd 3 mở đó đang chờ sudolệnh đó .
Lưu ý rằng catsẽ không đọc bất cứ điều gì (vì các quy trình không viết trên fd 3 của họ). Nó chỉ ở đó để đồng bộ hóa. Nó sẽ thực hiện chỉ một read()cuộc gọi hệ thống sẽ trở lại mà không có gì ở cuối.
Bạn thực sự có thể tránh chạy catbằng cách sử dụng thay thế lệnh để thực hiện đồng bộ hóa đường ống:
{ unused=$( { cmd1 >(cmd2); } 3>&1 >&4 4>&-); } 4>&1
Lần này, nó là cái vỏ thay vì catđọc từ ống có đầu kia mở trên fd 3 cmd1và cmd2. Chúng tôi đang sử dụng một phép gán biến để trạng thái thoát cmd1có sẵn trong $?.
Hoặc bạn có thể thực hiện thay thế quy trình bằng tay, và sau đó bạn thậm chí có thể sử dụng hệ thống của mình shvì điều đó sẽ trở thành cú pháp shell tiêu chuẩn:
{ cmd1 /dev/fd/3 3>&1 >&4 4>&- | cmd2 4>&-; } 4>&1
mặc dù lưu ý như đã lưu ý trước đó rằng không phải tất cả các shtriển khai sẽ đợi cmd1sau khi cmd2kết thúc (mặc dù điều đó tốt hơn so với cách khác). Thời gian đó, $?chứa trạng thái thoát của cmd2; mặc dù bashvà zshlàm cho cmd1trạng thái thoát có sẵn trong ${PIPESTATUS[0]}và $pipestatus[1]tương ứng (xem thêm pipefailtùy chọn trong một số shell để $?có thể báo cáo sự cố của các thành phần đường ống khác với lần cuối)
Lưu ý rằng yashcó vấn đề tương tự với tính năng chuyển hướng quy trình của nó . cmd1 >(cmd2)sẽ được viết cmd1 /dev/fd/3 3>(cmd2)ở đó. Nhưng cmd2không được chờ đợi và bạn cũng không thể sử dụng waitđể chờ đợi và pid của nó cũng không có sẵn trong $!biến. Bạn sẽ sử dụng cùng một công việc xung quanh như cho bash.