1

通过一些谷歌搜索(无论如何我都不是 bash 专家),我能够编写一个 bash 脚本,它允许我运行一个测试套件并在它运行时在底部输出一个状态栏。通常需要大约 10 个小时,状态栏会告诉我有多少测试通过,多少​​失败。

有时它工作得很好,但偶尔我会遇到一个无限循环,这很糟糕(mmm-kay?)。这是我正在使用的代码:

#!/bin/bash
WHITE="\033[0m"
GREEN="\033[32m"
RED="\033[31m"

(run_test_suite 2>&1) | tee out.txt |
while IFS=read -r line;
do
    printf "%$(tput cols)s\r" " ";
    printf "%s\n" "$line";

    printf "${WHITE}Passing Tests: ${GREEN}$(grep -c passed out.txt)\t"         2>&1;
    printf "${WHITE}Failed Tests: ${RED}$(   grep -c FAILED out.txt)${WHITE}\r" 2>&1;
done

当我遇到这个错误时会发生什么,我将有一个错误消息无限重复,导致日志文件 ( out.txt) 变成一些数兆字节的怪物(我认为它进入了 GB 一次)。这是一个重复的示例错误(每组之间有四行空白):

warning caused by MY::Custom::Perl::Module::TEST_FUNCTION
print() on closed filehandle GEN3663 at /some/CPAN/Perl/Module.pm line 123.

我尝试取消2>&1重定向,并尝试更改while IFS=read -r line;while read -r line;,但我不断进入无限循环。奇怪的是,这似乎在大多数情况下都会发生,但有时我完成了长长的测试套件而没有任何问题。

编辑

我写这篇文章的原因是从黑白测试套件升级到彩色测试套件(因此是 ANSI 代码)。以前,我会使用

run_test_suite > out.txt 2>&1 &
watch 'grep -c FAILED out.txt; grep -c passed out.txt; tail -20 out.txt'

以这种方式运行它会从 Perl 获得相同的警告,但会将其打印到文件中并继续前进,而不是陷入无限循环。使用 watch,也会打印类似的东西,[32m而不是实际将文本渲染为绿色。

4

2 回答 2

0

该错误在您的脚本中。这不是 IO 错误;这是一个非法的参数错误。当您作为句柄提供的变量根本不是句柄或者是您已关闭的句柄时,就会发生该错误。

写入损坏的管道会导致进程被杀死SIGPIPEprint返回 false 并$!设置为EPIPE

于 2013-02-20T22:49:44.267 回答
0

经过一些修改,我能够修复 perl 错误,并且 bash 脚本现在似乎运行良好。但是,如果将来发生类似的事情,这似乎是运行测试套件的一种更安全的方法:

#!/bin/bash
WHITE="\033[0m"
GREEN="\033[32m"
RED="\033[31m"

run_full_test > out.txt 2>&1 &
tail -f out.txt | while IFS= read line; do
    printf "%$(tput cols)s\r" " ";
    printf "%s\n" "$line";

    printf "${WHITE}Passing Tests: ${GREEN}$(grep -c passed     out.txt)\t"         2>&1;
    printf "${WHITE}Failed Tests: ${RED}$(   grep -c 'FAILED!!' out.txt)${WHITE}\r" 2>&1;
done

这有一些缺点。主要是,如果我点击Ctrl-C停止测试,它似乎已经停止,但实际上run_full_test仍在后台运行,我需要记住手动杀死它。此外,当测试完成时tail -f仍在运行。换句话说,这里有两个进程在运行并且它们不同步。

这是原始脚本,稍作修改,解决了这些问题,但并非万无一失(即,如果 run_full_test 有问题,可能会陷入无限循环):

#!/bin/bash
WHITE="\033[0m"
GREEN="\033[32m"
RED="\033[31m"

(run_full_test 2>&1) | tee out.txt | while IFS= read line; do
    printf "%$(tput cols)s\r" " ";
    printf "%s\n" "$line";

    printf "${WHITE}Passing Tests: ${GREEN}$(grep -c passed     out.txt)\t"         2>&1;
    printf "${WHITE}Failed Tests: ${RED}$(   grep -c 'FAILED!!' out.txt)${WHITE}\r" 2>&1;
done
于 2013-02-27T01:08:21.333 回答