Использовать Python xmlrpclib с сокетами домена unix?
Я пытаюсь взаимодействовать с supervisord
, и я хотел бы поговорить с ним по сокету unix (это среда с общим хостингом).
Я пробовал до сих пор:
import xmlrpclib
server = xmlrpclib.ServerProxy('unix:///path/to/supervisor.sock/RPC2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/xmlrpclib.py", line 1549, in __init__
raise IOError, "unsupported XML-RPC protocol"
IOError: unsupported XML-RPC protocol
/path/to/supervisor.sock
определенно существует. URI формы 'unix:///path/to/supervisor.sock/RPC2' используются supervisord
, где я получил эту идею. Документы не обсуждают сокеты unix: http://docs.python.org/library/xmlrpclib.html.
Возможно ли это? Должен ли я использовать другую библиотеку?
Ответы
Ответ 1
xmlrpclib
требует, чтобы URL-адрес начинался с http
или https
. Путь вокруг этого заключается в определении настраиваемого транспорта, который игнорирует этот URL-адрес. Здесь некоторый код, использующий транспорт от супервизора:
import supervisor.xmlrpc
import xmlrpclib
proxy = xmlrpclib.ServerProxy('http://127.0.0.1',
transport=supervisor.xmlrpc.SupervisorTransport(
None, None, serverurl='unix://'+socketpath))
proxy.supervisor.getState()
Если это не полезно, здесь обновленная версия найденного кода здесь:
class UnixStreamHTTPConnection(httplib.HTTPConnection, object):
def __init__(self, *args, **kwargs):
self.socketpath = kwargs.pop('socketpath')
super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs)
def connect(self):
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect_ex(self.socketpath)
class UnixStreamTransport(xmlrpclib.Transport, object):
def __init__(self, *args, **kwargs):
self.socketpath = kwargs.pop('socketpath')
super(UnixStreamTransport, self).__init__(*args, **kwargs)
Ответ 2
Вот обновленный пример использования xmlrpclib для беседы с супервизором:
import httplib
import socket
import xmlrpclib
class UnixStreamHTTPConnection(httplib.HTTPConnection):
def connect(self):
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(self.host)
class UnixStreamTransport(xmlrpclib.Transport, object):
def __init__(self, socket_path):
self.socket_path = socket_path
super(UnixStreamTransport, self).__init__()
def make_connection(self, host):
return UnixStreamHTTPConnection(self.socket_path)
server = xmlrpclib.Server('http://arg_unused', transport=UnixStreamTransport("/var/run/supervisor.sock"))
print(server.supervisor.getState())
Как уже упоминалось, мы должны указать фиктивный url с http://или https://, а затем указать настраиваемый транспорт для обработки сокета домена
Ответ 3
Смешивая ответы выше, вот что работает для меня...
import httplib
import socket
import xmlrpclib
class UnixStreamHTTPConnection(httplib.HTTPConnection, object):
def __init__(self, *args, **kwargs):
self.socketpath = kwargs.pop('socketpath')
super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs)
def connect(self):
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(self.socketpath)
class UnixStreamTransport(xmlrpclib.Transport, object):
def __init__(self, *args, **kwargs):
self.socketpath = kwargs.pop('socketpath')
super(UnixStreamTransport, self).__init__(*args, **kwargs)
def make_connection(self, host):
return UnixStreamHTTPConnection(host, socketpath=self.socketpath)
server = xmlrpclib.ServerProxy('http://arg_unused', transport=UnixStreamTransport(socketpath="path/to/supervisor.sock"))
print server.supervisor.getState()
Ответ 4
Моя версия для python3, подготовленная из версий выше.
from http.client import HTTPConnection
import socket
from xmlrpc import client
class UnixStreamHTTPConnection(HTTPConnection):
def connect(self):
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(self.host)
class UnixStreamTransport(client.Transport, object):
def __init__(self, socket_path):
self.socket_path = socket_path
super(UnixStreamTransport, self).__init__()
def make_connection(self, host):
return UnixStreamHTTPConnection(self.socket_path)
proxy = client.ServerProxy('http://localhost', transport=UnixStreamTransport("/var/run/supervisor.sock"))
print(proxy.supervisor.getState())