在 shell 脚本中输出给定行后终止程序

在 shell 脚本中输出给定行后终止程序

背景:

我正在为一个计算生物学软件编写测试脚本。我正在测试的软件可能需要几天甚至几周才能运行,因此它内置了恢复功能,以防系统崩溃或电源故障。

我正在尝试弄清楚如何测试恢复系统。具体来说,我无法找到一种以受控方式“崩溃”程序的方法。我正在考虑以某种方式定时在一定时间后运行 SIGKILL 指令。这可能不是理想的选择,因为测试用例不能保证每次都以相同的速度运行(它在共享环境中运行),因此将日志与所需输出进行比较会很困难。

该软件确实会为其完成的每个分析部分打印一行。

问题:

我想知道是否有一个好的/优雅的方法(在 shell 脚本中)来捕获程序的输出,然后在程序输出给定行/行数时终止该程序?

答案1

像这样的包装器脚本是一种标准方法。该脚本在后台运行程序,然后循环,每分钟检查日志文件中是否有某个字符串。如果找到该字符串,则后台程序将被终止,脚本退出。

command="prog -foo -whatever"
log="prog.log"
match="this is the what i want to match"

$command > "$log" 2>&1 &
pid=$!

while sleep 60
do
    if fgrep --quiet "$match" "$log"
    then
        kill $pid
        exit 0
    fi
done

答案2

如果您的程序将在 SIGPIPE 上终止(这是默认操作),那么将输出导入到读取器中就足够了,读取器将在读取该行时退出。

因此它可能很简单

$ program | sed -e '/Suitable text from the line/q'

如果你想抑制默认输出使用

$ program | sed -n -e '/Suitable text from the line/q'

同样,如果想在一定行数后停止,可以使用 head 代替 sed,例如

$ program | head -n$NUMBER_OF_LINES_TO_STOP_AFTER

击杀发生的确切时间取决于终端的缓冲行为,正如 stardt 在评论中所建议的那样。

答案3

作为 dmckee 答案的替代方案,grep带有-m选项的命令(参见例如本手册页) 命令也可以使用:

compbio | grep -m 1 "Text to match"

当找到 1 行匹配的文本时停止,或者

compbio | grep -v -m 10 "Text to match"

等待 10 行与给定的文本不匹配的内容。

答案4

您可以使用“while”语句:

您需要将软件的输出(或其日志)通过管道传输,然后对每个新行进行条件测试,然后运行 ​​kill -KILL。例如(我使用 /var/log/messages 作为日志文件进行测试):

tail -f /var/log/messages | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

或者直接使用软件:

./biosoftware | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

您需要替换日志路径/应用程序名称、要匹配的行和要终止的 PID(您也可以使用 killall)。

祝你的软件好运,

雨果,

相关内容