超时在bash命令没有不必要的延误 [英] Timeout a command in bash without unnecessary delay

查看:498
本文介绍了超时在bash命令没有不必要的延误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This answer to Command line command to auto-kill a command after a certain amount of time

提出了一个1线法从bash命令行超时一个长期运行的命令:

proposes a 1-line method to timeout a long-running command from the bash command line:

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

但它可能是一个给定的长期运行命令可以完成超过超时早。 (我们称之为典型的,长期运行,但是,有时候快命令,或 tlrbsf 的乐趣。)

所以,这个漂亮的1班轮方法有几个问题。首先,睡眠不是有条件的,这样的设置采取完成序列时的不良下限。考虑30秒或2米的,甚至不少于五米的睡眠时的 tlrbsf 的2秒&MDASH命令完成;极不可取的。其次,是无条件的,因此,此序列将试图杀死一个非运行的进程和抱怨它。

So this nifty 1-liner approach has a couple of problems. First, the sleep isn't conditional, so that sets an undesirable lower bound on the time taken for the sequence to finish. Consider 30s or 2m or even 5m for the sleep, when the tlrbsf command finishes in 2 seconds — highly undesirable. Second, the kill is unconditional, so this sequence will attempt to kill a non-running process and whine about it.

所以...

有没有办法以超时典型,长期运行,但是,有时快(tlrbsf的)命令

Is there a way to timeout a typically-long-running-but-sometimes-fast ("tlrbsf") command that


  • 有一个bash实现(其他问题已经有Perl的和C答案)

  • 将终止在这两个早期: tlrbsf 的程序终止,或超时已过

  • 不会杀不存在/不运行的进程(或者可选:不会的抱怨的又不好杀)

  • 不必是一个1衬垫

  • 可以的Cygwin或Linux下运行

  • has a bash implementation (the other question already has Perl and C answers)
  • will terminate at the earlier of the two: tlrbsf program termination, or timeout elapsed
  • will not kill non-existing/non-running processes (or, optionally: will not complain about a bad kill)
  • doesn't have to be a 1-liner
  • can run under Cygwin or Linux

...而且,奖励积分,运行的 tlrbsf 的在前台指挥的睡眠或额外的过程在后台,这样的标准输入/标准输出/标准错误的 tlrbsf 的命令可以重定向,一样的,如果它被直接运行?

... and, for bonus points, runs the tlrbsf command in the foreground and any 'sleep' or extra process in the background, such that the stdin/stdout/stderr of the tlrbsf command can be redirected, same as if it had been run directly?

如果有,请分享你的code。如果不是,请说明原因。

If so, please share your code. If not, please explain why.

我花了一段时间试图破解上述的例子,但我打我的bash技巧的极限。

I have spent awhile trying to hack the aforementioned example but I'm hitting the limit of my bash skills.

推荐答案

我觉得这是precisely你问的:

I think this is precisely what you are asking for:

<一个href=\"http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3\">http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3

#!/bin/bash
#
# The Bash shell script executes a command with a time-out.
# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
# is blocked, then the subsequent SIGKILL (9) terminates it.
#
# Based on the Bash documentation example.

# Hello Chet,
# please find attached a "little easier"  :-)  to comprehend
# time-out example.  If you find it suitable, feel free to include
# anywhere: the very same logic as in the original examples/scripts, a
# little more transparent implementation to my taste.
#
# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>

scriptName="${0##*/}"

declare -i DEFAULT_TIMEOUT=9
declare -i DEFAULT_INTERVAL=1
declare -i DEFAULT_DELAY=1

# Timeout.
declare -i timeout=DEFAULT_TIMEOUT
# Interval between checks if the process is still alive.
declare -i interval=DEFAULT_INTERVAL
# Delay between posting the SIGTERM signal and destroying the process by SIGKILL.
declare -i delay=DEFAULT_DELAY

function printUsage() {
    cat <<EOF

Synopsis
    $scriptName [-t timeout] [-i interval] [-d delay] command
    Execute a command with a time-out.
    Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM
    signal is blocked, then the subsequent SIGKILL (9) terminates it.

    -t timeout
        Number of seconds to wait for command completion.
        Default value: $DEFAULT_TIMEOUT seconds.

    -i interval
        Interval between checks if the process is still alive.
        Positive integer, default value: $DEFAULT_INTERVAL seconds.

    -d delay
        Delay between posting the SIGTERM signal and destroying the
        process by SIGKILL. Default value: $DEFAULT_DELAY seconds.

As of today, Bash does not support floating point arithmetic (sleep does),
therefore all delay/time values must be integers.
EOF
}

# Options.
while getopts ":t:i:d:" option; do
    case "$option" in
        t) timeout=$OPTARG ;;
        i) interval=$OPTARG ;;
        d) delay=$OPTARG ;;
        *) printUsage; exit 1 ;;
    esac
done
shift $((OPTIND - 1))

# $# should be at least 1 (the command to execute), however it may be strictly
# greater than 1 if the command itself has options.
if (($# == 0 || interval <= 0)); then
    printUsage
    exit 1
fi

# kill -0 pid   Exit code indicates if a signal may be sent to $pid process.
(
    ((t = timeout))

    while ((t > 0)); do
        sleep $interval
        kill -0 $$ || exit 0
        ((t -= interval))
    done

    # Be nice, post SIGTERM first.
    # The 'exit 0' below will be executed if any preceeding command fails.
    kill -s SIGTERM $$ && kill -0 $$ || exit 0
    sleep $delay
    kill -s SIGKILL $$
) 2> /dev/null &

exec "$@"

这篇关于超时在bash命令没有不必要的延误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