# Lock file and interrupt signals in POSIX shell script running indefinitely

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

• Have you actually found a Unix or kill that doesn't deal with signal names? man 7 signal says that POSIX does define those names. – Oh My Goodness Feb 11 at 11:19
• @OhMyGoodness Renamed it shortly after posting the question. – Vlastimil Feb 11 at 11:28