golang 管理 pidfile


Pidfile 存儲了進程的進程 id。一般情況下 pidfile 有以下幾個作用:

  • 其他進程可以讀取 pidfile 獲取運行進程的 pid(當然也可以通過其他命令 動態獲取)
  • 在啟動進程前先檢查 pidfile,防止啟動多個后台進程(特別像 agent 之類的)

下面是 docker 中管理 pidfile 的方法:

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"
)

func main() {
	_, err := NewPIDFile("pid.file")
	if err != nil {
		log.Errorf("error to create the pid file failed:%s", err.Error())
	}
}

// PIDFile stored the process id
type PIDFile struct {
	path string
}

// just suit for linux
func processExists(pid string) bool {
	if _, err := os.Stat(filepath.Join("/proc", pid)); err == nil {
		return true
	}
	return false
}

func checkPIDFILEAlreadyExists(path string) error {
	if pidByte, err := ioutil.ReadFile(path); err == nil {
		pid := strings.TrimSpace(string(pidByte))
		if processExists(pid) {
			return fmt.Errorf("ensure the process:%s is not running pid file:%s", pid, path)
		}
	}
	return nil
}

// NewPIDFile create the pid file 
// 指定路徑下生產 pidfile, 文件內容為 pid
func NewPIDFile(path string) (*PIDFile, error) {
	if err := checkPIDFILEAlreadyExists(path); err != nil {
		return nil, err
	}

	if err := os.MkdirAll(filepath.Dir(path), os.FileMode(0755)); err != nil {
		return nil, err
	}
	if err := ioutil.WriteFile(path, []byte(fmt.Sprintf("%d", os.Getpid())), 0644); err != nil {
		return nil, err
	}
	return &PIDFile{path: path}, nil
}

// Remove remove the pid file
func (file PIDFile) Remove() error {
	return os.Remove(file.path)
}

Tips:

  • 不同操作系統判斷進程是否存在的方式是不一樣的.文中的是檢測 linux 下進程是否存在的方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM