【问题标题】:Bash timeout with piped input带有管道输入的 Bash 超时
【发布时间】:2012-06-10 20:21:36
【问题描述】:

有一个命令(比如 $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 实用程序)。

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

【问题讨论】:

  • “有脚本”不清楚。是这个调用脚本还是 $run_command 需要在超时后被杀死?
  • 不,是 $run_command 需要被杀死。谢谢,我会编辑问题

标签: bash timeout pipe tar


【解决方案1】:

以非常简单的形式,你可以像这样杀死调用脚本:

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

另请注意,这会导致超时/终止。 “等待”告诉脚本等到第一个后台进程完成,所以 either 您的命令自行完成 它被超时杀死......然后脚本继续到wait 之后的任何内容。如果命令自行完成,那么您就会遇到 $pid 被回收到另一个进程的潜在问题。解决这个问题留给读者作为练习。 :-)

【讨论】:

  • 在此示例中,tar 执行时间也将出现在 $timeout_period 中。这是我想避免的情况。
  • 当然,在你澄清你想要杀死什么之前,我写了这篇文章。如果您想完全排除 tar 对您时间的影响,您需要将数据存储在一个临时文件中。我会更新...
  • 在你回答之前,我澄清了我想在这个话题中被杀死的东西。不过还是谢谢。还有,为什么需要trap?临时文件应该在父进程完成后消失,不是吗?
  • 在 shell 脚本中?有些东西必须删除一个临时文件。如果不是陷阱,什么会移除它?此外,对您的问题进行了编辑,以澄清您在最初回答四个小时后想要杀死的内容。
  • @ghoti 感谢您提供如此详细的答案。我会把你的标记为答案。关于澄清要被杀的东西-我的错,对不起。我只是说不清楚。
【解决方案2】:

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

【讨论】:

  • 我通常为此使用tempfile,但我真的不知道为什么。 mktemp 更好吗?
  • 您建议将 $1 的内容解压缩到 tempfile 中,然后像这样使用 smth /usr/bin/time -f "%e" --output=$time_output -- $run_command &lt; $tempfile_name ?
  • 是的,我会先使用mktemp 获取一个安全文件以解压到,然后按照您说的执行$run_command
  • @StephenNiedzielski:+1。嗯,谁知道?供未来读者参考,Russ Allbery 对该主题的看法见lists.debian.org/debian-devel/2006/12/msg00040.html。 (顺便说一句,奥尔伯里先生写的几乎所有主题的几乎所有内容都值得一读。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
相关资源
最近更新 更多