Linux sockets and system d
The key point here is to specify Accept=yes
, which will make the socket accept connections (behaving like inetd) and pass
only the resulting connection socket to the service handler.
Create /etc/systemd/system/baz.socket
:
[Unit]
Description=Baz Socket
[Socket]
ListenStream=/tmp/baz.socket
Accept=yes
[Install]
WantedBy=sockets.target
We now create a service template from which the actual service will be instantiated on-demand. The lifetime of this service is
usually very short (thus it may not appear at systemctl
).
Create /etc/systemd/system/baz@.service
:
[Unit]
Description=Baz Service
Requires=baz.socket
[Service]
Type=simple
ExecStart=/usr/bin/python /opt/baz-service/serve.py %i
StandardInput=socket
StandardError=journal
TimeoutStopSec=5
[Install]
WantedBy=multi-user.target
An example service handler would be (located at /opt/baz-service/serve.py
as specified at the service unit file):
#!/usr/bin/python
import sys
import logging
logging.basicConfig(level=logging.INFO)
instance = sys.argv[1]
# The connected socket is duplicated to stdin/stdout
data = sys.stdin.readline().strip()
logging.info('baz-service: at instance %s, got request: %s', instance, data)
sys.stdout.write(data.upper() + '\r\n')
Open the journal in following mode:
sudo journalctl -f
Startthe socket:
sudo systemctl start baz.socket
Verify it via:
sudo systemctl status baz.socket
Make a request to the service:
echo "Hello World" | nc -U /tmp/baz.sock
You should see in the jnournalctl
the python logger with the "Hello World".