bashversi 4 memiliki coprocperintah yang memungkinkan ini dilakukan dalam murni bashtanpa pipa bernama:
coproc cmd1
eval "exec cmd2 <&${COPROC[0]} >&${COPROC[1]}"
Beberapa cangkang lain juga bisa melakukannya coproc.
Di bawah ini adalah jawaban yang lebih terperinci tetapi mengaitkan tiga perintah, bukan dua, yang membuat hanya sedikit lebih menarik.
Jika Anda senang juga menggunakan catdan stdbufkemudian membangun dapat dibuat lebih mudah dimengerti.
Penggunaan versi bashdengan catdan stdbuf, mudah dimengerti:
# 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}"
Catatan, harus menggunakan eval karena ekspansi variabel dalam <& $ var adalah ilegal di versio of bash 4.2.25 saya.
Versi menggunakan pure bash: Pecah menjadi dua bagian, luncurkan pipa pertama di bawah coproc, lalu makan siang bagian kedua, (baik perintah tunggal atau pipa) menghubungkan kembali ke yang pertama:
coproc {
cmd 1 | cmd2
}
endcmd="exec cmd3 <&${COPROC[0]} >&${COPROC[1]}"
eval "${endcmd}"
Bukti dari konsep:
file ./prog, hanya prog dummy untuk mengkonsumsi, menandai dan mencetak ulang baris. Menggunakan subkulit untuk menghindari masalah buffering mungkin berlebihan, bukan itu intinya di sini.
#!/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
file ./start_cat
Ini adalah versi yang menggunakan bash, catdanstdbuf
#!/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}"
atau file ./start_part. Ini adalah versi yang menggunakan murni bashsaja. Untuk keperluan demo saya masih menggunakan stdbufkarena prog Anda yang sebenarnya harus berurusan dengan buffering secara internal untuk menghindari pemblokiran karena buffering.
#!/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}"
Keluaran:
> ~/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
Itu berhasil.