启动Python脚本作为守护进程后,只有闪烁光标,没有提示信息?

3 投票
1 回答
1501 浏览
提问于 2025-04-17 13:45
  • python-daemon-1.5.2-1.el6.noarch

下面是我从一个开发者那里收到的脚本:

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)

你可以看到,他使用了threading模块,这样可以让它作为一个守护进程运行。

我打算改用daemon库,参考这篇博客文章。

这是我第一次尝试:

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()

它可以运行,但我必须按Ctrl-C才能在启动后得到命令行提示符:

/etc/init.d/sendmailworker start

Starting server
# started with pid 2586
^C
#

我该如何解决这个问题呢?


加上一个&符号并没有帮助:

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

正如@Celada指出的:其实,我已经有了命令行提示符,但它没有像往常一样显示[root@hostname ~]#,只是一个闪烁的光标。简单按一下Enter就能让我的命令行提示符重新出现。所以问题应该是:如何让started with pid xxxxx出现在Starting server的同一行,然后再显示我的命令行提示符?


这个stop功能运行得很好:

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

我该如何让start功能也做到类似的效果?像这样:

[root@hostname ~]# /etc/init.d/sendmailworker start
Starting server
started with pid 30624
[root@hostname ~]# 

1 个回答

4

你可以通过修改

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

来实现你想要的效果:

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

我建议你在这种情况下写一个初始化脚本,使用的是shell脚本。

顺便说一下,我找不到关于runner的任何文档,除了它的源代码

撰写回答