有一个命令(比如$run_command),超时后必须将其终止。解决方案非常简单 - 我可以只使用来自 coreutils 的超时或来自其他堆栈溢出主题的 timeout3。但是我的命令从 untar 管道 smth 收到它的 stdin,就像这样
tar -xO -f "$1" | /usr/bin/time -f "%e" --output=$time_output -- $run_command
其中$run命令是我的命令,执行时间也被测量(使用时间实用程序)。
因此,问题是避免在超时实用程序中包含未延迟时间的最佳方法是什么?
在非常简单的形式中,您可以像这样终止调用脚本:
#!/bin/bash
( sleep $timeout_period && kill $$ ) &
tar -xO -f "$1" | ...
当然,这只是一个例子;您需要提供一些保险,即 $$ 在运行时仍然是相同的脚本kill
。
这当然会杀死整个脚本,包括time
(如果脚本被杀死,它将是 $timeout_period)。
更新#1:
使用临时文件的示例。
tmpfile=$(/usr/bin/mktemp /tmp/temp.XXXXX)
tar -xO -f "$1" > $tmpfile
trap "rm -f $tmpfile" 0 1 2 3 15
/usr/bin/time -f "%e" --output=$time_output -- $run_command < $tmpfile
请注意,由于文件系统的速度/性能,这仍然容易出错。
更新#2:
除了免除tar
时间外,这还添加了超时功能:
(
tmpfile=$(/usr/bin/mktemp /tmp/temp.XXXXX)
tar -xO -f "$1" > $tmpfile
trap "rm -f $tmpfile" 0 1 2 3 15
/usr/bin/time -f "%e" --output=$time_output -- $run_command < $tmpfile
) &
pid=$!
( sleep $timeout_period && kill $pid ) &
wait %1
在第一个脚本段中也存在相同的潜在问题;您需要提供保险,证明 $$ 仍然是您在杀死它之前所认为的。 此外,信号将发送到 shell 包装器,而不是直接发送到您的命令。 您必须测试信号是否按预期传递到您的命令。
另请注意,这为超时/终止提供了背景。 "等待"告诉脚本等到第一个后台进程完成,所以你的命令要么自己完成,要么它被超时杀死......然后脚本继续wait
之后的任何内容。 如果命令自行完成,则会遇到$pid被回收用于另一个进程的潜在问题。 解决这个问题留给读者作为练习。 :-)
我认为您在此示例中查找的是临时文件,而不是管道。在大多数情况下,您希望并行执行管道。在您的情况下(性能分析),以及前面的命令在执行后面的命令之前应该成功时,顺序操作是可取的。我建议使用mktemp
来实现此效果。在这个例子中,我不知道有什么方法可以通过进程替换或mkfifo
来使用 FIFO,因为$run_command
总是依赖于 tar
的输出。