HiveBrain v1.2.0
Get Started
← Back to all entries
debugbashMinor

forever.sh - should keep a process alive forever

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
processkeepaliveforevershould

Problem

This script's only responsibility is to keep a process alive. Forever.
It's sole dependencies shall be bash and coreutils. I'm not sure if it would be compatible with sh, that would be even better.

``
#!/bin/bash
#
# (c) Netcetera AG
# Author: Christian Mäder
date="10.07.2015"
version="1.0"
#

respawn() {
while true; do
$myprocess
exit_code=$?

now=
date +"%Y-%m-%dT%H:%M:%S%z"`

if [ $exit_code -ne 0 ] || [ $force -eq 1 ]; then
if [ $quite -eq 0 ]; then
echo "$now | service $myprocess crashed with code $?. Restarting after ${timeout}s." >&2
fi
sleep $timeout
else
break
fi
done
}

help() {
echo "Usage: $1 [-f] [-q] [-t #] \"command\""
echo " $1 -v"
echo " $1 -h"
echo
echo " -v : Shows the version of this tool."
echo " -h : Shows this help text."
echo " -f : Restart the program even if it exited with an exit"
echo " status of 0."
echo " -q : If set, this script won't write anything to stdout or stderr."
echo " -t # : Seconds for how long the script should wait until"
echo " the restart happend."
echo " command : The command to execute continuously until it exits"
echo " gracefully or forever if -f is set."
echo
echo "Example: $1 -f -t 2 \"echo hello, see you again in two.\""
}

about() {
echo "Respawns a process which dies. Hence it keeps it runnig forever."
echo "Version $version from $date."
}

while true; do
case "$1" in
"--help")
help $0
break
;;
"-h")
help $0
break
;;
"-v")
about
break
;;
"-q")
quite=1
shift
;;
"-f")
force=1
s

Solution

By quite, you mean quiet, I think. You also have a typo with "runnig".

The script would be better self-documented if you put the about and help functions first.

In help, instead of echoing $1, which may be a path, it would be more conventional to echo just the basename.

It would be more elegant for the respawn function to accept the command as a parameter rather than using the $myprocess global variable. "Process", to me, implies a particular instance, i.e. a running program with a PID, so I'd rename myprocess to command. You only need to execute date if you're actually going to print a log message. I'd rearrange the conditions to emphasize how to exit the loop and to reduce nesting.

respawn() {
    command="$1"
    while true; do
        $command
        exit_code=$?

        if [ $exit_code -eq 0 -a $force -ne 1 ]; then
            break
        elif [ $quiet -ne 1 ]; then
            echo "`date +"%Y-%m-%dT%H:%M:%S%z"` | service $command exited with code $?. Restarting after ${timeout}s." >&2
        fi
        sleep $timeout
    done
}


In the argument parser, the --help and the -h conditions are identical. You should write

case "$1" in
    "--help"|"-h")
        help "$0"
        break
        …


Note that double-quoting variables is a good habit.

I don't believe that the [[ $2 =~ '^[0-9]+$' ]] test is available in traditional Bourne shell. If portability is a concern, you could write the not-quite-equivalent test

case "$2" in
    [0-9]*) timeout=$2 ; shift
    ;;
esac
shift

Code Snippets

respawn() {
    command="$1"
    while true; do
        $command
        exit_code=$?

        if [ $exit_code -eq 0 -a $force -ne 1 ]; then
            break
        elif [ $quiet -ne 1 ]; then
            echo "`date +"%Y-%m-%dT%H:%M:%S%z"` | service $command exited with code $?. Restarting after ${timeout}s." >&2
        fi
        sleep $timeout
    done
}
case "$1" in
    "--help"|"-h")
        help "$0"
        break
        …
case "$2" in
    [0-9]*) timeout=$2 ; shift
    ;;
esac
shift

Context

StackExchange Code Review Q#103746, answer score: 4

Revisions (0)

No revisions yet.