bash
versi 4 memiliki coproc
perintah yang memungkinkan ini dilakukan dalam murni bash
tanpa 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 cat
dan stdbuf
kemudian membangun dapat dibuat lebih mudah dimengerti.
Penggunaan versi bash
dengan cat
dan 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
, cat
danstdbuf
#!/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 bash
saja. Untuk keperluan demo saya masih menggunakan stdbuf
karena 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.