bash
Version 4 verfügt über einen coproc
Befehl, der dies in reinen bash
Pipes ohne Named Pipes ermöglicht:
coproc cmd1
eval "exec cmd2 <&${COPROC[0]} >&${COPROC[1]}"
Einige andere Muscheln können das coproc
auch.
Nachfolgend finden Sie eine ausführlichere Antwort, die jedoch drei anstelle von zwei Befehlen verkettet, was ein wenig interessanter macht.
Wenn Sie auch gerne verwenden cat
und stdbuf
dann konstruieren, kann das leichter verständlich gemacht werden.
Version bash
mit cat
und stdbuf
, leicht verständlich:
# 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}"
Beachten Sie, dass Sie eval verwenden müssen, da die Variablenerweiterung in <& $ var in meiner Version von Bash 4.2.25 illegal ist.
Version using pure bash
: In zwei Teile aufteilen, erste Pipeline unter Coproc starten, dann den zweiten Teil zu Mittag essen (entweder ein einzelner Befehl oder eine Pipeline) und wieder mit der ersten verbinden:
coproc {
cmd 1 | cmd2
}
endcmd="exec cmd3 <&${COPROC[0]} >&${COPROC[1]}"
eval "${endcmd}"
Konzeptioneller Beweiß:
Datei ./prog
, nur ein Dummy-Programm zum Verzehren, Markieren und erneuten Drucken von Zeilen. Die Verwendung von Subshells, um Pufferprobleme zu vermeiden, kann zu einem Übermaß führen. Hier geht es nicht darum.
#!/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
Datei ./start_cat
Dies ist eine Version mit bash
, cat
undstdbuf
#!/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}"
oder Datei ./start_part
. Dies ist eine Version, die bash
nur pure verwendet . Für Demozwecke verwende ich immer noch, stdbuf
weil Ihr echter Prog sich sowieso intern mit dem Puffern befassen müsste, um ein Blockieren aufgrund von Puffern zu vermeiden.
#!/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}"
Ausgabe:
> ~/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
Das tut es.