시간 초과가 있는 통과 파이프

시간 초과가 있는 통과 파이프

파이프를 통해 데이터가 전달되지 않을 때 시간 초과를 구현하는 방법은 무엇입니까? 감시 장치 역할을 하며 다음과 같이 사용할 수 있습니다.

process1 | watchdog --timeout 60 | process2

데이터 파이프가 들어오지 않을 때 감시 프로세스가 종료되기를 원합니다.

감사해요!

답변1

첫째, 귀하의 질문에 있는 감시 파이프는 process1데드 파이프에 다시 쓰기를 시도하지 않는 한 종료되지 않을 것입니다. 따라서 워치독은 어떻게든 명시적으로 process1을 종료해야 합니다.

이 외에도 매우 간단한 watchdog.sh쉘 스크립트가 있습니다. 콘솔에서 대화형으로 테스트할 수 있습니다. 을 입력하면 ./watchdog.sh입력한 내용이 모두 복사되고 5초 동안 아무 것도 입력하지 않으면 중지됩니다.

#!/bin/bash

# first arg is timeout (default: 5)
T="${1:-5}"
PID=$$

exec tee >(bash -c '
while true ; do
    bytes=$(timeout '$T' cat | wc -c)
    if ! [ "$bytes" -gt 0 ] ;then
            break
    fi
done
## add something like "killall process1", for now we just kill this tee command
kill -9 '$PID)

스크립트는 실제로 T와 2*T 사이에서 시간 초과됩니다(그렇지 않으면 더 복잡해짐). 처음에 언급했듯이, kill 방법을 어떻게든 추가할 수 있습니다 process1.

다음은 테스트를 위한 예입니다.

프로세스1.sh:

#!/bin/bash

echo "here we are ..."
sleep 2
echo "still alive ..."
sleep 20
echo "too late ..."

그리고 다음과 같이 실행합니다(시간 초과 시 process1.sh를 종료하는 추악한 방법 포함).

(./process1.sh & echo $! >/tmp/pid; wait) |(./watchdog.sh 5; kill `cat /tmp/pid`)

답변2

이는 성능 측면에서 이상적이지 않을 수 있으며 라인 기반이지만 read이 목적에는 명령의 시간 초과 기능이 유용할 수 있습니다. 에서는 섹션 bash에 대해 다음과 같은 명령줄 섹션을 사용할 수 있습니다 watchdog --timeout 60.

while read -r -s -t 60 line ; do printf "%s\n" "$line" ; done

zsh유사한 read명령이 제공됩니다.

process1그러나 표준 출력이 닫혀서 첫 번째 부분(예: yours )이 종료되기 전까지는 전체 명령이 실제로 종료되지 않는다는 점에 유의하세요 .

답변3

문제에 대한 또 다른 관점은 파이프라인에서 감시 장치를 제거하고 파이프라인의 마지막 수정 시간을 계산하는 것일 수 있습니다. 예를 들어,

(
process1 &
pid=$!
old=0
while   new=$(stat -L /dev/stderr -c %Y)
        [ $new != $old ]
do      old=$new
        sleep 60
done 3>&2 2>&1 1>&3   &&   kill -hup $pid
) |
process2

그러면 process1이 백그라운드에 배치되어 pid를 얻은 다음 마지막 수정 시간에 대해 출력 파이프를 폴링할 수 있습니다. 60초 이내에 변경 사항이 없으면 PID를 종료할 수 있습니다. 출력을 캡처할 수 있도록 stat파일 설명자 1(즉, 파이프)을 stderr 및 stat로 바꿉니다.

관련 정보