What is the cleanest way to create a non-linear pipeline?
Asked Answered
A

2

13

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:

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.

Alkahest answered 5/3, 2016 at 22:44 Comment(1)
This is what Coproceses are for. They are supported differently on Korn shell and bash, bash coprocesses were introduced in bash 4.0. See wiki.bash-hackers.org/syntax/keywords/coprocSihonn
S
4

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:

pipe-flow

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.

Spartacus answered 16/3, 2016 at 14:3 Comment(0)
M
0

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.

Mattoid answered 19/10, 2018 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.