Não consigo discernir por que timeout
em uma chamada de função fará com que um loop pare. Eu tenho uma "solução", mas estou realmente muito intrigado sobre como / porque isso está acontecendo! Parece haver algo a ver com cat
sendo o comando expirado?
TL; DR
while read -r line; do ... done < file
é finalizado quando um timeout
ocorre em cat
, produzindo a saída e o código de saída incorretos. O loop faz não percorrer todas as linhas do arquivo.
Se, em vez disso, uma matriz for criada antes de todas as linhas no arquivo e ...
for executada em for line in "${all_lines[@]}"; do
, todas as linhas serão processadas e a saída de timeout
com relação aos códigos de saída estará correta. / p>
Suponha que o script grade.sh
pretenda ler todos os tests.txt
e executar soln.sh
, certificando-se de que soln.sh
termine. Para demonstrar um exemplo de "trabalho", soln.sh
será primeiro 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]"
saída esperada
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
Se alterarmos soln
para fazer algo que continuará para sempre (aguardando entrada), o loop será encerrado
soln.sh
#!/usr/bin/env bash
if [[ "$1" == "third" ]]; then
cat $(find . -name iamnothere.txt) | wc -l
fi
echo "[soln running $1]"
A saída
termina cedo, extra 2
, errado exit
code
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 fix é fazer um loop em todas as linhas primeiro e usar um loop for
que irá ignorar isso.
"corrigido" 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
saída esperada
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
isso é um recurso ou um bug ou estou faltando alguma coisa?
Parece-me que cat
está, de alguma forma, substituindo timeout
, já que o restante do script é executado.