在bash中,如何在不必要的延迟情况下超时执行命令?

377

这个答案针对命令行命令在一定时间后自动终止执行提出了一种一行代码的方法,用于从bash命令行超时终止长时间运行的命令:

( /path/to/slow command with options ) & sleep 5 ; kill $!

但是一个长时间运行的命令可能会在超时之前完成。
(我们称其为“通常长时间运行但有时很快”的命令,或者为了好玩而称之为tlrbsf。)

因此,这种巧妙的一行代码方法存在几个问题。
首先,sleep不是条件性的,因此它设置了序列完成所需的不良下限时间。当tlrbsf命令在2秒内完成时,请考虑30秒、2分钟甚至5分钟的睡眠时间- 这是非常不理想的。
其次,kill是无条件的,因此该序列将尝试杀死一个非运行进程并抱怨。

所以...

是否有一种方法可以超时一个通常长时间运行但有时很快("tlrbsf")的命令,使其

  • 具有bash实现(其他问题已经有Perl和C的答案)
  • 将在以下两者中较早终止:tlrbsf程序终止,或超时时间到期
  • 不会杀死不存在/未运行的进程(或者,可选:不会抱怨错误的杀死)
  • 不必是1行代码
  • 可以在Cygwin或Linux下运行

...并且,额外加分项:

  • 在前台中运行tlrbsf命令
  • 任何“睡眠”或额外进程在后台运行

这样,tlrbsf 命令的标准输入/输出/错误可以被重定向,就像直接运行一样吗?

如果是这样,请分享你的代码。如果不是,请解释原因。

我已经花了一段时间尝试破解上述示例,但我达到了我的 Bash 技能极限。


5
另一个类似的问题:https://dev59.com/gXRB5IYBdhLWcg3wv5o_(但我认为这里的“timeout3”答案更好)。 - system PAUSE
2
有没有不使用GNU timeout实用程序的原因? - Chris Johnson
2
timeout 真是太棒了!你甚至可以将其用于 多个命令(多行脚本):https://dev59.com/EloT5IYBdhLWcg3w8jJm#61888916 - Noam Manos
24个回答

-1

@loup的回答的基础上...

如果你想要超时一个进程并且不显示kill job/pid输出,运行以下命令:

( (sleep 1 && killall program 2>/dev/null) &) && program --version 

这将把后台进程放入子shell中,以便您不会看到作业输出。


-2
一种非常简单的方式:
# command & sleep 5; pkill -9 -x -f "command"

使用pkill(选项-f),您可以杀死带有参数的特定命令,或指定-n以避免杀死旧进程。


你意识到这基本上就是OP在他的帖子中所说的,而他表示他不想要的,对吧?因为它总是等待完整的睡眠延迟。 - Etan Reisner

-3
在99%的情况下,答案并不是实现任何超时逻辑。 超时逻辑几乎在任何情况下都是一个红色警告信号,表示有其他问题需要解决。
你的进程有时会在n秒后挂起或中断吗? 那么找出原因并修复它。
另外,要正确执行strager的解决方案,您需要使用wait "$SPID"而不是fg 1,因为在脚本中您没有作业控制(尝试打开它是愚蠢的)。 此外,fg 1依赖于您之前没有在脚本中启动任何其他作业这一事实,这是一个错误的假设。

4
有了对源代码的100%访问权限(包括大部分硬件,如网络交换机),我同意可能会有比超时更好的解决方案。但是,当“tlrbsf”是闭源的、仅有二进制版本时,有时你必须绕过这种限制。 - system PAUSE
@lhunath,“在脚本中,你没有作业控制(试图打开它是愚蠢的)”--请在这里澄清:https://dev59.com/inRB5IYBdhLWcg3wNk53 - system PAUSE
@system 暂停:回复https://dev59.com/inRB5IYBdhLWcg3wNk53#690297是正确的,我也进行了评论。 - lhunath
31
Lhunath,你所说的话没有意义。有许多情况下超时是一个很好的选择,例如每当你必须通过网络传输数据时。 - Nate Murray
一个例外情况:你正在编写测试脚本,以检查已经运行的软件是否存在超时问题。 - peterh
一个例子是在某些情况下traceroute会一直运行。包括,截至本文撰写时,traceroute example.com - Beejor

-5

我有一个定时任务调用一个 PHP 脚本,有时候会卡在 PHP 脚本上。这个解决方案对我来说非常完美。

我使用:

scripttimeout -t 60 /script.php

3
ScriptTimeout 是什么?ScriptTimeout 是指在执行脚本时,等待浏览器响应的最长时间。当脚本运行超过设定的这个时间限制时,就会抛出一个超时异常并停止脚本的执行。 - rudolfbyker
这并不是一个有帮助的答案,我认为这可以保留,因为它根本没有解释。 - Snorik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接