![stdin이 닫힐 때까지 반복되는 sh 스크립트 - 이것을 어떻게 테스트합니까?](https://linux55.com/image/185476/stdin%EC%9D%B4%20%EB%8B%AB%ED%9E%90%20%EB%95%8C%EA%B9%8C%EC%A7%80%20%EB%B0%98%EB%B3%B5%EB%90%98%EB%8A%94%20sh%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%20-%20%EC%9D%B4%EA%B2%83%EC%9D%84%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%A9%EB%8B%88%EA%B9%8C%3F.png)
입력 스트림을 파이프하려고 하는데 다운스트림 파이프라인 프로그램이 실패할 수 있는 상황을 포착하고 싶습니다. 이 경우 다시 시작해야 합니다. 그래서 나는 그것을 루프에 넣었습니다.
step1 |while true ; do step2 ; done
그러나 업스트림 파이프가 닫히면 루프가 종료되기를 원합니다. 2단계의 종료 상태에서는 이를 알 수 없습니다. 그렇지 않으면 다음과 같이 말했을 수도 있습니다.
step1 |until [ $? -ne 0 ] ; do step2 ; done
stdin이 닫혀 있는지 확인하지만 실제로 stdin의 문자를 사용하지 않는 테스트가 필요합니다.
C에서는 어떻게 하는지 궁금합니다. 버퍼가 0인 read(2)를 사용하여 이것을 테스트할 수 있습니까? 나는 그렇게 생각하지 않습니다. 옵션 (2)는 어떻습니까? 아니요. 아니면 그럴까요? fcntl(2)은 어떻습니까? 아무것도 찾을 수 없습니다.
바이트를 소비하고 어떻게든 다시 출력하는 것 외에는 정말 다른 방법이 없나요? 파일 설명자를 닫지 않고 테스트하시겠습니까?
답변1
적어도 Linux에서는 poll()
이벤트 마스크에서 with를 사용하여 파이프의 다른 쪽 끝이 닫혔는지 알 수 있습니다.POLLHUP
그러나 이 시점에서 읽을 데이터가 파이프에 아직 남아 있을 수 있으므로 해당 데이터도 확인하는 것이 좋습니다. Linux에서는 ioctl을 통해 이 작업을 수행할 수 있습니다 FIONREAD
.
따라서 다음 중 하나를 정의할 수 있습니다.
stdin_alive() {
perl -MIO::Poll -e '
require "sys/ioctl.ph";
-p STDIN or die "stdin is not a pipe\n";
$p = IO::Poll->new;
$p->mask(STDIN, POLLHUP);
if ($p->poll(0)) {
ioctl(STDIN, &FIONREAD, $n) or die "FIONREAD: $!\n";
$n = unpack "L", $n;
exit 1 unless $n;
}'
}
다음과 같이 사용하십시오.
step1 | while stdin_alive; do step2; done
ifne
또 다른 방법은 다음 명령을 사용하는 것입니다 moreutils
.
step1 |
while
ifne sh -c 'step2 && exit 42'
[ "$?" -eq 42 ]
do
continue
done
ifne
표준 입력을 읽어보십시오. 적어도 1바이트를 읽으면 ifne
명령이 시작되고 해당 표준 입력이 새 파이프에 연결되며, 해당 새 파이프를 통해 표준 입력에서 읽은 내용이 명령에 삽입되므로 추가 삽질이 발생하므로 효율성이 떨어집니다. 전송을 위한 추가 파이프가 있지만 이는 입력 유형(파이프뿐만 아니라)에 관계없이 작동한다는 의미입니다.
이전 솔루션과의 또 다른 차이점은 ifne
시작하기 전에 stdin에 대한 입력을 기다리는 step2
반면, poll()
+ FIONREAD
메소드는 파이프가 활성 상태인지, 검사 시점의 정확한 시점에 데이터가 있는지만 확인한다는 것입니다. 그러나 POLLIN
이는 폴링되는 이벤트 목록에 추가하여 변경할 수 있습니다.