TonyChyi

我在那一角落患过抽风

用 Go 实现一个守护进程
2016年10月25日
 

 

实现一个守护进程,同时还可以调用该程序加特定参数停止该守护进程

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 调用也是可以的,但是写起来就比较麻烦了,而且还容易出现一些奇怪的问题

Tags: #Go

 

TonyChyi © 2020 GPLv2