명명된 파이프를 사용하는 bash IPC

명명된 파이프를 사용하는 bash IPC

다음 스크립트를 고려해보세요

#!/usr/bin/bash

chan=/tmp/pipe.$$
mkfifo $chan
{
    for x in a b c d e
    do
        echo $x > $chan
    done
} &
for y in 1 2 3 4 5
do
    x=$(cat $chan)
    echo "var $x = $y ;"
done
rm $chan

예상대로 작동하지 않는 것 같습니다. 예를 들어

❯ ./testpipe.sh
var a
b
c = 1 ;
^C

fifo에 리더가 없으면 에코 대기하면 안 되나요? 터미널에서 이 작업을 수행하면 예상대로 멈춥니다.

❯ mkfifo /tmp/pipe
❯ echo 1 > /tmp/pipe
^C

스크립트에서 왜 다르게 동작합니까?


고쳐 쓰다

매번 열지 않고 fds를 사용하도록 전환했습니다.

#!/usr/bin/bash
chan=/tmp/pipe.$$
mkfifo $chan    
{
    exec 5>"$chan"
    for x in a "ba ba ba baanannna" c d e
    do
        echo $x >&5
    done
} &

exec 6<"$chan"
for y in 1 2 3 4 5
do
    read -u 6 x
    echo "var $x = $y ;"
done
rm $chan

내가 문제를 고쳤는지 아니면 게임을 더 희귀하게 만든 것인지 확실하지 않습니다.

❯ ./testpipe.sh
var a = 1 ;
var ba ba ba baanannna = 2 ;
var c = 3 ;
var d = 4 ;
var e = 5 ;

업데이트 2

FIFO가 전혀 필요하지 않습니다. proc 대체만으로도 백그라운드에서 무언가를 실행하고 필요할 때 읽을 수 있습니다. 생산자와 소비자에 절전 모드를 추가하기 전후에 테스트되었습니다. 잘 작동하는 것 같습니다. 게임이 없을 수도 있습니다.

#!/usr/bin/bash

produce()
{
    for x in a "ba ba ba   baanannna" "more    space" d e
    do
        echo "$x"
    done
}

exec {fd}< <(produce)
for y in 1 2 3 4 5
do
    read -u $fd x
    echo "var $x = $y ;"
done

답변1

Running in background shell -- running in foreground shell

echo a waits
                        cat opens read side
                        cat is maybe faulting in some pages or maybe not just picked 
                        but for whatever reason doesn't immediately call read
echo a completes
echo b doesn't wait (read side already open) and completes
echo c ditto
                        cat calls read, gets a NL b NL c NL and writes them 
                        (but the shell's $(...) that reads them drops the final NL)
echo d probably doesn't wait, but might if cat has close'd already (race condition)

성공하면 $(cat <$chan)모든 ae를 얻을 수 있습니다.서브쉘읽기 전에 cat을 실행하기 전에 읽기 측을 열어 대기 시간을 늘립니다. OTOH 생산자를 사용 command echo하거나 /bin/echo속도를 늦추는 경우 아마도 하나만 얻을 수 있습니다.

관련 정보