Keep your Unix sockets alive through /tmp cleaners.
A service binds a socket under /tmp/myservice.sock. Two days later a cleanup cron runs, mtime is stale, the socket file gets deleted. The service keeps running (the listening file descriptor is still valid on its end), but new clients can't connect. The service is invisibly broken until someone restarts it.
This library fixes that.
SockKeeper— a stdlib-only Python wrapper forsocket.AF_UNIXthat can rebind the socket path automatically when it disappears. One background thread, no deps.- CLI — emits a systemd-tmpfiles.d snippet that tells cleaners to skip your socket path, and a recommendation for where sockets belong (spoiler:
$XDG_RUNTIME_DIR).
Single file, copy anywhere:
curl -o sockkeeper.py https://raw.githubusercontent.com/kithfoss/sockkeeper/main/sockkeeper.pyOr pip (once published):
pip install sockkeeperfrom sockkeeper import SockKeeper
with SockKeeper("/tmp/myservice.sock", watch=True) as keeper:
while True:
conn, _ = keeper.sock.accept()
handle(conn)watch=True starts a daemon thread that checks the path every 60 s (configurable). If the path is gone, it rebinds. Active connections survive — only the listening entry is replaced.
Full signature:
SockKeeper(
path,
mode=0o660,
backlog=16,
watch=False,
watch_interval=60.0,
on_rebind=None,
)sockkeeper check /tmp/myservice.sock
# → RISKY: under /tmp — subject to systemd-tmpfiles cleaners ...
sockkeeper check $XDG_RUNTIME_DIR/myservice.sock
# → OK: under $XDG_RUNTIME_DIR — the canonical runtime-state location
sockkeeper tmpfiles-snippet /tmp/myservice.sock
# → prints a systemd-tmpfiles.d rule that excludes the path from cleaning
sockkeeper demo /tmp/demo.sock
# → binds with watch=1s, deletes the path mid-run, shows the rebind| Location | Rating | Why |
|---|---|---|
$XDG_RUNTIME_DIR/... |
ok | Per-user runtime dir, cleaned at logout — systemd guarantees it exists |
/run/..., /var/run/... |
caution | System runtime dirs, fine for system services |
/tmp/... |
risky | Subject to systemd-tmpfiles-clean + ad-hoc cleanup scripts |
The "right" fix is to use $XDG_RUNTIME_DIR. sockkeeper exists because that migration is disruptive — every client has to learn the new path — so you often need a tide-over.
This tool exists because of a specific incident. A service had been running for two days with its socket at /tmp/kith-whisper.sock. The mtime of the socket file (not the fd, the filesystem inode) hit the 24h threshold of a cleanup script. The socket file got unlinked. The service kept accepting connections on its existing fd but no new client could reach it. Voice was silently broken until someone noticed.
Any long-running service with a Unix socket in /tmp has this hazard.
MIT.