Commit 8c316f22 authored by Tsaiilin's avatar Tsaiilin

配置文件支持配置为守护运行模式

parent 58161403
......@@ -10,12 +10,14 @@ import (
"net/http"
_ "net/http/pprof"
"os"
"os/exec"
"os/signal"
"path/filepath"
"runtime"
"syscall"
"time"
"virjar.com/majora-go/client"
"virjar.com/majora-go/daemon"
"virjar.com/majora-go/global"
"virjar.com/majora-go/initialize"
"virjar.com/majora-go/log"
......@@ -24,7 +26,7 @@ import (
var (
configure string
daemon bool
)
var (
......@@ -32,14 +34,9 @@ var (
Date string
)
var (
cmd *exec.Cmd
)
func init() {
rand.Seed(time.Now().UnixNano())
flag.StringVar(&configure, "conf", "", "./majora -c path/to/your/majora.ini")
flag.BoolVar(&daemon, "daemon", false, "daemon")
flag.Parse()
}
......@@ -61,22 +58,6 @@ func initial() {
},
}
}
if daemon {
var args []string
for _, arg := range os.Args[1:] {
if arg != "-daemon" {
args = append(args, arg)
}
}
cmd = exec.Command(os.Args[0], args...)
cmd.Env = os.Environ()
if err := cmd.Start(); err != nil {
panic(err)
}
log.Run().Infof("%s [pid-%d] running...\n", os.Args[0], cmd.Process.Pid)
os.Exit(0)
}
}
func cli() {
......@@ -99,8 +80,15 @@ func main() {
fmt.Println(Version)
os.Exit(0)
}
initialize.MustInitConfig(configure, global.Config)
if global.Config.Daemon {
logFile := filepath.Join(global.Config.LogPath, "daemon.log")
d := daemon.NewDaemon(logFile)
d.MaxCount = 20 //最大重启次数
d.Run()
}
initialize.InitLogger()
initial()
cli()
......
......@@ -87,12 +87,10 @@ func (client *Client) check() {
continue
}
log.Run().Warnf("Redial net check fail, redial...")
if client.session != nil {
client.Redial(client.session, "check")
} else {
client.redial.RedialByCheck(cfg)
if client.redial.RedialByCheck(cfg) {
client.natTunnel.Close()
client.connect()
}
}
})
}
......@@ -98,5 +98,6 @@ func (client *Client) Redial(session getty.Session, tag string) {
log.Run().Info("[Redial %s] start close local session", tag)
client.CloseAll(session)
client.redial.Redial(client.config, tag)
session.Close()
client.natTunnel.Close()
client.connect()
}
env: debug
tunnel_addr: majora-vps-zj.virjar.com:5879
dns_server: 114.114.114.114:53
pprof_port: 16666
daemon: true
log_level: debug
log_path: ./output/log/
log_path: ./majora-log/
reconn_intervalz: 5s
net_check_interval: 5s
dns_cache_duration: 10m
net_check_url: https://www.baidu.com[extra]
account: superman
#redial:
# command: /bin/bash
# exec_path: /root/ppp_redial.sh
# redial_duration: 5m
# wait_time: 10s
redial:
command: /bin/bash
exec_path: /root/ppp_redial.sh
redial_duration: 5m
wait_time: 10s
......@@ -2,6 +2,8 @@ env: debug
tunnel_addr: majora-vps-zj.virjar.com:5879
dns_server: 114.114.114.114:53
log_level: info
log_path: ./majora-log/
daemon: true
reconn_interval: 5s
net_check_interval: 5s
net_check_url: https://www.baidu.com
......@@ -10,4 +12,4 @@ redial:
command: /bin/bash
exec_path: /root/ppp_redial.sh
redial_duration: 5m
wait_time: 10s
wait_time: 15s
......@@ -12,7 +12,6 @@ echo "old pid is ${old_pid}"
echo "clean old ..."
`ps -ef | grep majora | grep -v grep | awk '{print $2}'| xargs kill -9`
mkdir -p "majora-log"
mkdir -p output/log
exec ./majora -daemon -conf majora.yaml
\ No newline at end of file
exec ./majora -conf majora.yaml
\ No newline at end of file
......@@ -9,11 +9,11 @@ rm -fr majora.yaml
rm -fr majora.service
rm -fr majora-dev.yaml
rm -fr majora.log
rm -fr output
rm -fr majora-log
rm -fr std.log
tar -zxvf majora-cli.tar.gz
mv -f majora-cli*/* .
exec bash ./start.sh
exec bash ./start.sh
\ No newline at end of file
// +build !windows,!plan9
package daemon
import "syscall"
func NewSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
Setsid: true,
}
}
// +build windows
package daemon
import "syscall"
func NewSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
HideWindow: true,
}
}
package daemon
import (
"fmt"
"log"
"os"
"os/exec"
"strconv"
"time"
)
const EnvName = "XW_DAEMON_IDX"
var runIdx = 0
type Daemon struct {
LogFile string
MaxCount int
MaxError int
MinExitTime int64
}
func Background(logFile string, isExit bool) (*exec.Cmd, error) {
runIdx++
envIdx, err := strconv.Atoi(os.Getenv(EnvName))
if err != nil {
envIdx = 0
}
if runIdx <= envIdx {
return nil, nil
}
env := os.Environ()
env = append(env, fmt.Sprintf("%s=%d", EnvName, runIdx))
cmd, err := startProc(os.Args, env, logFile)
if err != nil {
log.Println(os.Getpid(), " Start child process error:", err)
return nil, err
} else {
log.Println(os.Getpid(), " Start child process success:", cmd.Process.Pid)
}
if isExit {
os.Exit(0)
}
return cmd, nil
}
func NewDaemon(logFile string) *Daemon {
return &Daemon{
LogFile: logFile,
MaxCount: 0,
MaxError: 3,
MinExitTime: 10,
}
}
func (d *Daemon) Run() {
_, _ = Background(d.LogFile, true)
var t int64
count := 1
errNum := 0
for {
dInfo := fmt.Sprintf("daemon process(pid:%d; count:%d/%d; errNum:%d/%d):",
os.Getpid(), count, d.MaxCount, errNum, d.MaxError)
if errNum > d.MaxError {
log.Println(dInfo, "Start child process error too many,exit")
os.Exit(1)
}
if d.MaxCount > 0 && count > d.MaxCount {
log.Println(dInfo, "Too many restarts")
os.Exit(0)
}
count++
t = time.Now().Unix()
cmd, err := Background(d.LogFile, false)
if err != nil {
log.Println(dInfo, "Start child process err:", err)
errNum++
continue
}
if cmd == nil {
log.Printf("child process pid=%d: start", os.Getpid())
break
}
err = cmd.Wait()
dat := time.Now().Unix() - t
if dat < d.MinExitTime {
errNum++
} else {
errNum = 0
}
log.Printf("%s child process(%d)exit, Ran for %d seconds: %v\n", dInfo, cmd.ProcessState.Pid(), dat, err)
}
}
func startProc(args, env []string, logFile string) (*exec.Cmd, error) {
cmd := &exec.Cmd{
Path: args[0],
Args: args,
Env: env,
SysProcAttr: NewSysProcAttr(),
}
if logFile != "" {
stdout, err := os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
log.Println(os.Getpid(), ": Open log file error", err)
return nil, err
}
cmd.Stderr = stdout
cmd.Stdout = stdout
}
err := cmd.Start()
if err != nil {
return nil, err
}
return cmd, nil
}
......@@ -26,7 +26,7 @@ func NewPPPRedial() *PPPRedial {
}
}
func (p *PPPRedial) Redial(cfg *model.Configure, tag string) {
func (p *PPPRedial) Redial(cfg *model.Configure, tag string) bool{
if p.inRedialing.CAS(false, true) {
log.Run().Infof("[PPPRedial %s] start", tag)
beforeIp := GetPPP()
......@@ -46,13 +46,15 @@ func (p *PPPRedial) Redial(cfg *model.Configure, tag string) {
}
}
p.inRedialing.CAS(true, false)
return true
} else {
log.Run().Infof("[PPPRedial %s] inRedialing ignore this", tag)
return false
}
}
func (p *PPPRedial) RedialByCheck(cfg *model.Configure) {
p.Redial(cfg, "check")
func (p *PPPRedial) RedialByCheck(cfg *model.Configure) bool {
return p.Redial(cfg, "check")
}
func command(cfg *model.Configure) bool {
......
......@@ -22,6 +22,7 @@ type Configure struct {
Env string `mapstructure:"env"`
LogLevel string `mapstructure:"log_level"`
LogPath string `mapstructure:"log_path"`
Daemon bool `mapstructure:"daemon"`
PprofPort int `mapstructure:"pprof_port"`
TunnelAddr string `mapstructure:"tunnel_addr"`
DNSServer string `mapstructure:"dns_server"`
......@@ -43,6 +44,7 @@ func NewDefMajoraConf() *Configure {
return &Configure{
Env: "product",
LogLevel: "info",
Daemon: false,
PprofPort: 0,
TunnelAddr: common.DefNatAddr,
DNSServer: common.DNSServer, //nolint:typecheck
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment