Last Updated: February 25, 2016
·
6.712K
· kenmoini

Keep your Python app running

I had developed an application that uses AlgLib's Python stack for some computational efforts. It's a simple XML RPC server written in Python, but I'd find it offline every now and then (DC restarts VPS' box, I restart & forget it, etc)

Between a bit of Bash, a CRON job, and some extra Python bits, I made the script load itself into the background without user intervention.

In the Python XML RPC Server, I added a few imports, and functions...os and sys are needed for simple file operations, in this case writing to a PID file. atexit is what will remove the PID file when the script is terminated. The function all_done deletes the PID file and is registered to atexit where the function writePidFile creates the PID file, writes the PID of the script to it and is run towards the end of the script. There's also a simple exception that catches user initiated keyboard interrupts (Ctrl+C/X), and will gracefully exit without printing a frightening error.

#!/usr/bin/python
from array import *
import os
import sys
import atexit

try:
    #Define atexit function
    def all_done():
        pid = str('saltServer.pid')
        os.remove(pid)

    atexit.register(all_done)

    # Setup PID file
    def writePidFile():
        pid = str(os.getpid())
        f = open('saltServer.pid', 'w')
        f.write(pid)
        f.close()

    #Your code here...I had the RPC Server setup and listening here.

    writePidFile()

except KeyboardInterrupt:
    sys.exit(0)

Ok, so I got it running without any errors, it makes a populated PID file at launch and deletes it when it is exited. Then, there was the second part of the equation that kept this script running in the background; a simple bash script that would be run as a CRON job every 10 minutes.

To explain the following code, bash is simply set as the interpreter at the top, then the PID file is defined, I had it running out of one of my local users home directories. Then it checks to see i the PID file exists, and checks to see if the PID is running under the current user. If the file exists and is running under the current user, then it exits. If the file does not exist, or is not running under the current user then it continues with the script where at the bottom it will execute a command to launch the Python script.

#!/usr/bin/env bash

PIDFILE="$HOME/saltServer.pid"

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

nohup /home/spyro/saltServer.py >/dev/null 2>&1&

And as a bonus point, here's the CRONTAB listing that runs this bash script every 10 minutes:

*/10 * * * * /home/spyro/ssIsUpCheck.sh > /dev/null 2>&1

Hopefully this will help some with similar server/application/script requirements in making their jobs easier.

1 Response
Add your response

Why is it the "writePidFile()" function goes after my code?
Surely if I have a script that is in a while true loop it will never get to that line?

over 1 year ago ·