0

有一个命令(比如 $run_command),它必须在超时后被杀死。解决方案非常简单——我可以使用coreutils中的timeout或其他 stackoverflow 主题中的timeout3。但是我的命令像这样从 untar pipe smth 接收它的标准输入

tar -xO -f "$1" | /usr/bin/time -f "%e" --output=$time_output -- $run_command

其中$run-command是我的命令,还测量了执行时间(使用time实用程序)。

那么,问题是避免在超时实用程序中包含解压时间的最佳方法是什么?

4

2 回答 2

3

以非常简单的形式,您可以像这样终止调用脚本:

#!/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 包装器,而不是直接发送到您的命令。您必须测试信号是否按预期传递到您的命令。

Note also that this backgrounds the timeout/kill. The "wait" tells the script to wait until the first background process is finished, so either your command finishes by itself or it gets killed by the timeout ... and then the script proceeds to anything after the wait. If the command finishes by itself, then that's where you run into potential issues with $pid being recycled for another process. Solving that is left as an exercise for the reader. :-)

于 2012-06-11T03:20:42.800 回答
1

我认为您在此示例中要查找的是临时文件,而不是管道。在大多数情况下,您希望并行执行管道。在您的情况(分析)以及前面的命令应该在执行后面的命令之前成功时,顺序操作是可取的。我建议使用mktemp此效果。mkfifo对于此示例,我不知道通过进程替换或 with 使用 FIFO 的方法,因为$run_command它始终依赖于tar.

于 2012-06-11T02:02:51.047 回答