내 스크립트는 실행 시간에 STDIN에 있거나 없을 수있는 정보를 수집하려고 시도하지만 파이프가 비어 있으면 고양이가 정지합니다. STDIN에 아무것도 없으면 스크립트가이 단계를 건너 뛰도록하려면 어떻게해야합니까?
stdin=$(cat <&0)
가능한 경우 / dev /가 마운트되었는지 여부에 관계없이 chroot에서 사용할 수 있기 때문에 / dev /를 참조하는 솔루션을 구체적으로 찾고 있지 않습니다.
답변
일반적으로 파이프 및 stdin으로 작업하는 동안 고갈 된 파이프에는 특별한 의미가 없습니다. eof
파이프를 닫는 데이터가있을 때까지 새 데이터가 계속 나타날 수 있습니다 . 귀하 cat
의 종료 eof
예상대로. 전에 데이터가 없다면 eof
stdin 이 실제로 비어 있다고 말할 수 있습니다 .
고려하십시오 sender | receiver
. ; sender
보다 (느리게) 느리는 것은 드문 일이 아닙니다 receiver
. 이 경우 receiver
stdin은 거의 항상 고갈되지만 파이프로 인해 전체 파이프를 죽이려는 경우 는 거의 없습니다. 따라서 “빈”(고갈되었지만 아직 종료되지 않은) stdin으로 종료되는 도구는 표준이 아닌 예외입니다.
Bash에는 read -t 0
( -t
POSIX에는 필요하지 않음) 있습니다. 보낸 사람 help read
:
TIMEOUT
is0
인 경우read
데이터를 읽으려고하지 않고 즉시 반환하며 지정된 파일 설명자에서 입력을 사용할 수있는 경우에만 성공을 반환합니다.
기본적 read
으로 stdin에서 읽으므로 종료 상태가 read -t 0
stdin이 “비어 있는지”알려줍니다. 그러나 조심하십시오! 같은 명령
echo 1 | read -t 0
때문에, 성공적 여부 종료 될 수 있습니다 echo
및 read
되지 순차적으로 동시에 실행합니다. 이를 피하려면 스크립트가 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
. 바이트도없고 eof
5 초도 없으면 wc
그냥 수신합니다 eof
. 줄이 멈추지 않습니다.