Reputation: 19
I have a system I need to operate as a daemon, which has been developed in go. Ordinarily I could just manage this though something like systemd or even just something as simple as './project &' but this particular project needs to get some input before it can become a daemon - it needs a password to be entered.
This password cannot be provided as command line args, placed in a config file, hard coded in the source etc. It must be manually provided by someone who has knowledge of the password at system startup.
At startup, the project needs to collect the password, verify that things are correct, and only if the correct password has been provided (verified by attempting to decrypt a certificate) can it then actually begin to operate as the daemon.
Is there any way in go for the project to startup, accept input from stdin, perform whatever validation is needed etc, and only then become a daemon process (detaching from stdin etc)?
Currently I can simulate the required behavior by starting it, and after the password has been entered using 'ctrl+z' to suspend it and bg to push the process to the background. Surely there has to be a way of doing that from within the process itself...
Upvotes: 0
Views: 277
Reputation: 821
here is a program that does what I think you meant.
so the program only checks the password. The actual daemon is webserver
which gets called only when password checks out.
package main
import (
"golang.org/x/crypto/ssh/terminal"
"os/exec"
)
func main() {
pwd, err := terminal.ReadPassword(1)
if err != nil {
panic(err)
}
if string(pwd) == "test" {
c := exec.Command("./webserver")
c.Run()
}
return
}
the daemon program I used here was taken from here
https://github.com/sevlyar/go-daemon/blob/master/examples/cmd/gd-simple/simple.go
Its not possible to run a single program both as waiting for input and as a daemon.
Upvotes: 1
Reputation: 1
You could use flags and carefully control your app flow and run itself as a daemon if a given flag (such as encrypted credentials) is passed. Or even store them in a temporary file, database or anywhere.
func main() {
cred := flag.String("cred", "", "raw cred")
flag.Parse()
if *cred == "" {
fmt.Print("Enter credentials:\n")
decryptedCred, _ := bufio.NewReader(os.Stdin).ReadString('\n')
if !validCred(decryptedCred) {
os.Exit(1)
}
encryptedCred := encryptCredentials(decryptedCred)
cmd := exec.Command("./project", fmt.Sprintf("-cred=%s", encryptedCred), "&")
cmd.Start()
fmt.Printf("Started project with pid: %d\n", cmd.Process.Pid)
os.Exit(0)
}
for {
// start app
// use *cred here
}
}
Whatever the approach I would probably keep track of the pid, etc.
./project
# Enter credentials:
myCredentialsString
# Started project with pid: 11702
ps ax | grep project
# 11667 s001 R 0:02.47 ./project -cred=N/esPq8wsWn4/+Gco16ddl9UnJ0= &\012
Hope this helps
Upvotes: 0