Какой самый чистый способ создания нелинейного конвейера?
Какой самый чистый (самый простой, самый эффективный, самый короткий, самый быстрый, самый простой, самый элегантный) способ создать нелинейный конвейер, подобный этому, в Bash?
У меня есть три команды: mksock
, irclogin
и ircpingpong
. Я хочу irclogin
stdin
, irclogin
и ircpingpong
в mksock
и mksock
в stdout
и ircpingpong
. Это означает, что mksock
и ircpingpong
находятся в цикле. Я нарисовал диаграмму:
![Diagram]()
irclogin должен быть запущен только один раз и быть первым входом в mksock. После этого ircpingpong и stdin должны быть приняты в любое время. В настоящее время я использую каналы и временный файл, как это:
#!/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
Это работает, но я хочу знать, есть ли лучший способ сделать это. Меня беспокоит, что я использую файл, а не канал для возврата из ircpingpong в mksock с использованием tail. Использование канала не сработало, потому что, насколько я понимаю, что-то записывается в канал до того, как tail -f
начинает читать с него, и поэтому он пропускает его.
Меня также беспокоит, что мне нужно убить tail в конце скрипта, потому что он не останавливается сам по себе и оставлял сокет подключенным даже после завершения скрипта.
Ответы
Ответ 1
Я могу предложить версию без временных файлов и с двумя 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
Идея состоит в том, чтобы запускать все программы по отдельности и только гарантировать, что ввод и вывод каждой программы перенаправлен должным образом согласно этой схеме:
![pipe-flow]()
Конечно, ircpingpong
должен читать stdin
и писать в stdout
, irclogin
должен писать в stdout
, а mksock
должен читать из stdin
и писать в stdout
.
Ответ 2
Здесь что-то, что использует только один fifo.
fifo=/tmp/myfifo
rm $fifo
mkfifo $fifo
((ircpingpong < $fifo &) && irclogin && cat) | mksock | tee $fifo
Добавьте stdbuf по мере необходимости.
Я не знаю, получишь ли ты свою проблему "что-то не умирает само по себе"; когда я ctrl-c'ed сценарий, все, казалось, умерло.