mirror of
https://github.com/chenjia404/go-p2ptunnel.git
synced 2025-09-26 19:31:13 +08:00
0.0.2:增加进程守护,增加自动重启释放资源
This commit is contained in:
42
main.go
42
main.go
@@ -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"
|
||||
@@ -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 = ""
|
||||
)
|
||||
@@ -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()
|
||||
|
169
pRuntime/pRuntime.go
Normal file
169
pRuntime/pRuntime.go
Normal file
@@ -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
pRuntime/proc.go
Normal file
47
pRuntime/proc.go
Normal file
@@ -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
|
||||
}
|
Reference in New Issue
Block a user