Bash-4.2 distribution sources and documentation
[platform/upstream/bash.git] / examples / scripts / timeout3
1 #!/bin/bash
2 #
3 # The Bash script executes a command with a time-out.
4 # Based on the Bash documentation example.
5 #
6 # Upon time-out expiration SIGTERM (15) is sent to the process.  If the signal
7 # is blocked, then the subsequent SIGKILL (9) terminates it.
8 # Dmitry V Golovashkin (E-mail: dvg@ieee.org)
9 #
10 script_name="${0##*/}"
11
12 # Default values.
13 readonly param_timeout=5
14 readonly param_interval=1
15 readonly param_delay=1
16
17 declare -i timeout=param_timeout
18 declare -i interval=param_interval
19 declare -i delay=param_delay
20
21 blue="$(tput setaf 4)"
22 bold_red="$(tput bold; tput setaf 1)"
23 off="$(tput sgr0)"
24
25 function print_usage() {
26 cat <<EOF
27
28 Synopsis:  $script_name [-t timeout] [-i interval] [-d delay] command
29
30 Executes the command with a time-out.  Upon time-out expiration SIGTERM (15) is
31 sent to the process.  If SIGTERM signal is blocked, then the subsequent SIGKILL
32 (9) terminates it.
33
34 $blue-t timeout$off
35     Number of seconds to wait for command completion.
36     Default value: $param_timeout seconds.  In some practical situations
37     this value ${bold_red}must$off be increased (for instance -t 180) to allow
38     the command to complete.
39
40 $blue-i interval$off
41     Interval between checks if the process is still alive.
42     Positive integer, default value: $param_interval seconds.
43     Default value is OK for most situations.
44
45 $blue-d delay$off
46     Delay between posting the SIGTERM signal and destroying the process by
47     SIGKILL.  Default value: $param_delay seconds.
48     Default value is OK for most situations.
49
50 As of today, Bash does not support floating point arithmetic (sleep does),
51 therefore all time values must be integers.
52 Dmitry Golovashkin (E-mail: dvg@ieee.org)
53 EOF
54 exit 1 # No useful work was done.
55 }
56
57 # Options.
58 while getopts ":t:i:d:" option; do
59     case "$option" in
60         t) timeout=$OPTARG ;;
61         i) interval=$OPTARG ;;
62         d) delay=$OPTARG ;;
63         *) print_usage ;;
64     esac
65 done
66 shift $((OPTIND - 1))
67
68 # $# should be at least 1 (the command to execute), however it may be strictly
69 # greater than 1 if the command itself has options.
70 if (($# == 0 || interval <= 0)); then
71     print_usage
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 "$@"
92