Защо чакането не може да работи за процес на четене в наименуван канал?

wait в bash е процесът да промени състоянието. В следващия bash скрипт създайте именуван канал и отворете 5 процес, за да запишете поток от данни в него, и отворете 1 процес, за да прочетете потока от данни от него в друг файл.

cat pipe.sh
fifo_file=fifo.pipe
mkfifo $fifo_file
exec 6<>$fifo_file
rm $fifo_file

DateWrite ()
{
    i=0
    while [[ $i -lt 200 ]]
    do
        str=`date`
        i=$(( i+1 ))
        echo "$i $str"
    done
}

writers=()
for  (( i=0; i<5; i++ ))
do 
    DateWrite >&6  & 
    echo "add a writer process pid  $!"
    writers+=($!)
done


while read date_time
do
    echo $date_time >> output.file 
done  <&6  &
reader=$!

for writer in "${writers[@]}" 
do
    wait "$writer"
    echo "the status of writer process pid $writer changed"   
done

echo "reader process pid is $reader"
wait  "$reader"
echo "the status of reader process pid $reader changed"   

exec 6<&-

За да проверите командата за изчакване в pipe.sh с bash pipe.sh.

add a writer process pid  4749
add a writer process pid  4750
add a writer process pid  4751
add a writer process pid  4752
add a writer process pid  4753
the status of writer process pid 4749 changed
the status of writer process pid 4750 changed
the status of writer process pid 4751 changed
the status of writer process pid 4752 changed
the status of writer process pid 4753 changed
reader process pid is 4754

Информационният списък не съдържа

the status of reader process pid 4754 changed

Изявлението wait "$reader" се изпълнява в безкраен цикъл while, нормално е wait да не може да работи.
Ако изтрия линиите за теглене:

wait  "$reader"
echo "the status of reader process pid $reader changed"   

И изпълнете bash pipe.sh :

add a writer process pid  19670
add a writer process pid  19671
add a writer process pid  19673
add a writer process pid  19674
add a writer process pid  19675
the status of writer process pid 19670 changed
the status of writer process pid 19671 changed
the status of writer process pid 19673 changed
the status of writer process pid 19674 changed
the status of writer process pid 19675 changed
reader process pid is 19676

Потърсете pid 19676 в конзолата.

ps aux |grep '[p]ipe'
debian   19676  0.0  0.0  16516  2100 pts/1    S    19:54   0:00 bash pipe.sh

Процесът на четене, създаден в pipe.sh, все още работи, когато pipe.sh е завършен.
Не искам да променя wait "$reader" в kill "$reader" в pipe.sh.
Има ли начин да знам, че echo $date_time е прочел края на тръбата и да изпратя сигнал за затваряне на процеса на четене?

@Philippe и всички приятели тук ,sleep 1; echo q >&6, може би времевият интервал е толкова кратък. Да предположим по-сложен случай:

while read date_time
do
    test "$date_time" = q && exit
    echo $date_time >> output.file 
    bash_some_code_do_some_thing
done  <&6  &

Времето за изпълнение на bash_some_code_do_some_thing е по-дълго от 10 секунди, най-малко 10 секунди, не най-много 10 секунди и не можете да прецените точното време. Не можете да напишете такъв код като

sleep 10; echo q >&6

or

сън 100; echo q >&6 #какво ще стане, ако времето за работа е с 200 секунди повече?

Как да решим казуса тогава?


person showkey    schedule 05.05.2020    source източник
comment
Затваряте FD 6 след като изчакате четецът да приключи, но четецът няма да завърши, докато FD 6 не бъде затворен.   -  person l0b0    schedule 05.05.2020
comment
Моля, вижте актуализираната ми публикация, това не е причината, close FD 6 не е свързано с това.   -  person showkey    schedule 05.05.2020


Отговори (1)


Няма начин да изпратите EOF към тръба, отворена за четене-запис. Едно заобиколно решение е да изпратите команда за излизане:

fifo_file=fifo.pipe
mkfifo $fifo_file
exec 6<>$fifo_file
rm $fifo_file

DateWrite ()
{
    i=0
    while [[ $i -lt 200 ]]
    do
        str=`date`
        i=$(( i+1 ))
        echo "$i $str"
    done
}

writers=()
for  (( i=0; i<5; i++ ))
do 
    DateWrite >&6  & 
    echo "add a writer process pid  $!"
    writers+=($!)
done


while read date_time
do
    test "$date_time" = q && exit
    echo $date_time >> output.file 
done  <&6  &
reader=$!

for writer in "${writers[@]}" 
do
    wait "$writer"
    echo "the status of writer process pid $writer changed"   
done

echo "reader process pid is $reader"
sleep 1; echo q >&6
wait  "$reader"
echo "the status of reader process pid $reader changed"   

exec 6<&-

Друг начин е да изпратите TERM сигнал до читателя.

person Philippe    schedule 05.05.2020