主要包含golang对pid操作的封装和程序状态判断
package main
import (
"fmt"
"io/ioutil"
"os"
"os/signal"
"strconv"
"syscall"
)
func main() {
pid, exist := PidfileExit("./test_pid")
if exist {
if pid > 0 {
fmt.Printf("exec already exist:%d\n", pid)
}
} else {
if pid > 0 {
fmt.Printf("start new proc:%d", pid)
HandleSingle()
os.Remove("./test_pid")
}
}
}
func PidfileExit(pidfile string) (once_pid int, started bool) {
pf, err := os.OpenFile(pidfile, os.O_RDWR, 0)
defer pf.Close()
if os.IsNotExist(err) {
started = false
} else if err != nil {
fmt.Printf("pidfile check error:%v\n", err)
return
} else {
pd, _ := ioutil.ReadAll(pf)
old_pid, err := strconv.Atoi(string(pd))
if err == nil {
// not os.FindProcess(), Unix?
err := syscall.Kill(old_pid, 0)
if err == nil {
started = true
once_pid = old_pid
}
} else {
return
}
}
if !started {
pf, err := os.Create(pidfile)
if err != nil {
fmt.Println("create pid file error.")
return
}
new_pid := os.Getpid()
_, err = pf.Write([]byte(fmt.Sprintf("%d", new_pid)))
if err != nil {
fmt.Println("write pid failed.")
} else {
once_pid = new_pid
}
}
return
}
func HandleSingle() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGHUP)
<-sigs
fmt.Println("graceful exit...")
}