From 2d7625101fd73d4bbcdebe2105a60612b9448bcb Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Sat, 25 Jan 2025 00:55:02 +0200 Subject: [PATCH] implement daemonization --- go.mod | 6 ++++++ go.sum | 6 ++++++ main.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index d77dc34..2f62166 100644 --- a/go.mod +++ b/go.mod @@ -6,3 +6,9 @@ require ( github.com/google/uuid v1.6.0 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 ) + +require ( + github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect + github.com/sevlyar/go-daemon v0.1.6 + golang.org/x/sys v0.29.0 // indirect +) diff --git a/go.sum b/go.sum index 3a5a0f9..54428a7 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,12 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/sevlyar/go-daemon v0.1.6 h1:EUh1MDjEM4BI109Jign0EaknA2izkOyi0LV3ro3QQGs= +github.com/sevlyar/go-daemon v0.1.6/go.mod h1:6dJpPatBT9eUwM5VCw9Bt6CdX9Tk6UWvhW3MebLDRKE= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/main.go b/main.go index 025b4a2..fb57d8c 100644 --- a/main.go +++ b/main.go @@ -10,10 +10,12 @@ import ( "lux/rpc" "os" "os/signal" + "strconv" "strings" "syscall" "github.com/op/go-logging" + "github.com/sevlyar/go-daemon" ) var isNode bool @@ -117,6 +119,45 @@ func bootstrapNode() { var log = logging.MustGetLogger("main") +func becomeDaemon() { + cwd, err := os.Getwd() + if err != nil { + log.Criticalf("Getwd failed: %v", err) + os.Exit(1) + } + + ctx := &daemon.Context{ + PidFileName: pidPath, + PidFilePerm: 0644, + WorkDir: cwd, + Umask: 027, + } + + dmn, err := ctx.Reborn() + if err != nil { + log.Criticalf("ctx.Reborn failed: %v", err) + os.Exit(1) + } + if dmn != nil { + ctx.Release() + + // parent process no longer needed + os.Exit(0) + } + defer ctx.Release() + + // -- WE ARE NOW THE DAEMON -- + + // write pid + if pidPath != "" { + pidFile, _ := os.OpenFile(pidPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + defer pidFile.Close() + + pidBytes := []byte(strconv.Itoa(os.Getpid())) + pidFile.Write(pidBytes) + } +} + func nodeMain() { xmlBytes, err := os.ReadFile(configPath) if err != nil { @@ -126,13 +167,19 @@ func nodeMain() { var config NodeConfig if err := xml.Unmarshal(xmlBytes, &config); err != nil { - log.Criticalf("failed to parse xml: %v\n", err) + log.Criticalf("failed to parse xml: %v", err) os.Exit(1) } // setup logging setupLogging(config.Log) + // only after logging setup, we may became daemon + println(pidPath) + if daemonize { + becomeDaemon() + } + // check presense of keystore and id in config if config.KeyStore == "" { log.Critical("no keystore path specified!") @@ -145,14 +192,14 @@ func nodeMain() { nodeId, err := proto.ParseLuxID(config.ID) if err != nil { - log.Criticalf("failed to parse node id: %v\n", err) + log.Criticalf("failed to parse node id: %v", err) os.Exit(1) } // load keystore ks := crypto.NewLuxKeyStore(config.KeyStore) if err := ks.Load(); err != nil { - log.Criticalf("failed to laod keystore: %v\n", err) + log.Criticalf("failed to laod keystore: %v", err) os.Exit(1) } @@ -168,13 +215,13 @@ func nodeMain() { // add interior exterior channels for _, interior := range config.Interior { if err := node.AddInterior(interior); err != nil { - log.Criticalf("failed to add interior %s: %v\n", interior, err) + log.Criticalf("failed to add interior %s: %v", interior, err) os.Exit(1) } } for _, exterior := range config.Exterior { if err := node.AddExterior(exterior); err != nil { - log.Criticalf("failed to add exterior %s: %v\n", exterior, err) + log.Criticalf("failed to add exterior %s: %v", exterior, err) os.Exit(1) } } @@ -183,12 +230,12 @@ func nodeMain() { for _, neighbor := range config.Neighbors { neighId, err := proto.ParseLuxID(neighbor.ID) if err != nil { - log.Criticalf("failed to parse neigh id %s: %v\n", neighbor.ID, err) + log.Criticalf("failed to parse neigh id %s: %v", neighbor.ID, err) os.Exit(1) } if err := node.AddNeighbor(neighId, neighbor.Address); err != nil { - log.Criticalf("failed to add neighbor %s: %v\n", neighbor.ID, err) + log.Criticalf("failed to add neighbor %s: %v", neighbor.ID, err) os.Exit(1) } } @@ -203,14 +250,14 @@ func nodeMain() { path := rpcPath[7:] if err := sv.AddEndpoint("unix", path, rpc.LuxRpcTypeRoot); err != nil { - log.Criticalf("failed to add root rpc %s: %v\n", path, err) + log.Criticalf("failed to add root rpc %s: %v", path, err) os.Exit(1) } } else if strings.HasPrefix(rpcPath, "tcp://") { path := rpcPath[6:] if err := sv.AddEndpoint("tcp", path, rpc.LuxRpcTypeQuery); err != nil { - log.Criticalf("failed to add query rpc %s: %v\n", path, err) + log.Criticalf("failed to add query rpc %s: %v", path, err) os.Exit(1) } } else { @@ -364,7 +411,7 @@ func main() { flag.StringVar(&configPath, "config", "", "node or host config") flag.BoolVar(&bootstrap, "bootstrap", false, "bootstrap node keystore. config must be specified") flag.BoolVar(&justNodeId, "just-node-id", false, "when bootstrapping only output node id to stdout") - flag.BoolVar(&daemonize, "daemonize", false, "run LUX as daemon in background") + flag.BoolVar(&daemonize, "daemon", false, "run LUX as daemon in background") flag.StringVar(&pidPath, "pid", "", "after daemonization LUX will write its PID here") flag.StringVar(&rpcPath, "rpc", "", "Run as RPC client, specify path to RPC UNIX socket or TCP socket, must be in unix:// or tcp:// form")