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

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

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

TL;DR

while read -r line; do ... done < filetimeout에서 a가 발생 하면 종료되어 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]"

출력이 조기에 종료되고, 추가로 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

Hacky 수정은 먼저 모든 줄을 반복하고 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. 이는 두 번째 줄의 경우에 베어를 사용하여 관찰할 수 있습니다 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
$ 

관련 정보