超时导致当cat超时时,读取循环结束

斯韦涅夫斯

我无法分辨为什么timeout在函数调用中会导致循环停止。我有一个“解决方案”,但是对于这种情况的发生方式/原因,我真的很感兴趣!这似乎与cat命令超时有关?

TL; DR

while read -r line; do ... done < file在上timeout发生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

修补错误的方法是首先遍历每行,并使用一个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

 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
$ 

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章