bash
phiên bản 4 có coproc
lệnh cho phép thực hiện điều này một cách thuần túy bash
mà không cần đặt tên ống:
coproc cmd1
eval "exec cmd2 <&${COPROC[0]} >&${COPROC[1]}"
Một số vỏ khác cũng có thể làm coproc
như vậy.
Dưới đây là câu trả lời chi tiết hơn nhưng xâu chuỗi ba lệnh, thay vì hai, điều này làm cho chỉ thú vị hơn một chút.
Nếu bạn hài lòng cũng sử dụng cat
và stdbuf
sau đó xây dựng có thể được thực hiện dễ hiểu hơn.
Phiên bản sử dụng bash
với cat
và stdbuf
, dễ hiểu:
# start pipeline
coproc {
cmd1 | cmd2 | cmd3
}
# create command to reconnect STDOUT `cmd3` to STDIN of `cmd1`
endcmd="exec stdbuf -i0 -o0 /bin/cat <&${COPROC[0]} >&${COPROC[1]}"
# eval the command.
eval "${endcmd}"
Lưu ý, phải sử dụng eval vì việc mở rộng biến trong <& $ var là bất hợp pháp trong phiên bản bash 4.2.25 của tôi.
Phiên bản sử dụng thuần túy bash
: Chia thành hai phần, khởi chạy đường ống đầu tiên theo coproc, sau đó ăn trưa phần thứ hai, (một lệnh đơn hoặc đường ống) kết nối lại với đường dẫn thứ nhất:
coproc {
cmd 1 | cmd2
}
endcmd="exec cmd3 <&${COPROC[0]} >&${COPROC[1]}"
eval "${endcmd}"
Bằng chứng của khái niệm:
tập tin ./prog
, chỉ là một prog giả để tiêu thụ, gắn thẻ và in lại các dòng. Sử dụng các lớp con để tránh các vấn đề về bộ đệm có thể là quá mức cần thiết, đây không phải là vấn đề ở đây.
#!/bin/bash
let c=0
sleep 2
[ "$1" == "1" ] && ( echo start )
while : ; do
line=$( head -1 )
echo "$1:${c} ${line}" 1>&2
sleep 2
( echo "$1:${c} ${line}" )
let c++
[ $c -eq 3 ] && exit
done
nộp ./start_cat
Đây là một phiên bản sử dụng bash
, cat
vàstdbuf
#!/bin/bash
echo starting first cmd>&2
coproc {
stdbuf -i0 -o0 ./prog 1 \
| stdbuf -i0 -o0 ./prog 2 \
| stdbuf -i0 -o0 ./prog 3
}
echo "Delaying remainer" 1>&2
sleep 5
cmd="exec stdbuf -i0 -o0 /bin/cat <&${COPROC[0]} >&${COPROC[1]}"
echo "Running: ${cmd}" >&2
eval "${cmd}"
hoặc tập tin ./start_part
. Đây là một phiên bản chỉ sử dụng thuần túy bash
. Đối với mục đích demo tôi vẫn đang sử dụng stdbuf
vì prog thực sự của bạn sẽ phải xử lý bộ đệm trong nội bộ để tránh bị chặn do bộ đệm.
#!/bin/bash
echo starting first cmd>&2
coproc {
stdbuf -i0 -o0 ./prog 1 \
| stdbuf -i0 -o0 ./prog 2
}
echo "Delaying remainer" 1>&2
sleep 5
cmd="exec stdbuf -i0 -o0 ./prog 3 <&${COPROC[0]} >&${COPROC[1]}"
echo "Running: ${cmd}" >&2
eval "${cmd}"
Đầu ra:
> ~/iolooptest$ ./start_part
starting first cmd
Delaying remainer
2:0 start
Running: exec stdbuf -i0 -o0 ./prog 3 <&63 >&60
3:0 2:0 start
1:0 3:0 2:0 start
2:1 1:0 3:0 2:0 start
3:1 2:1 1:0 3:0 2:0 start
1:1 3:1 2:1 1:0 3:0 2:0 start
2:2 1:1 3:1 2:1 1:0 3:0 2:0 start
3:2 2:2 1:1 3:1 2:1 1:0 3:0 2:0 start
1:2 3:2 2:2 1:1 3:1 2:1 1:0 3:0 2:0 start
Nó làm điều đó.