빈 STDIN을 읽으려고 할 때 고양이가 멈춤 있거나 없을

내 스크립트는 실행 시간에 STDIN에 있거나 없을 수있는 정보를 수집하려고 시도하지만 파이프가 비어 있으면 고양이가 정지합니다. STDIN에 아무것도 없으면 스크립트가이 단계를 건너 뛰도록하려면 어떻게해야합니까?

stdin=$(cat <&0)

가능한 경우 / dev /가 마운트되었는지 여부에 관계없이 chroot에서 사용할 수 있기 때문에 / dev /를 참조하는 솔루션을 구체적으로 찾고 있지 않습니다.



답변

일반적으로 파이프 및 stdin으로 작업하는 동안 고갈 된 파이프에는 특별한 의미가 없습니다. eof파이프를 닫는 데이터가있을 때까지 새 데이터가 계속 나타날 수 있습니다 . 귀하 cat의 종료 eof예상대로. 전에 데이터가 없다면 eofstdin 실제로 비어 있다고 말할 수 있습니다 .

고려하십시오 sender | receiver. ; sender보다 (느리게) 느리는 것은 드문 일이 아닙니다 receiver. 이 경우 receiverstdin은 거의 항상 고갈되지만 파이프로 인해 전체 파이프를 죽이려는 경우 는 거의 없습니다. 따라서 “빈”(고갈되었지만 아직 종료되지 않은) stdin으로 종료되는 도구는 표준이 아닌 예외입니다.

Bash에는 read -t 0( -tPOSIX에는 필요하지 않음) 있습니다. 보낸 사람 help read:

TIMEOUTis 0인 경우 read데이터를 읽으려고하지 않고 즉시 반환하며 지정된 파일 설명자에서 입력을 사용할 수있는 경우에만 성공을 반환합니다.

기본적 read으로 stdin에서 읽으므로 종료 상태가 read -t 0stdin이 “비어 있는지”알려줍니다. 그러나 조심하십시오! 같은 명령

echo 1 | read -t 0

때문에, 성공적 여부 종료 될 수 있습니다 echoread되지 순차적으로 동시에 실행합니다. 이를 피하려면 스크립트가 sleep한참 전에 있어야 합니다 read -t 0. stdin의 출처에 따라 “한동안”이 상대적으로 길 수 있습니다. 다음과 같이하십시오 :

sleep 1
if read -t 0; then    # process stdin here, you know it's non-empty

stdin에서 가져온 데이터로 변수를 채 웁니다. 변수에 이진 데이터를 저장하는 좋은 생각 (읽기하지 않기 때문에 ), 어쩌면 당신의 데이터는 텍스트입니다. 그렇다면 다음 read -t과 같이 사용 하십시오.

read -r -t 5 -d $'\0' stdin

널 문자 (어쨌든 Bash 변수에 저장할 수 없음)를 구분 기호 ( -d $'\0')로 사용하면 stdin변수에 대한 텍스트 (예 : 줄 바꿈)를 읽을 수 있습니다 . 최대 5 초 ( -t 5) 후에 명령이 종료되어 스크립트를 계속 진행할 수 있습니다.

또 다른 방법은입니다 timeout. 내 데비안의 기본 예 :

timeout --foreground 5 cat | wc -c

(교체 wc -c표준 입력 구문 분석 코드와 함께, 그냥 예입니다).

이진 데이터를 잘 처리해야합니다. 경우 cat하지 않습니다 eof다음 오초 후 살해되므로, wc얻을 것이다 eof어쨌든 및 라인은 스톨하지 않습니다. 현재 cat데이터를 처리하고 있는지 여부에 관계없이 문제가 해결 됩니다. 5 초 이상 걸리더라도 일부 데이터 만 있으면 모든 데이터를 얻고 싶다고 생각합니다. 개선 된 버전 :

{ timeout --foreground 5 dd bs=1 count=1 2>/dev/null && cat; } | wc -c

첫 번째 바이트가 5 초 내에 나타나면 cat트리거됩니다. 그런 다음 eof시간이 오래 걸리더라도 추가 입력을 처리 할 수 있습니다. 첫 번째 바이트 (있는 경우)를 포함한 모든 것이로 이동합니다 wc. 바이트도없고 eof5 초도 없으면 wc그냥 수신합니다 eof. 줄이 멈추지 않습니다.