我无法分辨为什么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] 删除。
我来说两句