HRM
HRM

Reputation: 2127

How to start a Linux service (Bash script) containing an infinite loop in the start method

I'm trying to check whether one of my process is running or not every 10 minutes and if not, restart that process. I want this script to start automatically when the system boots up, so I go for services in Linux.

So here is what I did:

Everything was working fine, except one thing. If I do ./myservice start, then the terminal hangs up (it should as it's running an infinite loop), but if I do a ctrl-z then the script is killed and my task won't perform. How can I make this script to start from the terminal and execute normally? (like, say, ./etc/init.d/mysql start). Maybe do the process in the background and return.

My Bash script is given below:

#!/bin/bash

# Start the service
start() {

    #Process name that need to be monitored
    process_name="mysqld"

    #Restart command for process
    restart_process_command="service mysql start"

    #path to pgrep command
    PGREP="/usr/bin/pgrep"

    #Initially, on startup do create a testfile to indicate that the process
    #need to be monitored. If you dont want the process to be monitored, then
    #delete this file or stop this service
        touch /tmp/testfile

        while true;
        do

        if [ ! -f /tmp/testfile ]; then
             break
        fi

        $PGREP ${process_name}

        if [ $? -ne 0 ] # if <process> not running
        then
        # restart <process>
        $restart_process_command
        fi

        #Change the time for monitoring process here (in secs)
        sleep 1000

    done
}

stop() {
       echo "Stopping the service"
       rm -rf /tmp/testfile
}
### main logic ###
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        ;;
  restart|reload|condrestart)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|reload|status}"
        exit 1
esac
exit 0

Upvotes: 3

Views: 12584

Answers (3)

dsumsky
dsumsky

Reputation: 377

In my opinion, it's worth scheduling such kind of script with cron scheduler rather than writing standalone init script.

cat > /usr/local/bin/watch-mysql.sh <<-"__SEOF__"
    #!/bin/sh
    set -e

    # if this file exists monitoring is stopped
    if [ -f /var/run/dont-watch-mysql.lck ]; then
      exit 0
    fi

    process_name="mysqld"        
    restart_process_command="service mysql restart"
    PGREP="/usr/bin/pgrep"

    $PGREP ${process_name}

    if [ $? -ne 0 ] # if <process> not running
    then
        # restart <process>
        $restart_process_command
    fi
__SEOF__

# make the script executable
chmod u+x /usr/local/bin/watch-mysql.sh

# schedule the script to run every 10 minutes
(crontab -l ; echo "*/10 * * * * /usr/local/bin/watch-mysql.sh") | uniq - | crontab -

If you simply create the file /var/run/watch-mysql.lck it won't be monitored.

Upvotes: 2

devnull
devnull

Reputation: 123488

Execute the function in the background. Say:

start)
      start &

instead of saying:

start)
      start

Upvotes: 3

Netch
Netch

Reputation: 4562

You should detach the cycle itself to a separated script and run the latter script from the startup one according to the manner preferred in your distribution for a non-self-daemonizing application.

Please notice that your current startup script will likely hang a system boot up even if not run from terminal, at least for most traditional startups (I won't say for systemd and other contemporary ones which could start multiple scripts in parallel, but they definitely will think startup isn't finished). But you could miss it if e.g. logged in via ssh because sshd will start before your script.

Upvotes: 1

Related Questions