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