Tutorial

How To Write a Bash Script To Restart Server Programs

Published on August 30, 2012
How To Write a Bash Script To Restart Server Programs

To ensure that the most imperative programs remain online as much as possible (even after a server crash or reboot), one can create a short bash script to check if the program is running, and if it is not, to launch it. By using cron to schedule the script to be executed on a regular basis, we can make sure that program relaunches whenever it goes down.

Bash Script

The first step in this process is to create the script itself. There are a variety of programs such as upstart, supervisor, and monit, that have the capability to start and monitor applications on a virtual private server in a very nuanced way— this bash script will simply provide an on switch.

Below is a sample script that starts apache if it finds it off.

nano launch.sh
#!/bin/sh

ps auxw | grep apache2 | grep -v grep > /dev/null

if [ $? != 0 ]
then
        /etc/init.d/apache2 start > /dev/null
fi

Once you have saved the script, you must give it executable permissions in order to be able to run it:

chmod +x launch.sh

Apache can be replaced with any required application. Should you want to set up the script for a variety of applications, you can create a new script for each one, placing it on its own line in the cron file.

Cron Setup

With the script in hand, we need to set up the schedule on which it will run. The cron utility allows us to schedule at what intervals the script should execute. Start by opening up the cron file:

crontab -e

Cron has a detailed explanation of how the timing system works at the beginning.

Once you know how often you want the script to run, you can write in the corresponding line.

The most often that the script can run in cron is every minute. Should you want to set up such a small increment, you can use this template:

* * * * * ~/launch.sh

Every five minutes would be set up like this:

*/5 * * * * ~/launch.sh

See More

Setting up this simple script will keep the program starting up after it shuts down for any reason. This is convenient as it will ensure that the longest time that a program will be down is for the interval of time that you specified in the cron configuration.

Should you need a program that is even slightly more subtle, you can set up the details of your startup with one of the several server monitoring programs (Supervisor, Upstart, or Monit).

By Etel Sverdlov

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Etel Sverdlov
Etel Sverdlov
See author profile
Category:
Tutorial

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Don’t you need to make sure that the script is executable by doing something like u+x ~/launch.sh?

alexdo
Site Moderator
Site Moderator badge
October 31, 2024

Yes, you’re correct! Before you can run a script from the command line or through a cron job, it needs to have the appropriate executable permissions. You can do this with the chmod command. Here’s how to ensure your script is executable:

  1. Make the Script Executable: Use the following command:
chmod +x /path/to/your/script/relaunch.sh

Replace /path/to/your/script/relaunch.sh with the actual path to your script.

  1. Verify Permissions: You can verify the permissions by running:
ls -l /path/to/your/script/relaunch.sh

The output should show something like -rwxr-xr-x, indicating that the script is executable.

Regards

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
October 21, 2013

@Marc: That is correct, I’ve updated the article. Thanks!

I’m using this script to restart mysql with no luck. Log says

