- Example OS X daemon: http://stackoverflow.com/a/9523030
- Library for simplifying daemon creation: https://github.com/serverdensity/python-daemon/blob/master/daemon.py
Once a daemon is running, I need some way of communicating with it. That's where Pyro comes in. (I briefly considered running an HTTP server, but the HTTP protocol was designed to handle resources, not remote procedure calls (RPC). Plus, the overhead of an HTTP server, URL handling, and JSON parsing compared to a lightweight Pyro daemon was too much to justify if my plans were to only interact with the daemon over SSH.)
Example taken from http://stackoverflow.com/questions/24461167/how-can-i-cleanly-exit-a-pyro-daemon-by-client-request. (My test did not demonstrate the hangs that the OP was experiencing.)
server.py
:
import Pyro4
class TestAPI:
def __init__(self, daemon):
self.daemon = daemon
def hello(self, msg):
print 'client said {}'.format(msg)
return 'hola'
def shutdown(self):
print 'shutting down...'
self.daemon.shutdown()
if __name__ == '__main__':
daemon = Pyro4.Daemon(port=9999)
tapi = TestAPI(daemon)
uri = daemon.register(tapi, objectId='TestAPI')
daemon.requestLoop()
print 'exited requestLoop'
daemon.close()
print 'daemon closed'
client.py
:
import Pyro4
if __name__ == '__main__':
uri = 'PYRO:TestAPI@localhost:9999'
remote = Pyro4.Proxy(uri)
response = remote.hello('hello')
print 'server said {}'.format(response)
try:
remote.shutdown()
except Pyro4.errors.ConnectionClosedError:
pass
print 'client exiting'
The
server.py
application should be owned byroot
and have-rwxr-x--x
permissions. It will be launched as a daemon by system processes, so it will never be invoked by users. Theclient.py
process will be owned by the SSH user and have-rwx------
permissions. It can only be launched by the SSH user and it will only establish communication with the server daemon if the application was launched via SSH.