3
  • python-daemon-1.5.2-1.el6.noarch

Below is the script that I received from a developer:

import threading
import multiprocessing, os, signal, time, Queue
import time
from suds.client import Client
from hotqueue import HotQueue
from config import config

queue = HotQueue(config['redis_hotqueue_list'], host=config['redis_host'], port=int(config['redis_port']),password=config['redis_pass'], charset="utf-8",db=0)
@queue.worker()
def sendMail(item):    
    key = item[0]        
    domain = item[1]
    fromemail = item[2]
    fromname = item[3]
    subject = item[4]
    content = item[5]
    toemail = item[6]            
    cc = item[7]
    bcc = item[8]
    replyto = item[9]

    # Convert to string variable
    url = config['sendmail_tmdt_url']
    client = Client(url)        
    client.service.send_mail(key,domain, fromemail,subject, content, toemail,fromname, '','','');               
for i in range(10):
    t = threading.Thread(target=sendMail)
    t.setDaemon(True)
    t.start()
while True:
    time.sleep(50)

As you can see, he's using the threading module to make it can be run as a daemon.

I'm going to switch to use the daemon library follow this blog post.

Here's my first try:

from daemon import runner
import logging
import time
import threading
import multiprocessing, os, signal, time, Queue
import time
from suds.client import Client
from hotqueue import HotQueue
from config import config

class Mail():
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path = '/var/run/sendmailworker/sendmailworker.pid'
        self.pidfile_timeout = 1

    def run(self):    
        while True:
            queue = HotQueue(config['redis_hotqueue_list'], host=config['redis_host'], port=int(config['redis_port']), password=config['redis_pass'], charset=r"utf-8", db=0)
            @queue.worker()
            def sendMail(item):
                key = item[0]        
                domain = item[1]
                fromemail = item[2]
                fromname = item[3]
                subject = item[4]
                content = item[5]
                toemail = item[6]            
                cc = item[7]
                bcc = item[8]
                replyto = item[9]

                # Convert to string variable
                url = config['sendmail_tmdt_url']
                client = Client(url)        
                client.service.send_mail(key,domain, fromemail,subject, content, toemail, fromname, '', '', '');            
                logger.debug("result")
            #sleep(50)

mail = Mail()

logger = logging.getLogger("sendmailworker")
logger.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.FileHandler("/var/log/sendmailworker/sendmailworker.log")
handler.setFormatter(formatter)
logger.addHandler(handler)

daemon_runner = runner.DaemonRunner(mail)
daemon_runner.daemon_context.files_preserve=[handler.stream]
daemon_runner.do_action()

It works but I have to press the Ctrl-C to get the shell prompt after starting:

/etc/init.d/sendmailworker start

Starting server
# started with pid 2586
^C
#

How can I get rid of this problem?


Append an ampersand doesn't help:

# /etc/init.d/sendmailworker start &
[1] 4094
# Starting server
started with pid 4099
^C
[1]+  Done                    /etc/init.d/sendmailworker start
#

As @Celada pointed out: actually, I already had my shell prompt, but it doesn't display [root@hostname ~]# as usual, just a blinking cursor. Simple pressing Enter make my shell prompt reappear. So the question should be: how to make the started with pid xxxxx come first, at the same line with Starting server, then display my shell prompt?


The stop function is working fine:

[root@hostname ~]# /etc/init.d/sendmailworker stop
Stopping server
Terminating on signal 15
[root@hostname ~]# 

How can I do the similar for the start function? Something like this:

[root@hostname ~]# /etc/init.d/sendmailworker start
Starting server
started with pid 30624
[root@hostname ~]# 
quanta
  • 3,960
  • 4
  • 40
  • 75
  • 3
    Why not just start it with `/etc/init.d/sendmailworker start &`? – Justin Peel Jan 26 '13 at 15:34
  • Still have to press Ctrl-C. Updated my question. – quanta Jan 26 '13 at 15:38
  • possible duplicate of [How do you create a daemon in Python?](http://stackoverflow.com/questions/473620/how-do-you-create-a-daemon-in-python) – Celada Jan 26 '13 at 15:42
  • Could you simplify the sample so it'd run on someone else's computer while still manifesting the problem? – millimoose Jan 26 '13 at 15:45
  • 2
    (1) The original version is not a daemon at all, it just happens to be multithreaded. (2) I don't know which version of the `daemon` library you have, but none that I can see has a `runner` attribute. Check the documentation and PEP 3143 – Celada Jan 26 '13 at 15:46
  • 1
    @JustinPeel Running a startup script in `/etc/init.d` with `&` to put it in the background is not a valid workaround. If such a script does not terminate quickly on its own then when it is run during system startup the system startup will hang until the script exits. – Celada Jan 26 '13 at 15:48
  • @Celada: about your first comment, I saw that topic. About the second: (1) OK. (2) Updated the `python-daemon` version at the beginning. – quanta Jan 26 '13 at 15:53
  • Please ignore my comment about `daemon.runner`. I see it now. I don't know why I didn't see it before. (Still, PEP 3143 doesn't mention it, it only talks about `daemon.DaemonContext`) – Celada Jan 26 '13 at 15:53
  • @millimoose: you can try [this](http://stackoverflow.com/a/9047339/631612) code. – quanta Jan 26 '13 at 15:54
  • To anyone who has casted a close vote: could you please leave a comment? Do you think it is dupplicate? – quanta Jan 26 '13 at 15:57
  • 1
    Actually, @quanta, are you sure it's not working? Taking a closer look at both your shell transcripts, it looks as though the thing actually did start in the background: you get the message `Starting server`, then you get your shell prompt back again right away (the `#`, isn't it?). Then afterwards there is a logging message stating `started with pid 2586` but that doesn't matter, you already had your shell prompt back before that got logged. Afterwards you typed Control-C but I don't think you needed to. – Celada Jan 26 '13 at 16:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23414/discussion-between-quanta-and-celada) – quanta Jan 26 '13 at 16:03
  • @Celada: you're right: I already had my shell prompt but it doesn't display `[root@hostname ~]#` as usual. So the question should be: how to make it print the `started with pid ...` logging message at the same line with `Starting server` then display my shell prompt. – quanta Jan 26 '13 at 16:13
  • @quanta: I'm struggling with the same problem. Unfortunately I can't redirect the stdout to `/dev/null' , so, is there any other workaround for this? – cyber101 Apr 15 '15 at 09:15

1 Answers1

4

You can get your expected beahviour by change

self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'

to:

self.stdout_path = '/dev/null'
self.stderr_path = '/dev/null'

I recommend to write a init script using shell script in your case.

FYI, I can not find any document of runner except its source code.

favadi
  • 215
  • 2
  • 13