用 Go 实现一个守护进程
实现一个守护进程,同时还可以调用该程序加特定参数停止该守护进程
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"time"
)
func main() {
// 处理程序后的参数
if len(os.Args[1:]) > 0 {
switch os.Args[1] {
// 停止守护进程,从 /tmp/pidfile 中获取进程 ID
case "stop":
bpid, _ := ioutil.ReadFile("/tmp/pidfile")
pid, _ := strconv.Atoi(string(bpid))
proc, _ := os.FindProcess(pid)
proc.Kill()
fmt.Println("Killed.")
os.Exit(0)
}
}
// 启动守护进程,即当自身的父进程不为 1 时,就启动一个新的进程,
// 并退出自己,直到父进程为 1 (一般是 init)为止
if os.Getppid() != 1 {
exePath, _ := filepath.Abs(os.Args[0])
cmd := exec.Command(exePath, os.Args[1:]...)
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Start()
fmt.Println("Start...")
os.Exit(0)
}
// 将自已的进程号写入一个文件,以备后续可以退出进程
ioutil.WriteFile("/tmp/pidfile", []byte(fmt.Sprint(os.Getpid())), 0666)
// 模拟守护进程的操作
for {
fmt.Println("Backend Running...")
time.Sleep(2 * time.Second)
}
}
事实上,通过 fork 调用也是可以的,但是写起来就比较麻烦了,而且还容易出现一些奇怪的问题