feat: add systemd sdnotify support (ready, watchdog, stopping)
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled

- Add github.com/coreos/go-systemd/v22/daemon dependency
- Signal SdNotifyReady after configuration is loaded
- Start watchdog goroutine that pings systemd every WatchdogSec/2
- Signal SdNotifyStopping during graceful shutdown
- Update systemd unit file:
  - Type=notify (instead of simple)
  - WatchdogSec=30 (auto-restart if service hangs)
  - NotifyAccess=main (only main process can notify)

Benefits:
- systemd knows when service is truly ready
- Automatic detection of hung/frozen service
- Better integration with systemd supervision
- More accurate service status reporting

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Jacquin Antoine
2026-03-01 01:06:20 +01:00
parent 78c9102602
commit dcd6bd0a94
4 changed files with 55 additions and 2 deletions

View File

@ -10,6 +10,7 @@ import (
"syscall"
"time"
"github.com/coreos/go-systemd/v22/daemon"
"ja4sentinel/api"
"ja4sentinel/internal/capture"
"ja4sentinel/internal/config"
@ -66,6 +67,42 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Signal readiness to systemd
if _, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
appLogger.Warn("main", "Failed to send READY notification to systemd", map[string]string{
"error": err.Error(),
})
}
// Start watchdog goroutine if enabled
watchdogInterval, err := daemon.SdWatchdogEnabled(false)
if err != nil {
appLogger.Warn("main", "Failed to check watchdog status", map[string]string{
"error": err.Error(),
})
}
if watchdogInterval > 0 {
appLogger.Info("main", "systemd watchdog enabled", map[string]string{
"interval": watchdogInterval.String(),
})
go func() {
ticker := time.NewTicker(watchdogInterval / 2)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if _, err := daemon.SdNotify(false, daemon.SdNotifyWatchdog); err != nil {
appLogger.Warn("main", "Failed to send WATCHDOG notification", map[string]string{
"error": err.Error(),
})
}
case <-ctx.Done():
return
}
}
}()
}
// Setup signal handling
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
@ -176,6 +213,14 @@ func main() {
// Graceful shutdown
appLogger.Info("main", "Shutting down...", nil)
// Signal stopping to systemd
if _, err := daemon.SdNotify(false, daemon.SdNotifyStopping); err != nil {
appLogger.Warn("main", "Failed to send STOPPING notification to systemd", map[string]string{
"error": err.Error(),
})
}
cancel()
// Close components