-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtimeout3-v2
executable file
·93 lines (77 loc) · 2.54 KB
/
timeout3-v2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/bin/bash
#
# The Bash script executes a command with a time-out.
# Based on the Bash documentation example.
#
# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
# is blocked, then the subsequent SIGKILL (9) terminates it.
#
# Dmitry V Golovashkin <golovashkin at gmail.com>
# MIT Licensed in 2016
#
script_name="${0##*/}"
# Default values.
readonly param_timeout=5
readonly param_interval=1
readonly param_delay=1
declare -i timeout=param_timeout
declare -i interval=param_interval
declare -i delay=param_delay
blue="$(tput setaf 4)"
bold_red="$(tput bold; tput setaf 1)"
off="$(tput sgr0)"
function print_usage() {
cat <<EOF
Synopsis: $script_name [-t timeout] [-i interval] [-d delay] command
Executes the 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.
$blue-t timeout$off
Number of seconds to wait for command completion.
Default value: $param_timeout seconds. In some practical situations
this value ${bold_red}must$off be increased (for instance -t 180) to allow
the command to complete.
$blue-i interval$off
Interval between checks if the process is still alive.
Positive integer, default value: $param_interval seconds.
Default value is OK for most situations.
$blue-d delay$off
Delay between posting the SIGTERM signal and destroying the process by
SIGKILL. Default value: $param_delay seconds.
Default value is OK for most situations.
As of today, Bash does not support floating point arithmetic (sleep does),
therefore all time values must be integers.
Dmitry Golovashkin (E-mail: [email protected])
EOF
exit 1 # No useful work was done.
}
# Options.
while getopts ":t:i:d:" option; do
case "$option" in
t) timeout=$OPTARG ;;
i) interval=$OPTARG ;;
d) delay=$OPTARG ;;
*) print_usage ;;
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
print_usage
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 "$@"