CentOS의 FIFO 및 간단한 bash 병렬화

CentOS의 FIFO 및 간단한 bash 병렬화

Ubuntu 20.04에서 CentOS Linux 8까지의 간단한 병렬 실행을 처리하기 위해 bash 스크립트를 조정하는 데 문제가 있습니다. 스크립트에서는 FIFO에서 문자열을 읽고 이를 공통 파일로 출력하는 여러 "리더"를 생성했습니다. 문자열은 기본 스크립트에서 FIFO로 직접 전달됩니다. 프로세스를 깔끔하게 만들기 위해 파일 설명자와 잠금을 사용합니다. 나는 여전히 FIFO에 쓰기 전에 모든 독자가 시작할 때까지 기다리고 있습니다. 전체 스크립트를 맨 마지막에 넣었습니다.

스크립트는 Ubuntu에서 완벽하게 실행되며 출력은 다음과 같습니다(첫 번째 열은 판독기 ID이고 두 번째 열은 판독기가 FIFO에서 얻는 것입니다).

2 1
4 2
1 3
...
3 4998
2 4999
4 5000

읽기가 완료되면 메시지가 하나씩 전송됩니다.

CentOS에서 동일한 스크립트를 사용하여 이것을 얻었습니다.

4 1
1 7
2 8
...
3 153
4 154
1 155

눈에 띄는 점프가 있으며 메시지 2~6이 완전히 손실됩니다. 또한 프로세스가 155에서 조기에 중지됩니다.

무슨 일이 일어났는지 정말 모르겠어요. 어떤 아이디어가 있나요?

스크립트:

#!/bin/bash

readers=4
objs=5000

echo "" > output.txt

# Temporary files and fifo
FIFO=$(mktemp -t fifo-XXXX)
START=$(mktemp -t start-XXXX)
START_LOCK=$(mktemp -t lock-XXXX)
FIFO_LOCK=$(mktemp -t lock-XXXX)
OUTPUT_LOCK=$(mktemp -t lock-XXXX)
rm $FIFO
mkfifo $FIFO

# Cleanup trap
cleanall() {
rm -f $FIFO
rm -f $START
rm -f $START_LOCK
rm -f $FIFO_LOCK
rm -f $OUTPUT_LOCK
}
trap cleanall exit

# Reader process
reader() {
    ID=$1    
    exec 3<$FIFO
    exec 4<$FIFO_LOCK
    exec 5<$START_LOCK
    exec 6<$OUTPUT_LOCK
    
    # Signal the reader has started
    flock 5                
    echo $ID >> $START
    flock -u 5
    exec 5<&- 

    # Reading loop
    while true; do
        flock 4  
        read -su 3 item
        read_status=$?
        flock -u 4  
        if [[ $read_status -eq 0 ]]; then
            flock 6
            echo "$ID $item" >> output.txt
            flock -u 6  
        else
            break # EOF reached
        fi
    done

    exec 3<&-
    exec 4<&-
    exec 6<&-
}

# Spawn readers
for ((i=1;i<=$readers;i++)); do
    reader $i &
done

exec 3>$FIFO

# Wait for all the readers
exec 5<$START_LOCK
while true; do
        flock 5
        started=$(wc -l $START | cut -d \  -f 1)
        flock -u 5
        if [[ $started -eq $readers ]]; then
            break
        else
            sleep 0.5s
        fi
done
exec 5<&-

# Writing loop
for ((i=1;i<=$objs;i++)); do
    echo $i 1>&3
done

exec 3<&- 
wait

echo "Script done"

exit 0

관련 정보