Нет подсказки оболочки, просто мигающий курсор после запуска скрипта Python в качестве демона?

  • Python-демон-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 ~]# 

person quanta    schedule 26.01.2013    source источник
comment
Почему бы просто не начать с /etc/init.d/sendmailworker start &?   -  person Justin Peel    schedule 26.01.2013
comment
Все равно придется нажимать Ctrl-C. Обновил мой вопрос.   -  person quanta    schedule 26.01.2013
comment
возможный дубликат Как создать демон в Python?   -  person Celada    schedule 26.01.2013
comment
Не могли бы вы упростить образец, чтобы он работал на чужом компьютере, но при этом проявлял проблему?   -  person millimoose    schedule 26.01.2013
comment
(1) Исходная версия вовсе не демон, просто она многопоточная. (2) Я не знаю, какая у вас версия библиотеки daemon, но ни одна из них не имеет атрибута runner. Проверьте документацию и PEP 3143.   -  person Celada    schedule 26.01.2013
comment
@JustinPeel Запуск сценария запуска в /etc/init.d с & для перевода его в фоновый режим не является допустимым обходным путем. Если такой сценарий не завершится сам по себе быстро, то при его запуске во время запуска системы запуск системы будет зависать до завершения сценария.   -  person Celada    schedule 26.01.2013
comment
@Celada: по поводу твоего первого комментария я видел эту тему. Насчет второго: (1) ОК. (2) Обновлена ​​версия python-daemon в начале.   -  person quanta    schedule 26.01.2013
comment
Пожалуйста, проигнорируйте мой комментарий о daemon.runner. Я вижу это сейчас. Не знаю, почему я не видел его раньше. (Тем не менее, PEP 3143 не упоминает об этом, он говорит только о daemon.DaemonContext)   -  person Celada    schedule 26.01.2013
comment
@millimoose: вы можете попробовать этот код.   -  person quanta    schedule 26.01.2013
comment
Всем, кто проголосовал близко: не могли бы вы оставить комментарий? Как вы думаете, это дубликат?   -  person quanta    schedule 26.01.2013
comment
Вообще-то, @quanta, ты уверен, что это не работает? При внимательном рассмотрении обеих расшифровок вашей оболочки кажется, что все действительно началось в фоновом режиме: вы получаете сообщение Starting server, затем вы сразу же снова получаете приглашение оболочки (#, не так ли?). Затем после этого появляется сообщение журнала с указанием started with pid 2586, но это не имеет значения, вы уже получили приглашение оболочки до того, как оно было зарегистрировано. После этого вы нажали Control-C, но я не думаю, что вам это было нужно.   -  person Celada    schedule 26.01.2013
comment
давайте продолжим это обсуждение в чате   -  person quanta    schedule 26.01.2013
comment
@Celada: вы правы: у меня уже было приглашение оболочки, но оно не отображает [root@hostname ~]#, как обычно. Таким образом, вопрос должен быть таким: как заставить его печатать сообщение журнала started with pid ... в той же строке, что и Starting server, а затем отображать приглашение моей оболочки.   -  person quanta    schedule 26.01.2013
comment
@quanta: я борюсь с той же проблемой. К сожалению, я не могу перенаправить стандартный вывод на `/dev/null' , так что есть ли другой обходной путь для этого?   -  person cyber101    schedule 15.04.2015


Ответы (1)


Вы можете получить ожидаемое поведение, изменив

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

to:

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

Я рекомендую написать сценарий инициализации, используя сценарий оболочки в вашем случае.

К вашему сведению, я не могу найти ни одного документа runner, кроме его исходного кода< /а>.

person favadi    schedule 28.01.2013
comment
есть ли способ обойти это без перенаправления на '/dev/null'? - person cyber101; 15.04.2015