다음 스크립트를 고려해보세요
#!/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
속도를 늦추는 경우 아마도 하나만 얻을 수 있습니다.