How to wrap python daemon around my code

2019-04-02 10:38发布

问题:

I have a working server using Tornado now, according to the answer here: Python BaseHTTPServer and Tornado

I'd like to daemonize it. I have been reading over and over this daemon class example here, but I can't figure out how it wraps around my server code. Do I just put all the code from __main__ in the run() that I override?

How do I subclass it also if it's in another file? Make sure it's in the same directory and using it's filename without .py extension to import?

I'm just looking for the simplest way to run my python web server script with nothing more than a simple call such as ./startserver.sh (for example, if I was to use a bash script) and have it run in the background with no nohup.out file and all stdout and stderr redirected to log files.

回答1:

Let's keep it simple. Project tree:

$ tree
.
├── daemon.py
├── main.py
├── server.py
└──  __init__.py

daemon.py is a Daemon class from http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/, server.py is threaded version of code from Python BaseHTTPServer and Tornado, __init__.py is an empty file which allows us to import code from other files in directory. main.py is:

#!/usr/bin/env python

import sys, time, threading
from daemon import Daemon
from server import run_tornado, run_base_http_server

class ServerDaemon(Daemon):
    def run(self):
        threads = [
            threading.Thread(target=run_tornado),
            threading.Thread(target=run_base_http_server)
        ]

        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()

if __name__ == "__main__":
    daemon = ServerDaemon('/tmp/server-daemon.pid')

    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()          
        elif 'stop' == sys.argv[1]:
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            daemon.restart()
        else:
            print "Unknown command"
            sys.exit(2)
        sys.exit(0)
    else:
        print "usage: %s start|stop|restart" % sys.argv[0]
        sys.exit(2)

Run it with:

$ python main.py start

For first version from Python BaseHTTPServer and Tornado change if __name__ == '__main__': to def myfun(): and call it from run() method of Daemon subclass.



回答2:

Try using the supervisor daemon package on Linux. It lets you daemonize things easily.

For Ubuntu: sudo apt-get install supervisor

Create a conf.d file:

cd /etc/supervisor/conf.d/ vim pyhttpd.conf

Inside your pyhttpd.conf:

[program:pyhttpd]
directory=/path/to/project
environment=ENV_VAR=ENV_VAL,ENV_VAR2=ETC
command=startserver.sh
autostart=true
autorestart=true

Finally, update supervisor with the new config:

supervisorctl update

It should be started for you, and will now run whenever you boot up.


These commands are also available:

supervisorctl stop pyhttpd

supervisorctl start pyhttpd

supervisorctl restart pyhttpd


stdout and stderr are logged to the /var/log/supervisor/ directory.