This script is running indefinitely as the Linux background process.
I have put an enormous effort to make this POSIX shell script containing an infinite loop shut down tidily along with the operating system (TERM signal) and by me sending it a HUP signal.
Ok, we don't call it exception-handling, but I didn't find any other suitable tag for it. Also did not find an appropriate tag for the script's termination.
We have reviewed two big pieces of the puzzle already, so I cut it out.
readonly script_one_instance_lockfile="${HOME}/.PROGRAM/$(basename "${0}").lock"
# this is long and not relevant to this question, it does as its name says
# you can find a review on it here: https://codereview.stackexchange.com/q/204828/104270
print_error_and_exit() { ... }
is_number()
{
[ "${1}" -eq "${1}" ] 2> /dev/null
}
# purpose is clear, i.e. to clean up some temp, lock files
# which were created during script execution and should not be left in place
cleanup_on_exit()
{
[ -f "${script_one_instance_lockfile}" ] && rm "${script_one_instance_lockfile}"
}
# this function is merely for future expansions of the script
# it might very well be different from cleanup_on_exit
cleanup_on_signal()
{
cleanup_on_exit
}
# here we define a generic function to handle signals
# treat them as errors with appropriate messages
# example calls:
# kill -15 this_script_name # POSIX; all shells compatible
# kill -TERM this_script_name # Bash and alike; newer shells
signal_handler_generic()
# expected arguments:
# $1 = signal code
{
# check if exactly one argument has been passed
[ "${#}" -eq 1 ] || print_error_and_exit "signal_handler_generic()" "Exactly one argument has not been passed!\\n\\tPassed: ${*}"
# check if the argument is a number
is_number "${1}" || print_error_and_exit "signal_handler_generic()" "The argument is not a number!\\n\\Signal code expected.\\n\\tPassed: ${1}"
number_argument=${1}
signal_code=${number_argument}
case "${number_argument}" in
1 ) signal_human_friendly='HUP' ;;
2 ) signal_human_friendly='INT' ;;
3 ) signal_human_friendly='QUIT' ;;
6 ) signal_human_friendly='ABRT' ;;
15) signal_human_friendly='TERM' ;;
* ) signal_human_friendly='' ;;
esac
if [ "${signal_human_friendly}" = "" ]
then
print_error_and_exit "signal_handler_generic()" "Given number code (${signal_code}) does not correspond to supported signal codes."
else
# tidy up any temp or lock files created along the way
cleanup_on_signal
# print human friendly and number signal code that has been caught
print_error_and_exit "\\ntrap()" "Caught ${signal_human_friendly} termination signal ${signal_code}.\\n\\tClean-up finished. Exiting. Bye!"
fi
}
# use the above function for signal handling;
# note that the SIG* constants are undefined in POSIX,
# and numbers are to be used for the signals instead
trap 'signal_handler_generic 1' 1
trap 'signal_handler_generic 2' 2
trap 'signal_handler_generic 3' 3
trap 'signal_handler_generic 6' 6
trap 'signal_handler_generic 15' 15
# this is long and not relevant to this question, it does as its name says
# you can find a review on it here: https://codereview.stackexchange.com/q/213156/104270
is_java_program_running() { ... }
####################
### MAIN PROGRAM ###
####################
if [ -f "${script_one_instance_lockfile}" ]
then
# if one instance of this script is already running, quit to shell
print_error_and_exit "\\nmain()" "One instance of this script should already be running.\\n\\tLock file: ${script_one_instance_lockfile}\\n\\tMore than one instance is not allowed. Exiting."
else
# create a .lock file for one instance handling
touch "${script_one_instance_lockfile}"
fi
# keep the PROGRAM alive forever, check in 5 seconds interval
while true
do
sleep 5s
if ! is_java_program_running "${PROGRAM_java_process_identifier}"
then
my_date_time=$(date +%Y-%m-%d_%H:%M:%S)
printf '%s %s\n' "${my_date_time}" "(re-)starting PROGRAM"
( /full/path/to/program > /dev/null 2>&1 & )
fi
done
# ordinary scripts don't have infinite loops
# this code shall be unreachable, but it is good to have it here since I will be
# copying / reusing the script and I would definitely forget on this
cleanup_on_exit
kill
that doesn't deal with signal names?man 7 signal
says that POSIX does define those names. \$\endgroup\$