Project

General

Profile

Statistics
| Branch: | Revision:

cool / src / lib / GMLMIP-0.1 / timeoutwrapper.sh @ 7c4d2eb4

History | View | Annotate | Download (2.6 KB)

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

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

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

    
19
declare -i DEFAULT_TIMEOUT=9
20
declare -i DEFAULT_INTERVAL=1
21
declare -i DEFAULT_DELAY=1
22

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

    
30
function printUsage() {
31
    cat <<EOF
32

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

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

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

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

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

    
56
# Options.
57
while getopts ":t:i:d:" option; do
58
    case "$option" in
59
        t) timeout=$OPTARG ;;
60
        i) interval=$OPTARG ;;
61
        d) delay=$OPTARG ;;
62
        *) printUsage; exit 1 ;;
63
    esac
64
done
65
shift $((OPTIND - 1))
66

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

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

    
78
    while ((t > 0)); do
79
        sleep $interval
80
        kill -0 $$ || exit 0
81
        ((t -= interval))
82
    done
83

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

    
91
exec "$@"