Skip to content

Instantly share code, notes, and snippets.

@maksadbek
Last active August 29, 2015 14:21
Show Gist options
  • Save maksadbek/011b526f3b12d6a22145 to your computer and use it in GitHub Desktop.
Save maksadbek/011b526f3b12d6a22145 to your computer and use it in GitHub Desktop.
simple go http daemon
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"os/exec"
"os/signal"
"strconv"
"syscall"
)
var (
sig = make(chan os.Signal)
stop = make(chan bool)
res = make(chan bool)
)
type Server struct {
Listener net.Listener
}
func (srv *Server) Close() {
srv.Listener.Close()
}
func sendTERM(pid int) error {
process, err := os.FindProcess(pid)
if err != nil {
return err
}
err = process.Signal(syscall.SIGTERM)
if err != nil {
return err
}
return nil
}
func sendHUP(pid int) error {
process, err := os.FindProcess(pid)
if err != nil {
return err
}
err = process.Signal(syscall.SIGHUP)
if err != nil {
return err
}
return nil
}
func readPid(fileName string) (int, error) {
var pid int
p, err := ioutil.ReadFile(fileName)
if err != nil {
return pid, err
}
pid, err = strconv.Atoi(string(p))
if err != nil {
return pid, err
}
return pid, nil
}
var server Server
func main() {
daemon := flag.Bool("d", true, "do not touch it")
control := flag.String("s", "start", `send signal to the daemon
stop - stop the daemon
restart - restart the daemon`)
flag.Parse()
switch *control {
case "stop":
pid, err := readPid("pid")
if err != nil {
log.Println("cannot read pid")
os.Exit(1)
}
err = sendTERM(pid)
if err != nil {
log.Println("cannot send term signal to pid:", strconv.Itoa(pid))
os.Exit(1)
}
os.Exit(0)
case "restart":
pid, err := readPid("pid")
if err != nil {
log.Println("cannot read pid")
os.Exit(1)
}
err = sendHUP(pid)
if err != nil {
log.Println("cannot send term signal to pid:", strconv.Itoa(pid))
os.Exit(1)
}
os.Exit(0)
case "start":
break
default:
fmt.Println(` send signal to the daemon
stop - stop the daemon
restart - restart the daemon`)
os.Exit(1)
}
log.Println(*daemon)
signal.Notify(sig, syscall.SIGTERM, syscall.SIGHUP)
go sigCatch()
go stopd()
go resd()
if *daemon == true {
res <- true
stop <- true
}
go worker()
f, err := os.Create("pid")
if err != nil {
panic(err)
}
pid := os.Getpid()
log.Println("my pid is", pid)
pidStr := strconv.Itoa(pid)
_, err = f.Write([]byte(pidStr))
if err != nil {
panic(err)
}
f.Close()
<-stop
}
func sigCatch() {
for {
select {
case s := <-sig:
if s == syscall.SIGTERM {
log.Println("got term signal")
stop <- true
break
} else if s == syscall.SIGHUP {
log.Println("got hup signal")
server.Close()
res <- true
break
}
}
}
}
func stopd() {
<-stop
log.Println("stop")
os.Exit(0)
}
func resd() {
<-res
log.Println("restart")
logFile, err := os.Create("logs")
if err != nil {
panic(err)
}
defer logFile.Close()
cmd := exec.Command(os.Args[0], "-d=false")
cmd.Stdout = logFile
cmd.Stderr = logFile
err = cmd.Start()
if err != nil {
panic(err)
}
stop <- true
}
func worker() {
var err error
server.Listener, err = net.Listen("tcp", ":1234")
if err != nil {
panic(err)
}
serve := &http.Server{Handler: webHandlers()}
serve.Serve(server.Listener)
}
func sayHi(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hi"))
}
func webHandlers() http.Handler {
web := http.NewServeMux()
web.HandleFunc("/hi", sayHi)
return web
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment