some1
some1

Reputation: 2547

How to know if a running script dies?

So I'm somewhat new to programming and mostly self-taught, so sorry if this question is a bit on the novice side.

I have a python script that runs over long periods (e.g. it downloads pages every few seconds for days at a time.) Sort of a monitoring script for a web app.

Every so often, something will disrupt it, and it'll need restarted. I've gotten these events to a bare minimum but it still happens every few days, and when it does get killed it could be bad news if I don't notice for a few hours.

Right now it's running in a screen session on a VPS.

Could someone point me in the right direction as far as knowing when the script dies / and having it automatically restart?

Would this be something to write in Bash? Or something else? I've never done anything like it before and don't know where to start or even look for information.

Upvotes: 4

Views: 3179

Answers (4)

aculich
aculich

Reputation: 14865

You should daemonize your program.

As described in Efficient Python Daemon, you can install and use the python-daemon which implements the well-behaved daemon specification of PEP 3143, "Standard daemon process library".

Create a file mydaemon.py with contents like this:

#!/usr/bin/env python

import daemon
import time
import logging

def do_something():
    name = 'mydaemon'
    logger = logging.getLogger(name)
    handler = logging.FileHandler('/tmp/%s.log' % (name))
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler) 
    logger.setLevel(logging.WARNING)

    while True:
        try:
            time.sleep(5)
            with open("/tmp/file-does-not-exist", "r") as f:
                f.write("The time is now " + time.ctime())
        except Exception, ex:
            logger.error(ex)

def run():
    with daemon.DaemonContext():
        do_something()

if __name__ == "__main__":
    run()

To actually run it use:

python mydaemon.py

Which will spawn do_something() within the DaemonContext and then the script mydaemon.py will exit. You can see the running daemon with: pgrep -fl mydaemon.py. This short example will simply log errors to a log file in /tmp/mydaemon.log. You'll need to kill the daemon manually or it will run indefinitely.

To run your own program, just replace the contents of the try block with a call to your code.

Upvotes: 4

David Wolever
David Wolever

Reputation: 154682

That depends on the kind of failure you want to guard against. If it's just the script crashing, the simplest thing to do would be to wrap your main function in a try/except:

import logging as log

while True:
    try:
        main()
    except:
        log.exception("main() crashed")

If something is killing the Python process, it might be simplest to run it in a shell loop:

while sleep 1; do python checker.py; done

And if it's crashing because the machine is going down… well… Quis custodiet ipsos custodes?

However, to answer your question directly: the absolute simplest way to check if it's running from the shell would be to grep the output of ps:

ps | grep "python checker.py" 2>&1 > /dev/null
running=$?

Of course, this isn't fool-proof, but it's generally Good Enough.

Upvotes: 2

torrential coding
torrential coding

Reputation: 1765

I believe a wrapper bash script that executes the python script inside a loop should do the trick.

while true; do
    # Execute python script here
    echo "Web app monitoring script disrupted ... Restarting script."
done

Hope this helps.

Upvotes: 3

radu.ciorba
radu.ciorba

Reputation: 1054

You could try supervisord, it's a tool for controlling daemon processes.

Upvotes: 4

Related Questions