golang代码笔记 -- 使用pid文件控制程序多实例运行

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/villare/article/details/85453489

主要包含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...")
}

猜你喜欢

转载自blog.csdn.net/villare/article/details/85453489