Mam kilka procesów uruchomionychasynchronicznie, a każdy z nich pobiera dane wejściowe z fifo i wyświetla sygnał wyjściowy do innego fifo. Chcę je odczytać asynchronicznie. Problem polega na tym, że nie mogę uzyskać wyjścia przed zamknięciem fifo. Oto przykład
#!/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
Co skutkuje w
$ ./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
Jak mogę uzyskać asynchroniczną komunikację w ten sposób? Chciałbym uniknąć koprocesów, ponieważ nie wiem z góry, ile procesów asynchronicznych będę potrzebować, a rzeczy będą się bałaganić.
Odpowiedzi:
1 dla odpowiedzi № 1Dodawanie następującego wiersza
for x in $fout1 $fout2 $fout3; do printf "" > $x & done
tuż przed rozpoczęciem trzech podprocesów zdaje się przełamać zakleszczenie. Nie jestem do końca pewien, dlaczego. Zastąpienie pustego łańcucha tekstem powoduje utworzenie tego tekstu test.before
, więc podejrzewam, że cała podpowłoka, a nie tylko załączona read
, blokuje przekierowania we / wy.
0 dla odpowiedzi nr 2
Zastanawiam się, dlaczego umieszczasz przekierowania stdout i stderr poza podpowłoką:
(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 &
IMHO Powinien stać się:
(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 ^^^^^
Zatem wszystkie procesy, w tym przekierowania, znajdują się w podpowłoce, która jest rozwidlona od głównego procesu, a główny skrypt nie będzie blokował się podczas pierwszego cyklu.