빈 STDIN을 읽으려고 할 때 고양이가 멈춤


2

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

stdin=$(cat <&0)

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


최소한 / dev / null이 없는 chroot 를 프로덕션에서 사용할 수 있다면 놀랍습니다 . 어쨌든 "/ dev 마운트"와 "/ dev 수동으로 최소한으로 생성"사이에는 먼 길이있다.
grawity

해결책하지만 cat -심지어 간단한은 cat당신과 같은 일을하지 않을 것이다 cat <&0.
xenoid

@ xenoid 예, 알고 있습니다. 나는 세 가지를 모두 시도했지만 모두 동일한 결과를 낳습니다. <& 0은 잠시 기다리지 않고 고양이 오류를 일으킬 수 있는지 확인하기 위해 놀아 남았습니다.
StarCrashr

그건 그렇고, 나는 대답을 기다리는 동안 계속 놀고 있었고 그것이 단지 교수형이 아니라는 것을 발견했습니다. 콘솔에서 입력을 찾고있었습니다. 이로 인해 heredocs로 입력하여 고양이가 없으면 고양이를 끝내려고 시도했지만 그에 도달하기 전에 대답을 얻었습니다.
StarCrashr

답변:


3

일반적으로 파이프 및 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. 줄이 멈추지 않습니다.


누군가가 궁금한 경우를 대비하여 제 입력은 실제로 텍스트입니다. 암호를 포함하거나 포함하지 않을 수있는 사용자 및 / 또는 호스트에 대한 콜론으로 구분 된 정보 배열이므로 선택적 stdin이 내 용도에 중요합니다 (명령 줄에서 암호가 허용되지 않음). stdin에 데이터가 없으면 스크립트는 비밀번호없는 인증 방법을 시도하고 대신 첫 번째 인수에서 나머지 정보를 찾습니다.
StarCrashr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.