연속 폴링 명명된(FIFO) 파이프

연속 폴링 명명된(FIFO) 파이프

실행 중인 셸 스크립트의 활동을 모니터링하기 위해 명명된 파이프를 사용하려고 합니다. 쉘 스크립트는 처리를 "시작"했다는 것을 파이프에 기록합니다. 처리가 완료되면 파이프에 "Completed"라고 기록됩니다. 두 번째 스크립트는 모니터링을 수행하고 두 개의 메시지를 읽습니다. 두 번째 스크립트가 5분 이내에 "완료" 메시지를 받지 못하면 경고가 전송됩니다.

그래서 두 프로세스 간 통신을 위해 명명된 파이프를 사용하는 방법에 대한 Linux Journal의 코드를 찾았습니다. 파이프에서 한 번에 두 개의 메시지를 가져오고 루프 중에 카운터를 표시하려고 하지만 "완료" 메시지가 나타나면 다시 0으로 재설정됩니다. 다음 메시지에 대해 파이프를 지속적으로 폴링할 것인지 확인하기 위해 타이밍이 다음에 추가됩니다. 그러나 카운터가 증가하는 것을 볼 수 없습니다. 파이프에서 읽기 라인을 기다리는 것 같습니다. 내가 뭘 잘못하고 있는지에 대한 제안이 있습니까?

#!/bin/bash

pipe=/tmp/testpipe

loopcnt=0
while true
do
    echo "count: $loopcnt"

    if read line <$pipe; then
        if [[ "$line" == 'Started' ]]; then
            echo $line
        elif [[ "$line" == 'Completed' ]]; then
            echo $line
            loopcnt=0
        fi
    fi
    ((loopcnt=loopcnt+1))
done

답변1

파이프의 쓰기 쪽이 열려 있지 않은 경우 읽기 쪽을 열면 쓰기가 나타날 때까지 차단됩니다. 이는 쉘이 자체적으로 실행되기 전에 리디렉션을 설정하려고 시도할 때 발생하므로 read자체 시간 초과는 도움이 되지 않습니다.read-t

그래도 파이프에 무엇이든 쓰면 루프가 계속되지만 데이터를 읽기 전에 너무 많은 시간이 경과했는지 감지하는 것은 말할 것도 없고 경과된 시간을 찾는 데 도움이 되지 않습니다.

이 문제를 해결하는 가장 쉬운 방법은 판독기에서 읽기-쓰기 모드로 파이프를 열어 항상 기록기가 있는지 확인하는 것입니다.

예를 들어 다음과 같습니다.

#!/bin/bash

pipe=/tmp/testpipe
if ! [[ -p "$pipe" ]]; then
    echo "'$pipe' isn't a pipe"
    exit 1
fi
exec 3<> "$pipe"
secs=0
timeout=5
while true; do
    if read -t 1 -u 3 line; then
        echo "read '$line'"
        secs=0
    else
        echo .
    fi
    if ((++secs >= timeout)); then
        echo "no data within $timeout secs"
        break
    fi
done
echo end.

하지만 $pipe존재하지 않는 경우에는 exec 3<> "$pipe"일반 파일로 생성되므로 주의하세요. 파이프인지 확인하기 위한 명시적인 테스트를 수행하더라도 테스트와 열기 사이에 파이프가 제거되었을 가능성이 있습니다. 이런 일이 발생하면 read파일에 데이터가 없기 때문에 s는 즉시 오류 상태를 반환합니다.

관련 정보