Skip to content

Instantly share code, notes, and snippets.

@mrccnt
Last active October 23, 2023 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrccnt/ab862481c98033c63143993405a39b0c to your computer and use it in GitHub Desktop.
Save mrccnt/ab862481c98033c63143993405a39b0c to your computer and use it in GitHub Desktop.
Start and stop redis server as process in background in golang
package main
import (
"log"
"os"
"syscall"
"time"
)
// Prerequisites:
//
// * redis binary available
// * redis.conf available
// * redis user and group available
// * /var/lib/redis exists and ownership is redis:redis
//
// Example redis.conf:
//
// protected-mode yes
// requirepass redis
// dir /var/lib/redis
// appendonly yes
// maxmemory 128mb
//
// Concerning `Files []*os.File`:
//
// The first three entries correspond to standard input, standard output,
// and standard error.
//
// On Unix systems, StartProcess will change these File values
// to blocking mode, which means that SetDeadline will stop working
// and calling Close will not interrupt a Read or Write.
//
// Attention:
//
// Starting a process with specific UIDs/GIDs requires being root.
// I do not like running `sudo go run` so I just build as usual and
// execute binary via sudo but hey; fire at will...
// go build -o mybin . && sudo ./mybin
func main() {
// Replace own paths, uids, gids, etc
ex := "/usr/bin/redis-server"
cfg := "/etc/redis.conf"
dir := "/var/lib/redis"
uid := uint32(133)
gid := uint32(137)
redis, err := os.StartProcess(ex, []string{ex, cfg}, &os.ProcAttr{
Dir: dir,
Env: os.Environ(),
Files: []*os.File{
os.Stdin,
os.Stdout,
os.Stderr,
},
Sys: &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
Groups: []uint32{},
},
Noctty: true,
},
})
if err != nil {
log.Fatalln(err.Error())
}
pid := redis.Pid
_ = redis.Release()
// Wait 10 secs before shutting down
time.Sleep(10 * time.Second)
p, err := os.FindProcess(pid)
if err != nil {
log.Fatalln(err.Error())
}
if err = p.Signal(syscall.SIGTERM); err != nil {
log.Fatalln(err.Error())
}
state, err := p.Wait()
if err != nil {
log.Println("Wait:", err.Error())
}
log.Println("State:", state.String())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment