login community faq
1
2

Does anyone have a simple but effective script which can be used with cron in order to maintain a process and keep it running, restarting it only if necessary?

If I simply tell the program itself to run on cron, I may get several copies running simultaneously. This program is not smart enough to test whether or not it is already active before firing up another copy of itself.

asked Nov 11 '11 at 18:35

ryans's gravatar image

ryans ♦♦
28161420


Yes. All you need to do is to create a simple bash script like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/env bash

PIDFILE="$HOME/tmp/myprogram.pid"

if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -f | grep "[ ]$(cat ${PIDFILE})[ ]"); then
  echo "Already running."
  exit 99
fi

/path/to/myprogram > $HOME/tmp/myprogram.log &

echo $! > "${PIDFILE}"
chmod 644 "${PIDFILE}"

Then, run the program on a short cron job, like this:

1
*/5 * * * * $HOME/cron/watchdog.sh > $HOME/cron/watchdog.log 2>&1

In this example, I have named the script watchdog.sh and placed it in my $HOME/cron directory. We would also want to ensure that execute permissions are set on the script; so we would chmod 755 it.

The script itself also uses the $HOME/tmp directory, so you would want to create that as well. In general, keeping a $HOME/tmp directory is a better idea than relying on /tmp.

answered Nov 11 '11 at 18:46

ryans's gravatar image

ryans ♦♦
28161420

edited Mar 13 at 22:39

Thanks, but I'm actually trying to keep an SSH tunnel alive for a database connection, and the:

/path/to/myprogram & > $HOME/tmp/myprogram.log &

line doesn't seem to work out-of-the-box for ssh.

(Nov 11 '11 at 18:48) ryans ♦♦ ryans's gravatar image

The above is a general format applicable to all programs. Specifically for SSH, you should try something like this:

/usr/bin/ssh -N "-L 12671:127.0.0.1:3306" -oServerAliveInterval=60 -oServerAliveCountMax=3 -oBatchMode=yes -oConnectTimeout=10 "USERNAME@webNNN.webfaction.com" &

Where the following would be replaced by your information:

  • 12671 - your local port on your server. The source of the tunnel.
  • 3306 - the destination port of the tunnel. Would point to the database port. (use 3306 for mysql, 5432 for postgresql)
  • USERNAME - your username.
  • webNNN - the number of your webserver; for example, web200.webfaction.com

To be more aggressive in automatically handling migrations and/or IP changes by ignoring host credentials, add the -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no options to the above command as well.

(Nov 11 '11 at 18:54) ryans ♦♦ ryans's gravatar image

I'm new to Bash scripting, and have a problem with the watchdog script. My user name is replicounts, and the program that needs an occasional restart is aff.py.

The crontab is working fine, and my watchdog.sh script (below) is being executed when it should. But the resulting watchdog.log is:

1
/home/replicounts/cron/watchdog.sh: line 7: python3.1: command not found

I manually run the program (in webapps/aff/htdocs) with:

1
nohup python3.1 aff.py &

The python3.1 is available interactively in all my directories. Also note:

1
2
3
4
[replicounts@web214 cron]$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/replicounts/bin
[replicounts@web214 cron]$ ls -a /home/replicounts/bin
.  ..  .ph

FYI, my watchdog.sh script is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[replicounts@web214 cron]$ cat watchdog.sh
#!/usr/bin/env bash
PIDFILE="$HOME/tmp/aff.pid"
if [ -e "${PIDFILE}" ] && (ps -u $USER -f | grep "[ ]$(cat ${PIDFILE})[ ]"); then
  echo "Already running."
  exit 99
fi
python3.1 $HOME/webapps/aff/htdocs/aff.py > $HOME/tmp/aff.log &
echo $! > "${PIDFILE}"
chmod 644 "${PIDFILE}"

What needs to be changed?

John

(Apr 25 '12 at 14:03) replicounts replicounts's gravatar image

cron doesn't operate with the same PATH as your shell account, so try using the full path to everything in your script and in your cron jobs. For example, instead of python3.1, use /usr/local/bin/python3.1. You can find the full path for a particular tool with the which command, eg:

1
2
[root@web214 ~]# which python3.1
/usr/local/bin/python3.1

Or, you can explicitly set the PATH in your script.

Hope that helps!

(Apr 25 '12 at 14:21) seanf ♦♦ seanf's gravatar image

For reference, here is cron's environment:

1
2
3
4
5
6
7
SHELL=/bin/sh
USER=<username>
PATH=/usr/bin:/bin
PWD=/home/<username>
SHLVL=1
HOME=/home/<username>
LOGNAME=<username>

Additionally, cron runs the commands directly from your $HOME directory. To test cron commands, I like to run something like this:

1
2
3
4
5
6
7
8
9
cd $HOME
unset $(env | awk -F= '/^\w/ {print $1}' | xargs)
export USER=$(/usr/bin/whoami)
export SHELL=/bin/sh
export PATH=/usr/bin:/bin
export PWD=/home/$USER
export SHLVL=1
export HOME=/home/$USER
export LOGNAME=$USER

And then run the command exactly as it appears in the crontab.

(Apr 26 '12 at 00:53) ryans ♦♦ ryans's gravatar image
Your answer
If you have an answer to the above question, then use the form below. Otherwise, use the appropriate 'add new comment' button above to post your feedback.
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Tags:

×50
×3
×3

Asked: Nov 11 '11 at 18:35

Seen: 2,771 times

Last updated: Mar 14 at 03:41

Plans & prices    Sign up    Why WebFaction?    Contact us    Affiliate program    Support    Legal    Jobs    Blog    Control panel login
Powered by OSQA
© Copyright 2003-2012 Swarma Limited - WebFaction is a service of Swarma Limited