주어진 벽 시간 동안만 지속되는 파이프를 만드는 쉬운 방법이 있습니까?
시간이 지남에 따라 STDOUT에 기록되는 내용(바이트나 라인이 아님)의 "스냅샷"을 찍을 수 있기를 원합니다. 그것은 마치
tail -f /var/log/whatever.log | pipe_for_seconds 10 > ./10_second_sample_of_log
저는 BASH를 사용하고 있는데 다른 쉘에서 이것이 더 쉽다면 이에 대해 듣고 싶습니다.
답변1
게누핵심 도구버전 7.0부터 다음 명령이 있습니다 timeout
.
timeout 10 tail -f /var/log/whatever.log
만약 너라면진짜약간 다른 프로세스를 시간 초과한 다음 파이프를 연결하려면 파이프가 필요합니다 timeout
.
tail -f /var/log/whatever.log | timeout 10 cat > ./10_second_sample_of_log
하지만 참고하세요파이프라인의 일부를 종료하면 버퍼링으로 인해 문제가 발생할 수 있습니다., 신호 및 프로그램 동작에 따라 다름(이 질문은 관련 문제를 다룹니다.파이프라인에서 버퍼링 끄기). 보통 변해요종료 코드과정도 마찬가지다.
(최근) coreutils가 없으면 이 간단한 시간 초과 프로그램도 잘 작동합니다. http://www.unixlabplus.com/unix-prog/timeout/timeout.html 또는 펄 방법:
tail -f /var/log/whatever.log | perl -n -e 'BEGIN{alarm 10; $|=1}; print;'
(참고로 $|=1
출력 버퍼링은 꺼집니다. 이는 위에서 언급한 것처럼 파이프 내 출력 손실을 방지하기 위한 것입니다.)
(약간 나이가 들었음)네트워크 파이프패키지에는 timelimit
명령도 있습니다(일부 Linux 시스템에서는 여전히 찾을 수 있음).
이 유사한 질문에는 몇 가지 옵션이 있습니다.쉘 스크립트에 시간 초과를 도입하는 방법은 무엇입니까?
답변2
이것은 작동합니다:
tail -f /var/log/whatever.log > ten_second_sample & sleep 10 && kill $!
tail
sleep
10초 동안 백그라운드에서 병렬로 시작이후 kill
$!
마지막으로 시작된 백그라운드 프로세스의 PID입니다.
답변3
tail -f
PID 종료에 의존하는 것은 PID가 너무 빨리 종료되는 경우(예: 파일이 존재하지 않는 경우) 신뢰할 수 없을 수 있습니다. 또 다른 보다 일반적인 해결책은 시간 초과 전에 "킬 타이머"가 완료되면 wait
and 사용도 중지됩니다 kill %%
( %%
bash에서 시작한 가장 최근 작업 - using 사용을 의미함 &
).
구성은 다음과 같습니다( sleep 2
매개변수 등이 포함된 사용자 정의 명령이 있고 시간 제한이 10초로 설정되어 있음).
# Your command that may take some (or not) time to execute:
sleep 2 &
# Set a timer that kills the last started job
sleep 10 & wait -n 1; kill %%; wait -n 1
이 구성은 제한 시간에 도달하거나 사용자 지정 명령이 실행을 완료할 때까지 기다립니다(이 경우 항상 sleep 2
먼저 중지됩니다). 그러면 명령 또는 시간 초과가 각각 종료됩니다 kill %%
. 그런 다음 마지막 명령은 wait -n 1
명령 또는 시간 제한이 실제로 종료될 때까지 추가 실행을 차단합니다(선택 사항이지만 필수일 수 있음).
노트. 필요하고 예상한 대로 이전에 병렬로 실행된 명령은 영향을 받지 않습니다.
예
read
시간 초과가 있는 명명된 파이프에서 행을 읽지만 시간 초과 플래그를 사용하지 않는 보다 실용적인 예:
# Custom bash function to set timeout in seconds for the most recently started job (parallel execution).
timeout() { sleep $1 & wait -n 1; kill %%; wait -n 1 }
# Example 1:
mkfifo /tmp/test
read ln </tmp/test &
timeout 10
아무 것도 기록되지 않으므로 /tmp/test
10초 후에 시간 초과됩니다. 명령이 즉시 종료되더라도 종료 타이머가 중지된다는 것을 보여주기 위해:
# Example 2:
mkfifo /tmp/test
echo "Hello" >/tmp/test &
ln="$(read ln </tmp/test && echo -e "$ln" & timeout 10)"
echo "Line was read: $ln"
명명된 파이프의 실제 사용에 유의하세요. 서브쉘에서 실행되기 때문에 read ln
(상위) 스크립트에서는 접근할 수 없습니다. 따라서 echo
(다른) 변수에 저장하기 위해 행이 인쇄됩니다 ln
.