/root/mysql-check.sh: 2: [: unexpected operator
alexdo
Site Moderator
Site Moderator badge
October 31, 2024

The error message you’re encountering (unexpected operator) typically arises from using [ for conditional tests in a shell script where the syntax is not correctly followed. In this case, it might be due to the way you’re checking the exit status of the previous command. In shell scripts, the correct syntax for string comparison is = or != rather than using == as you might in other programming languages.

Here’s a revised version of your script that includes proper syntax and adds some logging for troubleshooting:

#!/bin/sh

LOGFILE="/var/log/mysql-check.log"

# Check if MySQL is running
if ps aux | grep mysql | grep -v grep > /dev/null; then
    echo "$(date): MySQL is running." >> $LOGFILE
else
    echo "$(date): MySQL is not running, attempting to restart." >> $LOGFILE
    service mysql restart >> $LOGFILE 2>&1
    if [ $? -eq 0 ]; then
        echo "$(date): MySQL restarted successfully." >> $LOGFILE
    else
        echo "$(date): Failed to restart MySQL." >> $LOGFILE
    fi
fi

If the script does not work as expected, check the log file at /var/log/mysql-check.log for any output that may indicate what went wrong.

Regards

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
July 13, 2014

@robert: Can you pastebin the contents of /root/mysql-check.sh?

I’m trying to utilise this script and crontab to keep an eye on MySQL.

I couldn’t get the script to work.

#!/bin/sh

ps auxw | grep mysql | grep -v grep > /dev/null

if [ $? != 0 ]
then
        service mysql restart > /dev/null
fi

I’m very inexperienced with this stuff but reviewing the above shouldn’t it be:

if [ $? = 0 ]

I’m not really sure the significance of the $? in the above though I would assume it’s a print of the output from the previous command.

I’m probably wrong here but if MySQL is down and thus not printed in ps auxw and we’re removing the grep process too then isn’t an output of nothing what should be triggering the process restart?

EDIT: No that still doesn’t solve the problem. If I use = 0 the service reboots at every run of the script. If I use != 0 then the service never reboots. Confused.

alexdo
Site Moderator
Site Moderator badge
October 31, 2024

It sounds like you’re on the right track with your script, but let’s clarify how the logic should work and how the exit status $? is used.

  1. Exit Status $?: This special variable captures the exit status of the last command executed. In your case:

    • If ps auxw | grep mysql | grep -v grep finds a running MySQL process, it will exit with status 0.
    • If it does not find a running MySQL process (meaning MySQL is down), it will exit with a status 1 (or another non-zero value).
  2. Condition Logic:

    • You want to check if MySQL is not running to restart it. Therefore, your condition should check for a non-zero exit status (!= 0).
    • If the exit status is 0, it means MySQL is running, and you should not restart it.
    • If the exit status is 1, it means MySQL is not running, and you want to restart it.

Here’s the script with comments explaining each part:

#!/bin/sh

# Check if MySQL is running
ps auxw | grep mysql | grep -v grep > /dev/null

# Check the exit status of the previous command
if [ $? != 0 ]; then
    # If MySQL is not running (exit status != 0), restart it
    echo "MySQL is down, restarting..." >> /var/log/mysql-check.log
    service mysql restart >> /var/log/mysql-check.log 2>&1
else
    # If MySQL is running (exit status = 0), do nothing
    echo "MySQL is running." >> /var/log/mysql-check.log
fi
  • ps auxw | grep mysql | grep -v grep: This command lists all running processes and checks for “mysql”, filtering out the grep process itself.
  • > /dev/null: Suppresses output.
  • if [ $? != 0 ]: This checks if the exit status is not 0, indicating MySQL is not running.
  • The script appends logs to /var/log/mysql-check.log so you can track when it checks the status and any actions taken.

To set this script to run periodically (e.g., every minute), you can add it to your crontab:

  1. Open the crontab file:
crontab -e
  1. Add the following line to run your script every minute:
* * * * * /path/to/your/script/relaunch.sh
  • Log File: Make sure the log file exists and is writable by the user executing the cron job. If necessary, you can create it with:
sudo touch /var/log/mysql-check.log sudo chmod 664 /var/log/mysql-check.log
  • Script Permissions: Ensure the script has executable permissions:
chmod +x /path/to/your/script/relaunch.sh
  • Test Manually: You can test the script manually to see if it behaves as expected by running:
/path/to/your/script/relaunch.sh

Your original logic is correct. Keep the != 0 condition to restart MySQL when it’s not running. The added logging will help you diagnose what the script is doing when it runs via cron. If you still face issues, check the log file for entries and errors to help pinpoint the problem.

Regards

Anyone able to help on this?

@savage above had some good stuff and I modified it for systemd based Debian and to my liking as follows - this works, and no, I also could not get the original syntax to work.

#!/bin/sh

#functions

RESTART=“/bin/systemctl restart apache2.service” SERVICE=“apache2.service” LOGFILE=“/home/username/Desktop/apache.log”

#check for the word dead in the service output from systemctl

if

    systemctl status apache2.service | grep dead

then

    echo "User, apache2 failed at $(date), so I restarted it for you." >> $LOGFILE
    $RESTART >> $LOGFILE

else echo “User, apache2 was running as of $(date)” >> $LOGFILE

fi

Thanks for the tutorial of how to make a bash script. However for this case I would prefer something like “service apache2 status || service apache2 start” directly on the crontab line. I saw that trick here https://www.digitalocean.com/community/questions/how-do-you-check-mysql-status-via-cron?answer=18288

alexdo
Site Moderator
Site Moderator badge
October 31, 2024

You can simplify your cron job by using a one-liner directly in the crontab. This approach checks the status of the Apache service and starts it if it’s not running, all in one command.

* * * * * service apache2 status || service apache2 start

Regards

hello i add the commande and when i try to add cron tab i got this ? */1 * * * * ~/launch.sh -bash: */1: No such file or directory

alexdo
Site Moderator
Site Moderator badge
October 31, 2024

The error you’re encountering is due to how you’re trying to add the cron job. When you add a cron job, the timing syntax should be specified without any leading characters like */1. Also, ~ (the home directory shortcut) may not resolve properly in the cron environment.

Here’s how to properly set up your cron job:

  1. Specify the Full Path: Instead of using ~/launch.sh, specify the full path to your script. For example, if your script is located in /home/yourusername/launch.sh, you would use that full path.

  2. Cron Timing Syntax: If you want to run the script every minute, you can simply use * * * * * instead of */1 * * * *. They both serve the same purpose, but the former is more commonly used.

Regards

Sorry but it does not work… It doesn’t restart my programs…

alexdo
Site Moderator
Site Moderator badge
October 31, 2024

You can double check the syntax in your commands and also examine the command output and also service logs to see if there is anything wrong with the services itself before automating the process to restart them.

Regards

Some problem here too.

My script works just fine. It is in /etc/apache2/relaunch.sh, file permissions are

-rwxr-xr-x   1 root root   372 Feb 21 08:01 relaunch.sh*

here’s the script

#!/bin/sh
echo "running apache2 relaunch at $(date)" >> /var/log/uwe-crontab/crons.log
ps auxw | grep apache2 | grep -v grep > /dev/null

if [ $? != 0 ]
then
        /etc/init.d/apache2 restart >> /var/log/uwe-crontab/crons.log
        echo "apache relaunched at $(date)" >> /var/log/uwe-crontab/crons.log
else 
        echo "apache is running"  >> /var/log/uwe-crontab/crons.log
fi

I try to run it from root’s cron. Here’s the cron entry.

* * * * * sh /etc/apache2/relaunch.sh

Strangely, the script fires every minute and writes an entry into my log file without a problem, but won’t work correctly when it is run from Cron. Is it some problem with environment variable? Maybe I need to set that in the script too?

If I stop Apache, the script still writes the the log file but doesn’t restart Apache.

alexdo
Site Moderator
Site Moderator badge
October 31, 2024

The issue you’re encountering is likely due to the environment in which the cron job runs, which is more limited than your normal shell environment. When cron executes a script, it doesn’t inherit the same environment variables, which may affect how commands like /etc/init.d/apache2 restart work.

Here are a few things to check and modify to improve the functionality of your script when run from cron:

Modifications to the Script

  1. Use Absolute Paths: Ensure that all commands used in the script have absolute paths. While you’ve done that for apache2, it’s good practice to specify the full path for ps and grep as well.
  2. Check for Errors: Capture the output and error of the restart command to the log file.
  3. Use a Shell Shebang: Instead of #!/bin/sh, you might want to use #!/bin/bash for better compatibility, especially if you’re using features specific to bash.
#!/bin/bash

LOGFILE="/var/log/uwe-crontab/crons.log"
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")

# Function to log messages with a timestamp
log_message() {
    echo "$TIMESTAMP - $1" >> $LOGFILE
}

# Log that the script is running
log_message "Running apache2 relaunch."

# Check if Apache is running
/usr/bin/ps auxw | /bin/grep apache2 | /bin/grep -v grep > /dev/null
STATUS_CODE=$?

if [ $STATUS_CODE -ne 0 ]; then
    # Apache is not running, attempt to restart
    /etc/init.d/apache2 restart >> $LOGFILE 2>&1
    log_message "Apache relaunched."
else
    log_message "Apache is running."
fi

Explanation of Changes

  • Absolute Paths: The paths to ps and grep are specified to ensure that cron can find them.
  • Logging: The output and errors from the restart command are captured in the log for easier debugging.
  • Timestamp Function: A logging function is added to maintain a consistent log format.

Cron Entry

Ensure the cron job is set correctly:

* * * * * /bin/bash /etc/apache2/relaunch.sh

Permissions

Make sure the script is executable:

chmod +x /etc/apache2/relaunch.sh

Testing

After making these changes, monitor the log file to see if it behaves correctly when Apache is stopped. If it still doesn’t restart Apache, check the log file for any errors reported by the restart command. If issues persist, you can also check /var/log/syslog for cron-specific logs that may provide additional insights.

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.