这回答命令行命令自动杀死一个命令后,一定的时间

建议使用1行方法使bash命令行中运行的命令超时:

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

但是,给定的“长时间运行”命令可能会在超时之前完成。 (让我们称它为“通常运行时间长但有时很快”的命令,或者简称为tlrbsf。)

所以这个漂亮的一行方法有几个问题。 首先,睡眠不是有条件的,因此在序列完成所花费的时间上设置了一个不希望的下界。当tlrbsf命令在2秒内完成时,考虑30秒或2m甚至5m的睡眠时间——这是非常不可取的。 其次,kill是无条件的,因此该序列将尝试kill一个未运行的进程并抱怨它。

所以…

是否有一种方法可以超时一个典型的长时间运行但有时快速(“tlrbsf”)命令

有一个bash实现(另一个问题已经有Perl和C的答案) 将终止在较早的两个:TLRBSF程序终止,或超时过去 不会杀死不存在/不运行的进程(或者,可选:不会抱怨失败的杀死) 不一定非要是一行字 可以在Cygwin或Linux下运行吗

... 还有,为了加分

在前台运行TLRBSF命令 任何“睡眠”或额外的进程在后台

这样,TLRBSF命令的stdin/stdout/stderr可以重定向,就像它已经直接运行吗?

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

我花了一段时间试图破解前面提到的例子,但我的bash技能达到了极限。


当前回答

使用实例在1秒后使slows命令超时。

timeout 1 || echo "I failed, maybe due to timeout "

要确定命令是否超时或由于自身原因失败,请检查状态代码是否为124:

# ping the address 8.8.8.8 for 3 seconds, but timeout after only 1 second
timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process Timed Out!'
else
echo 'Process did not timeout. Something else went wrong.'
fi
exit $EXIT_STATUS

注意,当退出状态为124时,您不知道它是由于您的timeout命令而超时,还是命令本身由于它自己的一些内部超时逻辑而终止,然后返回124。不过,在这两种情况下,您都可以安全地假设发生了某种超时。

其他回答

您可能正在coreutils中寻找timeout命令。因为它是coreutils的一部分,所以技术上它是一个C解决方案,但它仍然是coreutils。信息超时查看更多详细信息。 这里有一个例子:

timeout 5 /path/to/slow/command with options

timeout命令本身有一个——前台选项。这使得命令“在不直接从shell提示符运行超时时”与用户交互。

timeout --foreground the_command its_options

我认为提问者一定知道timeout命令的非常明显的解决方案,但出于这个原因,他要求另一种解决方案。超时没有为我工作时,我调用它使用popen,即。“不是直接从壳里取的。”然而,我不认为这就是提问者的原因。看看它的手册页。

如果您已经知道要在超时后终止的程序(假设是程序)的名称(例如3秒),我可以提供一个简单但有点脏的替代解决方案:

(sleep 3 && killall program) & ./program

如果我用系统调用来调用基准测试进程,这将非常有效。

你完全可以用bash 4.3及以上版本来完成:

_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; r=$?; kill -9 `jobs -p`; exit $r; ) }

Example: _timeout 5 longrunning_command args Example: { _timeout 5 producer || echo KABOOM $?; } | consumer Example: producer | { _timeout 5 consumer1; consumer2; } Example: { while date; do sleep .3; done; } | _timeout 5 cat | less Needs Bash 4.3 for wait -n Gives 137 if the command was killed, else the return value of the command. Works for pipes. (You do not need to go foreground here!) Works with internal shell commands or functions, too. Runs in a subshell, so no variable export into the current shell, sorry.

如果你不需要返回代码,这可以变得更简单:

_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; kill -9 `jobs -p`; ) }

注:

严格来说你不需要;在;),但是它使事情更加一致;}案例。set +b可能也可以不用,但小心为妙。 除了——forground(可能),你可以实现所有的变量超时支持。——保存状态有点困难,不过。这是留给读者的练习;)

这个配方可以在壳中“自然地”使用(与flock fd一样自然):

(
set +b
sleep 20 &
{
YOUR SHELL CODE HERE
} &
wait -n
kill `jobs -p`
)

但是,如上所述,不能自然地以这种方式将环境变量重新导出到外壳中。

编辑:

真实世界的例子:超时__git_ps1以防它花费太长时间(对于像缓慢的SSHFS-Links这样的事情):

eval "__orig$(declare -f __git_ps1)" && __git_ps1() { ( git() { _timeout 0.3 /usr/bin/git "$@"; }; _timeout 0.3 __orig__git_ps1 "$@"; ) }

Edit2:错误修复。我注意到退出137是不需要的,同时使_timeout不可靠。

Edit3: git是一个顽固分子,所以它需要双重技巧才能令人满意地工作。

Edit4:在真实GIT示例的第一个_timeout中忘记了_。

我提出了一个问题,以保留shell上下文和允许超时,唯一的问题是它将停止脚本执行超时-但这是我提出的需求很好:

#!/usr/bin/env bash

safe_kill()
{
  ps aux | grep -v grep | grep $1 >/dev/null && kill ${2:-} $1
}

my_timeout()
{
  typeset _my_timeout _waiter_pid _return
  _my_timeout=$1
  echo "Timeout($_my_timeout) running: $*"
  shift
  (
    trap "return 0" USR1
    sleep $_my_timeout
    echo "Timeout($_my_timeout) reached for: $*"
    safe_kill $$
  ) &
  _waiter_pid=$!
  "$@" || _return=$?
  safe_kill $_waiter_pid -USR1
  echo "Timeout($_my_timeout) ran: $*"
  return ${_return:-0}
}

my_timeout 3 cd scripts
my_timeout 3 pwd
my_timeout 3 true  && echo true || echo false
my_timeout 3 false && echo true || echo false
my_timeout 3 sleep 10
my_timeout 3 pwd

输出:

Timeout(3) running: 3 cd scripts
Timeout(3) ran: cd scripts
Timeout(3) running: 3 pwd
/home/mpapis/projects/rvm/rvm/scripts
Timeout(3) ran: pwd
Timeout(3) running: 3 true
Timeout(3) ran: true
true
Timeout(3) running: 3 false
Timeout(3) ran: false
false
Timeout(3) running: 3 sleep 10
Timeout(3) reached for: sleep 10
Terminated

当然,我认为有一个目录叫做脚本