"cat"이 시간 초과되면 시간 초과로 인해 while 읽기 루프가 종료됩니다.

"cat"이 시간 초과되면 시간 초과로 인해 while 읽기 루프가 종료됩니다.

timeout함수 호출로 인해 루프가 중지되는 이유를 알 수 없습니다 . "해결책"이 있지만 어떻게/왜 이런 일이 발생하는지 정말 궁금합니다! 이것은 cat명령 시간 초과와 관련된 것 같습니다 .

긴 이야기 짧게

while read -r line; do ... done < filetimeout가 발생하면 종료되어 cat오류 출력과 종료 코드가 생성됩니다. 실제로 루프아니요파일의 각 줄을 반복합니다.

먼저 파일의 모든 줄을 포함하는 배열을 만든 다음 ...에서 실행하면 모든 줄이 처리되고 for line in "${all_lines[@]}"; do종료 코드의 출력이 정확해집니다.timeout


스크립트가 grade.sh모든 것을 읽고 tests.txt실행하여 종료 soln.sh되도록 의도되었다고 가정합니다 soln.sh. "작동하는" 예를 보여주기 위해 soln.sh먼저 sleep.

tests.txt

first
second
third
fourth
fifth

grade.sh

#!/usr/bin/env bash

while read -r line; do
    echo "Test: $line"
    output="$(timeout 2 ./soln.sh "$line")"
    timed_exit=$?
    echo "  Soln Output: $output"
    echo "  Timed exit:  $timed_exit"
done < "tests.txt"

soln.sh

#!/usr/bin/env bash
if [[ "$1" == "third" ]]; then
    sleep 3
fi
echo "[soln running $1]"

예상 출력

Test: first
  Soln Output: [soln running first]
  Timed exit:  0
Test: second
  Soln Output: [soln running second]
  Timed exit:  0
Test: third
  Soln Output: 
  Timed exit:  124
Test: fourth
  Soln Output: [soln running fourth]
  Timed exit:  0
Test: fifth
  Soln Output: [soln running fifth]
  Timed exit:  0

soln대신 영원히 지속되는 작업(입력 대기)을 수행 하면 루프가 종료됩니다.

soln.sh

#!/usr/bin/env bash
if [[ "$1" == "third" ]]; then
    cat $(find . -name iamnothere.txt) | wc -l
fi
echo "[soln running $1]"

조기 종료, extra 2, 오류 exit코드 출력

Test: first
  Soln Output: [soln running first]
  Timed exit:  0
Test: second
  Soln Output: [soln running second]
  Timed exit:  0
Test: third
  Soln Output: 2
[soln running third]
  Timed exit:  0

해키 수정은 먼저 각 행을 반복한 다음 루프를 사용하여 for이를 우회하는 것입니다.

"안정적인"grade.sh

#!/usr/bin/env bash

all_lines=()
idx=0
while read -r line; do
    all_lines[idx]="$line"
    (( idx++ ))
done < "tests.txt"

for line in "${all_lines[@]}"; do
    echo "Test: $line"
    output="$(timeout 2 ./soln.sh "$line")"
    timed_exit=$?
    echo "  Soln Output: $output"
    echo "  Timed exit:  $timed_exit"
done

예상 출력

Test: first
  Soln Output: [soln running first]
  Timed exit:  0
Test: second
  Soln Output: [soln running second]
  Timed exit:  0
Test: third
  Soln Output: 
  Timed exit:  124
Test: fourth
  Soln Output: [soln running fourth]
  Timed exit:  0
Test: fifth
  Soln Output: [soln running fifth]
  Timed exit:  0

이것은 기능입니까, 버그입니까, 아니면 뭔가 빠졌습니까?

나에게는 스크립트의 나머지 부분이 실행되기 시작하면서 이것이 cat압도적인 것 같습니다.timeout

답변1

 cat $(find . -name iamnothere.txt) | wc -l

존재하지 않으면 iamnothere.txt된다.

cat | wc -l

표준 입력을 소비합니다.while행을 읽는 것과 동일한 표준 입력을 반복합니다.. for표준 입력을 사용하지 않음으로써 이를 방지하십시오 while. 이는 두 번째 줄에 bare를 사용하여 관찰할 수 있습니다 cat. 이는 세 번째 줄을 읽었음을 나타냅니다 cat.

$ cat lines 
first
secon
third
$ cat looper 
#!/bin/sh
while read line; do
    x=$(timeout 2 ./doer "$line")
    echo "$line out=$x code=$?"
done < lines

$ cat doer 
#!/bin/sh
if [ "$1" = secon ]; then
    cat
else
    echo "$1 pid$$"
fi

$ ./looper 
first out=first pid42079 code=0
secon out=third code=0
$ 

관련 정보