58

I want to run a python script in a CENTOS server:

#!/usr/bin/env python
import socket
try:    
    import thread 
except ImportError:
    import _thread as thread #Py3K changed it.
class Polserv(object):
    def __init__(self):
        self.numthreads = 0
        self.tidcount   = 0
        self.port       = 843
        self.sock       = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(('100.100.100.100', self.port))
        self.sock.listen(5)
    def run(self):
        while True:
            thread.start_new_thread(self.handle, self.sock.accept()) 
    def handle(self,conn,addr):
        self.numthreads += 1
        self.tidcount   += 1
        tid=self.tidcount
        while True:
            data=conn.recv(2048)
            if not data:
                conn.close()
                self.numthreads-=1
                break
            #if "<policy-file-request/>\0" in data:
            conn.sendall(b"<?xml version='1.0'?><cross-domain-policy><allow-access-from domain='*' to-ports='*'/></cross-domain-policy>")
            conn.close()
            self.numthreads-=1
            break
        #conn.sendall(b"[#%d (%d running)] %s" % (tid,self.numthreads,data) )
Polserv().run()

Im using $ python flashpolicyd.py and it works fine... The question is: How to keep this script running even after I close the terminal(console)?

Filipe Tagliacozzi
  • 1,431
  • 2
  • 20
  • 28
  • possible duplicate of [How to make a python script run like a service or daemon in linux](http://stackoverflow.com/questions/1603109/how-to-make-a-python-script-run-like-a-service-or-daemon-in-linux) – piokuc May 07 '13 at 13:18
  • 2
    Not an exact duplicate -- the linked-to question is about a recurring task, this is about a network daemon; the solution to the other was cron, the solution to this is inetd (or equivalent). – Robᵩ May 07 '13 at 13:33

5 Answers5

81

I offer two recommendations:

supervisord

1) Install the supervisor package (more verbose instructions here):

sudo apt-get install supervisor

2) Create a config file for your daemon at /etc/supervisor/conf.d/flashpolicyd.conf:

[program:flashpolicyd]
directory=/path/to/project/root
environment=ENV_VARIABLE=example,OTHER_ENV_VARIABLE=example2
command=python flashpolicyd.py
autostart=true
autorestart=true

3) Restart supervisor to load your new .conf

supervisorctl update
supervisorctl restart flashpolicyd

systemd (if currently used by your Linux distro)

[Unit]
Description=My Python daemon

