Reputation: 361
What is the cleanest (simplest, most efficient, shortest, quickest, easiest, most elegant) way to create a non-linear pipeline like this in Bash?
I have three commands: mksock
, irclogin
, and ircpingpong
. I want to pipe stdin
, irclogin
, and ircpingpong
into mksock
, and pipe mksock
into stdout
and ircpingpong
. This means that mksock
and ircpingpong
are in a loop. I drew a diagram:
irclogin only needs to be run once and be the first input into mksock. After that, ircpingpong, and stdin should be accepted at any time. I am currently using pipes and a temporary file like this:
#!/bin/bash
server=127.0.0.1
port=6667
infifo=/tmp/ircin
outfifo=/tmp/ircout
pongfifo=/tmp/ircpong
rm $infifo
rm $outfifo
rm $pongfifo
mkfifo $infifo
mkfifo $outfifo
touch $pongfifo
( irclogin | cat - $infifo & tail -f $pongfifo; ) | mksock $server $port | tee $outfifo | stdbuf -oL ircpingpong > $pongfifo &
cat < $outfifo &
cat > $infifo
pkill tail
This works, but I want to know if there is a better way to do this. It bothers me that I am using a file rather than a pipe for looping back from ircpingpong to mksock using tail. Using a pipe didn't work because, to my understanding, something is written to the pipe before tail -f
starts reading from it, and so it misses it.
It also bothers me that I have to kill tail at the end of the script, because it doesn't stop on it's own and would leave the socket connected even after the script has ended.
Upvotes: 13
Views: 484
Reputation: 767
I can suggest a version without temporary files, and with two fifo-s:
fifo1=/tmp/fifo1
fifo2=/tmp/fifo2
rm $fifo1
rm $fifo2
mkfifo $fifo1
mkfifo $fifo2
ircpingpong < $fifo2 > $fifo1 &
(mksock <$fifo1|tee $fifo2 )&
irclogin >$fifo1 &
cat >$fifo1
The idea is to run all programs separately, and only ensure that input and output of each program is redirected properly according to this diagram:
Of course, ircpingpong
must read stdin
and write to stdout
, irclogin
must write to stdout
, and mksock
must read from stdin
and write to stdout
.
Upvotes: 4
Reputation: 5509
Here's something that uses just one fifo.
fifo=/tmp/myfifo
rm $fifo
mkfifo $fifo
((ircpingpong < $fifo &) && irclogin && cat) | mksock | tee $fifo
Add stdbuf as needed.
I don't know whether you will get your "something doesn't die on its own" problem; when I ctrl-c'ed the script, everything seemed to die.
Upvotes: 0