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

建议使用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技能达到了极限。


当前回答

有点俗气,但很管用。不工作,如果你有其他前台进程(请帮我修复这个!)

sleep TIMEOUT & SPID=${!}; (YOUR COMMAND HERE; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}

实际上,我认为你可以反过来,满足你的“奖金”标准:

(YOUR COMMAND HERE & SPID=${!}; (sleep TIMEOUT; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}) < asdf > fdsa

其他回答

超时可能是要尝试的第一种方法。如果超时,您可能需要执行通知或其他命令。经过相当多的搜索和实验,我想出了这个bash脚本:

if 
    timeout 20s COMMAND_YOU_WANT_TO_EXECUTE;
    timeout 20s AS_MANY_COMMANDS_AS_YOU_WANT;
then
    echo 'OK'; #if you want a positive response
else
    echo 'Not OK';
    AND_ALTERNATIVE_COMMANDS
fi

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

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

我提出了一个问题,以保留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

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

你完全可以用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中忘记了_。

有点俗气,但很管用。不工作,如果你有其他前台进程(请帮我修复这个!)

sleep TIMEOUT & SPID=${!}; (YOUR COMMAND HERE; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}

实际上,我认为你可以反过来,满足你的“奖金”标准:

(YOUR COMMAND HERE & SPID=${!}; (sleep TIMEOUT; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}) < asdf > fdsa