[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/project/main.py
WorkingDirectory=/opt/project/
Environment=API_KEY=123456789
Environment=API_PASS=password
Restart=always
RestartSec=2

[Install]
WantedBy=sysinit.target

Place this file into /etc/systemd/system/my_daemon.service and enable it using systemctl daemon-reload && systemctl enable my_daemon && systemctl start my_daemon --no-block.

To view logs:

systemctl status my_daemon

pztrick
  • 3,741
  • 30
  • 35
80

I use this code to daemonize my applications. It allows you start/stop/restart the script using the following commands.

python myscript.py start
python myscript.py stop
python myscript.py restart

In addition to this I also have an init.d script for controlling my service. This allows you to automatically start the service when your operating system boots-up.

Here is a simple example to get your going. Simply move your code inside a class, and call it from the run function inside MyDeamon.

import sys
import time

from daemon import Daemon


class YourCode(object):
    def run(self):
        while True:
            time.sleep(1)


class MyDaemon(Daemon):
    def run(self):
        # Or simply merge your code with MyDaemon.
        your_code = YourCode()
        your_code.run()


if __name__ == "__main__":
    daemon = MyDaemon('/tmp/daemon-example.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)

Upstart

If you are running an operating system that is using Upstart (e.g. CentOS 6) - you can also use Upstart to manage the service. If you use Upstart you can keep your script as is, and simply add something like this under /etc/init/my-service.conf

start on started sshd
stop on runlevel [!2345]

exec /usr/bin/python /opt/my_service.py
respawn

You can then use start/stop/restart to manage your service.

e.g.

start my-service
stop my-service
restart my-service

A more detailed example of working with upstart is available here.

Systemd

If you are running an operating system that uses Systemd (e.g. CentOS 7) you can take a look at the following Stackoverflow answer.

Community
  • 1
  • 1
eandersson
  • 25,781
  • 8
  • 89
  • 110
  • Ok.. but i cant see how to use this class in my script... may you teach? – Filipe Tagliacozzi May 07 '13 at 13:25
  • how would you use init.d script with MyDaemon? Assuming Daemon forks the MyDaemon process could this possibility fork a new process and then it might try to restart - because it thinks the script has finished (resulting in 1000's of running python processes). Can you maybe provide a quick / simple example of init.d with the simple python Dameon? – sigi Mar 10 '15 at 15:54
  • @sigi: Unless the script actually finishes the python daemon should prevent any new processes from starting up, but you can always just check for the pid file in your init.d script. I can update the answer when I have time in a day or two if you need a proper example. – eandersson Mar 10 '15 at 22:43
  • @eandersson: I thought the python daemon script you referred to does a process fork twice, and hence init.d (Upstart) I think needs to have an "expect daemon" command in the ".conf" file or something of that sort... I'm just wondering how you would make your Upstart .conf file look for a simple python daemon using the daemonizer script you reffered to - i.e. a simple example of how you use an init.d script for controlling your service would be really great... Thanks. – sigi Mar 12 '15 at 11:22
  • If you are using Upstart it is probably better to simply leverage the Upstart scripts and completely skip my solution. It is super simply and will do all the heavy lifting for you. See this Stackoverflow answer for more information: http://stackoverflow.com/questions/17747605/daemon-vs-upstart-for-python-script – eandersson Mar 13 '15 at 11:18
  • this does not work anymore, cannot import Daemon from daemon. – Thijs Dec 02 '15 at 10:34
  • @Thijs this has nothing to do with this code. You are most likely missing the __init__.py file in the directory, or something similar. – eandersson Dec 02 '15 at 13:54
  • @eandersson, sorry about my comment earlier but this daemon does not work when script being daemonized imports multiprocessing module. Some conflict appears when creating process with multiprocessing inside this daemon giving error that can only join a child process. Please test this daemon with any basic example of multiprocessing module. – MohitC Jun 27 '16 at 16:23
  • 1
    @MohitC: That is a little off-topic unfortunately. I would recommend that you open a new question specifically for demonizing an multi process application. – eandersson Jun 30 '16 at 12:14
  • @eandersson Thanks for good answer, I am trying to create the init.d script for controlling my service. In the init.d docs they are mentioned about PID file. is this is PID and daemon = MyDaemon('/tmp/daemon-example.pid') is same? and how to pass start/stop argument from initd. script to the python script – ShivaPrasad Sep 12 '19 at 18:13
9

My non pythonic approach would be using & suffix. That is:

python flashpolicyd.py &

To stop the script

killall flashpolicyd.py

also piping & suffix with disown would put the process under superparent (upper):

python flashpolicyd.pi & disown
psukys
  • 387
  • 2
  • 6
  • 20
5

first import os module in your app than with use from getpid function get pid's app and save in a file.for example :

import os
pid = os.getpid()
op = open("/var/us.pid","w")
op.write("%s" % pid)
op.close()

and create a bash file in /etc/init.d path: /etc/init.d/servername

PATHAPP="/etc/bin/userscript.py &"
PIDAPP="/var/us.pid"
case $1 in 
        start)
                echo "starting"
                $(python $PATHAPP)
        ;;
        stop)
                echo "stoping"
                PID=$(cat $PIDAPP)
                kill $PID
        ;;

esac

now , u can start and stop ur app with down command:

service servername stop service servername start

or

/etc/init.d/servername stop /etc/init.d/servername start

Arsalan
  • 96
  • 1
  • 1
2

for my script of python, I use...

To START python script :

start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --exec $DAEMON

To STOP python script :

PID=$(cat $PIDFILE)
kill -9 $PID
rm -f $PIDFILE

P.S.: sorry for poor English, I'm from CHILE :D

Roman
  • 1,727
  • 1
  • 20
  • 28