Skip to content

Commit

Permalink
0.0.2:增加进程守护,增加自动重启释放资源
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjia404 committed Apr 29, 2023
1 parent 89f77c8 commit e1ca8a8
Show file tree
Hide file tree
Showing 3 changed files with 257 additions and 1 deletion.
42 changes: 41 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"runtime"
"time"

"github.com/chenjia404/go-p2ptunnel/pRuntime"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peerstore"
Expand Down Expand Up @@ -191,7 +192,7 @@ func createLibp2pHost(ctx context.Context, priv crypto.PrivKey) (host.Host, erro
}

var (
version = "0.0.1"
version = "0.0.2"
gitRev = ""
buildTime = ""
)
Expand All @@ -207,6 +208,45 @@ func main() {
networkType := flag.String("type", "tcp", "network type tcp/udp")
flag.Parse()

RE:
proc, err := pRuntime.NewProc()
if err != nil {
fmt.Println("up proc fail........")
}
//如果proc为nil表示当前进程已经是子进程了
//不为空表示当前进程为主进程
if proc != nil {
go func() {
pRuntime.HandleEndSignal(func() {
if err := proc.Kill(); err != nil {
fmt.Println(err)
}
fmt.Println("main proc exit....")

os.Exit(0)
})
}()
//等待子进程退出后 重启
err = proc.Wait()
if err != nil {
fmt.Println("proc wait err........")
} else {
goto RE
}
return
} else {

go func() {
now := time.Now()
next := now.Add(time.Hour * 4)
timer := time.NewTimer(next.Sub(now))
t := <-timer.C //从定时器拿数据
fmt.Println("restart time:", t)
os.Exit(0)
}()

}

ctx, cancel := context.WithCancel(context.Background())

priv, _ := loadUserPrivKey()
Expand Down
169 changes: 169 additions & 0 deletions pRuntime/pRuntime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package pRuntime

import (
"errors"
"io/ioutil"
"log"
"os"
"os/exec"
"os/signal"
"runtime"
"strconv"
"syscall"
)

var pidFile = "go-p2ptunnel.pid"

func SetPidFile(pFile string) {
pidFile = pFile
}

func forkDaemon(isWritePidFile bool, environ ...string) (*exec.Cmd, error) {
cmdRet := &exec.Cmd{
Path: os.Args[0],
Args: os.Args,
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
Env: append(os.Environ(), environ...),
}
err := cmdRet.Start()
if err != nil {
return nil, err
}
//写入pid
if isWritePidFile {
err = ioutil.WriteFile(pidFile, []byte(strconv.Itoa(cmdRet.Process.Pid)), 0666)
}
if err != nil {
return nil, err
}
return cmdRet, nil
}

func DaemonInit() {
if runtime.GOOS == "windows" {
return
}
if os.Getenv("__Daemon") == "true" {
return
}
c := "start"
if l := len(os.Args); l > 1 {
c = os.Args[l-1]
}
switch c {
case "start":
if CheckProIsRun() {
log.Fatal("当前进程已运行...")
}
cmdRet, err := forkDaemon(true, "__Daemon=true")
if err != nil {
log.Fatal("start err : ", err)
}
log.Println("Daemon is run... pid: ", cmdRet.Process.Pid)
case "restart":
err := Stop()
if err != nil {
log.Fatal("restart stop err : ", err)
}
os.Args = os.Args[:len(os.Args)-1]
cmdRet, err := forkDaemon(true, "__Daemon=true")
if err != nil {
log.Fatal("forkDaemon err : ", err)
}
log.Println("Daemon is run... pid: ", cmdRet.Process.Pid)
case "stop":
err := Stop()
if err != nil {
log.Fatal("stop err : ", err)
}
log.Println("Daemon is stop....")
case "reload":
err := Reload()
if err != nil {
log.Fatal("reload err : ", err)
}
log.Println("Daemon reload success....")
}
os.Exit(0)
}

func CheckProIsRun() bool {
if GetRunningPid() == 0 {
return false
}
return true
}

func FileExists(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
if err != nil {
if os.IsExist(err) {
return true
}
return false
}
return true
}

func GetRunningPid() int {
if !FileExists(pidFile) {
return 0
}
b, err := ioutil.ReadFile(pidFile)
if err != nil {
log.Fatal("程序异常:", err)
}
pid, _ := strconv.Atoi(string(b))
p, err := os.FindProcess(pid)
if err != nil {
return 0
}
err = p.Signal(syscall.Signal(0))
if err == nil {
return p.Pid
}
_ = os.Remove(pidFile)
return 0
}

func HandleEndSignal(fn func()) {
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
_ = os.Remove(pidFile)
fn()
return
}

func HandleReloadSignal(fn func()) {
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGHUP)
for {
<-sig
fn()
}
}

func Stop() error {
if !CheckProIsRun() {
return errors.New("进程没有运行")
}
pro, err := os.FindProcess(GetRunningPid())
if err != nil {
return err
}
return pro.Signal(syscall.SIGTERM)
}

func Reload() error {
if !CheckProIsRun() {
return errors.New("进程没有运行")
}
pro, err := os.FindProcess(GetRunningPid())
if err != nil {
return err
}
return pro.Signal(syscall.SIGHUP)
}
47 changes: 47 additions & 0 deletions pRuntime/proc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package pRuntime

import (
"fmt"
"os"
)

type Proc struct {
proc *os.Process
procState *os.ProcessState
}

func NewProc() (*Proc, error) {
if os.Getenv("__NewProc") == "true" {
return nil, nil
}
cmdRet, err := forkDaemon(false, "__NewProc=true")
if err != nil {
return nil, err
}
return &Proc{
proc: cmdRet.Process,
}, nil
}

func (p *Proc) Pid() int {
if p.proc == nil {
return 0
}
return p.proc.Pid
}

func (p *Proc) Kill() error {
if p.proc == nil {
return fmt.Errorf("proc is null")
}
return p.proc.Kill()
}

func (p *Proc) Wait() error {
var err error
p.procState, err = p.proc.Wait()
if err != nil {
return err
}
return nil
}

0 comments on commit e1ca8a8

Please sign in to comment.