Bash将stdin重定向到命名管道

时间:2014-09-08 14:38:51

标签: bash asynchronous pipe named-pipes

我有几个异步运行的进程,每个进程从fifo接收输入并将其输出转发到另一个fifo。我想异步读取它们。问题是我似乎无法在fifo关闭之前获得输出。这是一个例子

#!/bin/bash -x

rm -rf /tmp/fifo[123].{in,out}
for i in $(seq 1 3) ; do
    mkfifo /tmp/fifo$i.in
    mkfifo /tmp/fifo$i.out
done

fin1=/tmp/fifo1.in
fout1=/tmp/fifo1.out

fin2=/tmp/fifo2.in
fout2=/tmp/fifo2.out

fin3=/tmp/fifo3.in
fout3=/tmp/fifo3.out

(echo "Proc 1"; while read var; do echo "proc1: " $var; done) < $fin1 > $fout1 &
(echo "Proc 2"; while read var; do echo "proc2: " $var; done) < $fin2 > $fout2 &
(echo "Proc 3"; while read var; do echo "proc3: " $var; done) < $fin3 > $fout3 &

# Get some of the output
cat $fout1 >> /tmp/test.before
cat $fout2 >> /tmp/test.before
cat $fout3 >> /tmp/test.before

# Generate more output
echo "Do you copy proc 1" > $fin1
echo "Do you copy proc 1" > $fin2
echo "Do you copy proc 1" > $fin3

# Get the rest of the output
cat $fout1 >> /tmp/test.after
cat $fout2 >> /tmp/test.after
cat $fout3 >> /tmp/test.after

# Show the results
echo "Before input:"
cat /tmp/test.before

echo "After input:"
cat /tmp/test.after

结果是

$ ./test.sh
+ rm -rf '/tmp/fifo[123].in' '/tmp/fifo[123].out'
++ seq 1 3
+ for i in '$(seq 1 3)'
+ mkfifo /tmp/fifo1.in
+ mkfifo /tmp/fifo1.out
+ for i in '$(seq 1 3)'
+ mkfifo /tmp/fifo2.in
+ mkfifo /tmp/fifo2.out
+ for i in '$(seq 1 3)'
+ mkfifo /tmp/fifo3.in
+ mkfifo /tmp/fifo3.out
+ fin1=/tmp/fifo1.in
+ fout1=/tmp/fifo1.out
+ fin2=/tmp/fifo2.in
+ fout2=/tmp/fifo2.out
+ fin3=/tmp/fifo3.in
+ fout3=/tmp/fifo3.out
+ cat /tmp/fifo1.out

我怎样才能获得这样的异步通信?我想避免使用coprocesses,因为我事先并不知道我需要多少异步进程,而且事情会变得混乱。

2 个答案:

答案 0 :(得分:1)

添加以下行

for x in $fout1 $fout2 $fout3; do printf "" > $x & done
在你开始三个子进程之前的

似乎打破了僵局。我不完全确定原因。用一些文本替换空字符串会在test.before中生成该文本,因此我怀疑整个子shell,而不仅仅是封闭的read,阻止了I / O重定向。

答案 1 :(得分:0)

我想知道你为什么把stdout和stderr重定向放在子shell之外:

(echo "Proc 1"; while read var; do echo "proc1: " $var; done) < $fin1 > $fout1 &
(echo "Proc 2"; while read var; do echo "proc2: " $var; done) < $fin2 > $fout2 &
(echo "Proc 3"; while read var; do echo "proc3: " $var; done) < $fin3 > $fout3 &

恕我直言应该成为:

(echo "Proc 1" > $fout1; while read var; do echo "proc1: " $var; done < $fin1 >> $fout1) &
(echo "Proc 2" > $fout2; while read var; do echo "proc2: " $var; done < $fin2 >> $fout2) &
(echo "Proc 3" > $fout3; while read var; do echo "proc3: " $var; done < $fin3 >> $fout3) &
                                                                           look here ^^^^^

因此,所有进程(包括重定向)都位于从主进程派生的子shell中,并且主脚本不会在第一个while循环中阻塞。

相关问题