92 lines
2.5 KiB
Bash
92 lines
2.5 KiB
Bash
#!/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 (E-mail: dvg@ieee.org)
|
|
#
|
|
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: dvg@ieee.org)
|
|
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 "$@"
|
|
|