How systemd names instances of templated socket service units
Systemd famously has socket units,
which cause systemd itself to listen on something and start a systemd
unit when the there's traffic. In other words, systemd can act like
(x)inetd. When you do this for a stream-based service (such as a
TCP based one), there are two options for what systemd should do
when there's a connection, controlled by the Accept=
setting.
The default and normal behavior (in systemd) is 'Accept=no
', which
causes systemd to start the service unit associated with the socket
and pass it the listening socket (or sockets) to interact with. If
you specify 'Accept=yes
', you get xinetd-like behavior where a
new instance of the service is spawned for each new connection, and
the instance is passed only the connected socket. As the documentation
covers, Accept=yes
requires that you have a template .service
unit; if you have 'oidentd.socket' set with Accept=yes, you have
to have an 'oidentd@.service' unit. This service unit will be
instantiated with a specific instance name.
You might wonder what the instance name actually is for such a service unit, especially since the systemd documentation is silent about this. For IPv4 connections, the answer turns out to be that the unit names come out like this:
oidentd@<number>-<server-ip>:<server-port>-<client-ip>:<client-port>,service
The number isn't a process ID and it seems to stay constant over multiple instances, so I don't know where it comes from. I suspect that IPv6 connections will look substantially the same, just with IPv6 IP addresses instead of IPv4 ones. I don't know what local stream connections will look like (and I don't feel like experimenting).
Update: looking more closely, the number appears to be a sequence number that increments for each new instance.
On the one hand, this is somewhat convenient for your logs, since you can always tell what the exact connection a given instance was spawned for. On the other hand, this creates rather long service names, probably among the longest server names you have, and if you have anything that's trying to index observed unit names, it's going to be fed lots and lots of units that probably appear only once.
(So Grafana Loki will have another cardinality problem.)
Since this format for socket instance names isn't documented, I
would avoid depending on it for anything beyond log parsing. It's
probably unlikely to change at this point, but you never know. This
implies that the '%i
' instance parameter (see systemd.unit's
discussion of template and instance units) probably isn't very
useful in templated socket service units. You do have the remote
(client) IP address and port available in environment variables,
although you don't get the server IP or port passed to you.
(Of course you can determine both the local and remote addresses in your code by examining the socket.)
|
|