Взаимодействие с запущенным демоном python


Я написал небольшое приложение Python, которое работает как демон. Он использует резьбу и очереди.

Я ищу общие подходы к изменению этого приложения, чтобы я мог общаться с ним во время его работы. В основном я хотел бы иметь возможность следить за его здоровьем.

в двух словах, я хотел бы быть в состоянии сделать что-то вроде этого:

python application.py start  # launches the daemon

позже, я хотел бы иметь возможность прийти и сделать что-то вроде:

python application.py check_queue_size  # return info from the daemonized process

будет ясно, что у меня нет никаких проблем с реализацией синтаксиса, вдохновленного Django. То, что я не знаю, как это сделать, - это отправить сигналы в демонизированный процесс (start) или как написать демон для обработки и ответа на такие сигналы.

Как я уже сказал выше, я ищу общие подходы. Единственное, что я вижу прямо сейчас, - это то, что демон постоянно записывает все, что может понадобиться в файл, но я надеюсь, что есть менее грязный способ оно.

обновление: Вау, много отличных ответов. Большое спасибо. Я думаю, что посмотрю и на пиро, и на web.py/Werkzeug подходит, так как Twisted-это немного больше, чем я хочу откусить в этот момент. Следующая концептуальная проблема, я полагаю, заключается в том, как говорить с моими рабочими потоками, не вешая их.

еще раз спасибо.

7   51  

7 ответов:

Как насчет того, чтобы он запускал http-сервер?

Это кажется сумасшедшим, но работает простой веб-сервер для администрирования вашего сервер требует всего несколько строк с помощью web.py

вы также можете рассмотреть возможность создания канала unix.

еще один подход: использовать Pyro (объекты удаленного взаимодействия Python).

Pyro в основном позволяет публиковать экземпляры объектов Python в качестве служб, которые могут быть вызваны удаленно. Я использовал Pyro для точной цели, которую вы описываете, и я обнаружил, что он работает очень хорошо.

по умолчанию демон Pyro server принимает соединения отовсюду. Чтобы ограничить это, либо используйте средство проверки соединения (см. документацию), либо поставьте host='127.0.0.1' до Daemon конструктора прослушивайте только локальные соединения.

пример кода взят из документации Pyro:

сервер

import Pyro.core

class JokeGen(Pyro.core.ObjBase):
        def __init__(self):
                Pyro.core.ObjBase.__init__(self)
        def joke(self, name):
                return "Sorry "+name+", I don't know any jokes."

Pyro.core.initServer()
daemon=Pyro.core.Daemon()
uri=daemon.connect(JokeGen(),"jokegen")

print "The daemon runs on port:",daemon.port
print "The object's uri is:",uri

daemon.requestLoop()

клиент

import Pyro.core

# you have to change the URI below to match your own host/port.
jokes = Pyro.core.getProxyForURI("PYROLOC://localhost:7766/jokegen")

print jokes.joke("Irmen")

еще один подобный проект -RPyC. Я не пробовал ветеранами.

использовать werkzeug и сделать ваш демон включает в себя сервер WSGI на основе HTTP.

ваш демон имеет коллекцию небольших приложений WSGI для ответа с информацией о состоянии.

ваш клиент просто использует urllib2, чтобы сделать Post или GET запросы на localhost:некий_порт. Ваш клиент и сервер должны согласовать номер порта (и URL-адрес).

Это очень просто реализовать и очень масштабируемо. Добавление новых команд является тривиальным упражнение.

обратите внимание, что ваш демон не должен отвечать в HTML (это часто просто, хотя). Наши демоны отвечают на WSGI-запросы с помощью объектов состояния в кодировке JSON.

Я бы использовал twisted с именованной трубой или просто открыл сокет. Взгляните на эхо-сервер и клиент примеры. Вам нужно будет изменить эхо-сервер, чтобы проверить некоторую строку, переданную клиентом, а затем ответить на любую запрошенную информацию.

из-за проблем с потоками Python у вас будут проблемы с ответом на информационные запросы, одновременно продолжая делать все, что демон должен делать в любом случае. Асинхронный методы или разветвление других процессов - ваш единственный реальный вариант.

# your server

from twisted.web import xmlrpc, server
from twisted.internet import reactor

class MyServer(xmlrpc.XMLRPC):

    def xmlrpc_monitor(self, params):        
        return server_related_info

if __name__ == '__main__':
    r = MyServer()
    reactor.listenTCP(8080, Server.Site(r))
    reactor.run()

клиент может быть записан с помощью xmlrpclib, проверьте пример кода здесь.

предполагая, что вы находитесь под *nix, вы можете отправлять сигналы в запущенную программу с помощью kill из оболочки (и аналогов во многих других средах). Чтобы справиться с ними изнутри python проверить сигнал модуль.

вы можете связать его с Pyro (http://pythonhosted.org/Pyro4/) удаленный объект Python. Он позволяет удаленно обращаться к объектам python. Это легко реализовать, имеет низкие накладные расходы и не так инвазивно, как Twisted.