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

3
  • 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”模块将其作为守护进程运行。我打算按照这篇博客文章切换到使用守护程序库。以下是我的第一次尝试:
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才能获得shell提示符:

/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所指出的那样:实际上,我已经有了我的shell提示符,但它不像通常显示[root@hostname ~]#,只有一个闪烁的光标。简单地按下Enter键即可使我的shell提示符重新出现。所以问题应该是:如何使started with pid xxxxx首先出现,与Starting server在同一行,然后显示我的shell提示符?
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 ~]# 

3
为什么不直接用"/etc/init.d/sendmailworker start &"来启动它呢? - Justin Peel
2
(1)原始版本根本不是守护程序,只是恰好具有多线程功能。 (2)我不知道你使用的daemon库的哪个版本,但据我所知,没有一个版本具有runner属性。请查阅文档和PEP 3143。 - Celada
1
/etc/init.d 中使用 & 将启动脚本放入后台并不是有效的解决方法。如果这样的脚本无法快速地自行终止,那么当它在系统启动期间运行时,系统启动将会一直挂起,直到该脚本退出。 - Celada
1
实际上,@quanta,你确定它没起作用吗?仔细查看你的shell转录,看起来事情实际上是在后台启动的:你收到了消息“Starting server”,然后你立刻又回到了shell提示符(,不是吗?)。然后之后有一个记录消息说明“以pid 2586启动”,但这并不重要,因为在那被记录之前,你已经拿回了你的shell提示符。之后你输入了Control-C,但我觉得你不需要这样做。 - Celada
@quanta:我也遇到了同样的问题。不幸的是,我无法将stdout重定向到`/dev/null',那么还有其他解决方法吗? - cyber101
显示剩余9条评论
1个回答

4
您可以通过更改来获取您期望的行为
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'

to:

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

我建议在您的情况下使用shell脚本编写初始化脚本。
顺便说一下,我找不到任何有关runner的文件,除了源代码

有没有一种方法可以解决这个问题,而不需要重定向到“/dev/null”? - cyber101

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接