[systemd-devel] Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily?
Lennart Poettering
lennart at poettering.net
Mon Oct 10 13:24:43 UTC 2022
On Fr, 07.10.22 07:24, Klaus Ebbe Grue (grue at di.ku.dk) wrote:
> Hi systemd-devel,
>
> I have a user question which I take the liberty to send here since
> "about systemd-devel" says "... it's also OK to direct user
> questions to this mailing list ...".
>
> I have a daemon, /usr/bin/mydaemon, which listens on one and only
> one TCP port, say 9999, and which does no more than communicating
> over 9999 and creating, reading, writing and deleting files in
> /home/me/mydaemon/.
>
> Mydaemon leaves it to systemd to create a socket which listens at
> 9999.
>
> It is unimportant whether or not mydaemon is started at boot and it
> is also unimportant whether or not mydaemon is socket activated. As
> long as it is at least one of the two.
>
> Now I want to upgrade mydaemon to a new version using a script,
> without race conditions and without closing the listening socket. I
> want the listening socket to stay open since otherwise there can be
> a one minute interval during which it is impossible to reopen 9999.
>
> If it is just a clean upgrade, the script could replace
> /usr/bin/mydaemon, then stop mydaemon. If the daemon is socket
> activated there is no more to do. If the daemon is activated only on
> boot then the script must end up restarting mydaemon.
>
> But now I want to do some more while mydaemon is not running. It
> could be that my script should take a backup of /home/me/mydaemon/
> in case things go wrong. It could be the script should translate
> some file in /home/me/mydaemon/ to some new format required by the
> new mydaemon or whatever.
>
> So I need to stop mydaemon in such a way that mydaemon cannot wake
> up while my script fiddles with /home/me/mydaemon/.
>
> According to https://0pointer.de/blog/projects/three-levels-of-off
> it seems that that was possible in 2011: just do "systemctl disable
> mydaemon.service". But when I try that, mydaemon still wakes up if I
> connect to 9999 using eg netcat.
Well, that's a misunderstanding...
> I have also tried to mask mydaemon. But if I then connect to 9999
> using netcat, then netcat gets kicked of. And if I try again then
> 9999 is no longer listening.
>
> QUESTION: Is it possible to let systemd create a listening socket
> and yet be able to have that socket activate nothing, at least
> temporarily?
Can't you run your upgrade script in idempotent way as a helper
service that is pulled in by your main daemon and ordered before it,
but conditions itself out if it already did its job? that's usually
the most robust way, since then it's sufficient to just restart your
daemon or reboot, and everything will always catch up correctly.
i.e. if you have foo-daemon.socket + foo-daemon.service then define
foo-upgrade.service that is pulled in from foo-daemon.service via
`Wants=foo-upgrade.service` + `After=foo-upgrade.service`. And then
add `ConditionFileExists=!/some/touch/file` to `foo-upgrade.service` to
make it a NOP if things have already been updated, using a touch
file. (some better, smarter condition check might work as well, see
man pages of things systemd can check for you).
Lennart
--
Lennart Poettering, Berlin
More information about the systemd-devel
mailing list