「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。これは、2行目のbareを使用して観察できますcat。これは、3行目を読んだことを示します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
$ 

おすすめ記事