pidproxy 实现
参考python的supervisor pidproxy实现
https://github.com/Supervisor/supervisor/blob/master/supervisor/pidproxy.py
子进程检查
package pidproxy
import (
"errors"
"io/ioutil"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
"github.com/spf13/cobra"
)
func getPid(pidfile string) (int, error) {
dt, err := ioutil.ReadFile(pidfile)
if err != nil {
return -1, err
}
if len(dt) == 0 {
return -1, errors.New("pid is null")
}
pid, err := strconv.Atoi(string(dt))
if err != nil {
return -1, err
}
return pid, err
}
func GetCmd() *cobra.Command {
var signals = []os.Signal{
syscall.SIGHUP,
syscall.SIGUSR1,
syscall.SIGUSR2,
syscall.SIGTSTP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT,
syscall.SIGCHLD,
}
var sigChan = make(chan os.Signal)
var pid = -1
var pidfile = ""
var forkExec = func(argv0 string, argv []string) (pid int, err error) {
return syscall.ForkExec(argv0, argv, &syscall.ProcAttr{
Env: os.Environ(),
Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
})
}
return &cobra.Command{
Use: "pp",
Short: "Run as a pidproxy server",
Example: `dio pp <pidfile name> "<command> [<cmdarg1> ...]"
dio pp test.pid "/usr/local/bin/etcd --name=default"`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
if len(args) < 2 {
return errors.New("请输入pidfile和需要执行的命令以及参数")
}
if strings.TrimSpace(args[1]) == "" {
return errors.New("command命令为空")
}
command := strings.Split(args[1], " ")
pid, err = forkExec(command[0], command)
if err != nil {
return err
}
// 防止子进程变成僵尸进程
go func(pid int) {
for {
_, _ = syscall.Wait4(pid, nil, syscall.WNOWAIT, nil)
time.Sleep(time.Second * 5)
return
}
}(pid)
pidfile = args[0]
if err := ioutil.WriteFile(pidfile, []byte(strconv.Itoa(pid)), 0600); err != nil {
return err
}
signal.Notify(sigChan, signals...)
var tk = time.Tick(time.Second * 2)
var sig os.Signal
for {
select {
// pidproxy进程获取信号
case sig = <-sigChan:
// 定时监控子进程状态
case <-tk:
// 信号0一般用来检查进程是否存在, 没有具体的意义
sig = syscall.Signal(0)
}
// 获取子命令pid
if pid, err = getPid(pidfile); err != nil {
return err
}
// 校验pid是否存在
proc, err := os.FindProcess(pid)
if err != nil {
return err
}
// 给子命令发送信号, 如果程序有问题, 就退出重启
if err := proc.Signal(sig); err != nil {
return err
}
switch sig {
case syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT:
os.Exit(0)
}
}
},
}
}
作者:百里求一
出处:http://www.cnblogs.com/bergus/
我的语雀: https://www.yuque.com/barry.bai
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】FlashTable:表单开发界的极速跑车,让你的开发效率一路狂飙
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 于是转身独立开发者
· C#.Net筑基-泛型T & 协变逆变
· dotnet 代码调试方法
· DbContext是如何识别出实体集合的
· 一次 .NET 性能优化之旅:将 GC 压力降低 99%
· 免费开源 .NET OpenCV 迷你运行时全平台发布
· 10亿订单如何分库分表?
· 一个static关键字引发的线上故障:深度剖析静态变量与配置热更新的陷阱
· C# 的深度强化学习框架RL_Matrix
· 如何基于three.js(webgl)引擎架构,实现3D医院、3D园区导航,3D科室路径导航