增加后台运行

This commit is contained in:
samwaf
2023-05-25 09:46:02 +08:00
parent e16ef9be0a
commit 0a07db9b3b
9 changed files with 211 additions and 4 deletions

View File

@@ -2,4 +2,4 @@ SET CGO_ENABLED=1
SET GOOS=windows
SET GOARCH=amd64
SET GIN_MODE=release
go build -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230329 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w" -o %cd%/release/SamWaf64.exe main.go && %cd%/upx/win64/upx -9 %cd%/release/SamWaf64.exe
go build -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230525 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w" -o %cd%/release/SamWaf64.exe main.go && %cd%/upx/win64/upx -9 %cd%/release/SamWaf64.exe

1
go.mod
View File

@@ -15,6 +15,7 @@ require (
github.com/satori/go.uuid v1.2.0
github.com/spf13/viper v1.13.0
github.com/stretchr/testify v1.8.0
github.com/takama/daemon v1.0.0
go.uber.org/zap v1.21.0
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
golang.org/x/text v0.3.7

4
go.sum
View File

@@ -232,6 +232,7 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -270,6 +271,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/takama/daemon v1.0.0 h1:XS3VLnFKmqw2Z7fQ/dHRarrVjdir9G3z7BEP8osjizQ=
github.com/takama/daemon v1.0.0/go.mod h1:gKlhcjbqtBODg5v9H1nj5dU1a2j2GemtuWSNLD5rxOE=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
@@ -422,6 +425,7 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

36
main.go
View File

@@ -11,6 +11,7 @@ import (
"SamWaf/utils/zlog"
"SamWaf/wafenginecore"
"SamWaf/waftask"
"SamWaf/xdaemon"
"crypto/tls"
dlp "github.com/bytedance/godlp"
"github.com/go-co-op/gocron"
@@ -20,6 +21,7 @@ import (
"log"
"net/http"
"os"
"os/exec"
"runtime"
"strconv"
"syscall"
@@ -27,6 +29,7 @@ import (
)
func main() {
rversion := "初始化系统 版本号:" + global.GWAF_RELEASE_VERSION_NAME + "(" + global.GWAF_RELEASE_VERSION + ")"
if global.GWAF_RELEASE == "false" {
rversion = rversion + " 调试版本"
@@ -48,6 +51,39 @@ func main() {
if err != nil {
log.Fatal(err)
}
// if received any kind of command, do it
if len(os.Args) > 1 {
command := os.Args[1]
switch command {
case "-d":
logFile := "./logs/daemon.log"
//启动一个子进程后主程序退出
xdaemon.Background(logFile, true)
break
case "-c":
println("关闭")
if runtime.GOOS == "windows" {
c := exec.Command("taskkill.exe", "/f", "/im", "SamWaf.exe")
c.Start()
} else {
println("SamWaf -d")
}
break
case "-help":
if runtime.GOOS == "windows" {
println("SamWaf.exe -d 是后台运行 -c 是强制关闭 -help 是帮助说明")
} else {
println("SamWaf -d 是后台运行 -c 是强制关闭 -help 是帮助说明")
}
break
default:
println(command)
}
}
//守护程序开始
//xdaemon.DaemonProcess("GoTest.exe","./logs/damon.log")
/*runtime.GOMAXPROCS(1) // 限制 CPU 使用数,避免过载
runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪
runtime.SetBlockProfileRate(1) // 开启对阻塞操作的跟踪

4
vue/dist/index.html vendored
View File

@@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sam网站应用级入侵防御系统后台Web Application Firewall</title>
<script type="module" crossorigin src="./assets/index.d7381a43.js"></script>
<link rel="stylesheet" href="./assets/style.ce473e80.css">
<script type="module" crossorigin src="./assets/index.e09d30b7.js"></script>
<link rel="stylesheet" href="./assets/style.24f2db9d.css">
</head>
<body>
<div id="app"></div>

12
xdaemon/attr_default.go Normal file
View File

@@ -0,0 +1,12 @@
//go:build !windows && !plan9
// +build !windows,!plan9
package xdaemon
import "syscall"
func NewSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
Setsid: true,
}
}

12
xdaemon/attr_windows.go Normal file
View File

@@ -0,0 +1,12 @@
//go:build windows
// +build windows
package xdaemon
import "syscall"
func NewSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
HideWindow: true,
}
}

142
xdaemon/daemon.go Normal file
View File

@@ -0,0 +1,142 @@
package xdaemon
import (
"fmt"
"log"
"os"
"os/exec"
"strconv"
"time"
)
const ENV_NAME = "XW_DAEMON_IDX"
//运行时调用background的次数
var runIdx int = 0
//守护进程
type Daemon struct {
LogFile string //日志文件, 记录守护进程和子进程的标准输出和错误输出. 若为空则不记录
MaxCount int //循环重启最大次数, 若为0则无限重启
MaxError int //连续启动失败或异常退出的最大次数, 超过此数, 守护进程退出, 不再重启子进程
MinExitTime int64 //子进程正常退出的最小时间(秒). 小于此时间则认为是异常退出
}
// 把本身程序转化为后台运行(启动一个子进程, 然后自己退出)
// logFile 若不为空,子程序的标准输出和错误输出将记入此文件
// isExit 启动子加进程后是否直接退出主程序, 若为false, 主程序返回*os.Process, 子程序返回 nil. 需自行判断处理
func Background(logFile string, isExit bool) (*exec.Cmd, error) {
//判断子进程还是父进程
runIdx++
envIdx, err := strconv.Atoi(os.Getenv(ENV_NAME))
if err != nil {
envIdx = 0
}
if runIdx <= envIdx { //子进程, 退出
return nil, nil
}
//设置子进程环境变量
env := os.Environ()
env = append(env, fmt.Sprintf("%s=%d", ENV_NAME, runIdx))
//启动子进程
cmd, err := startProc(os.Args, env, logFile)
if err != nil {
log.Println(os.Getpid(), "启动子进程失败:", err)
return nil, err
} else {
//执行成功
log.Println(os.Getpid(), ":", "启动子进程成功:", "->", cmd.Process.Pid, "\n ")
}
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 {
//daemon 信息描述
dInfo := fmt.Sprintf("守护进程(pid:%d; count:%d/%d; errNum:%d/%d):",
os.Getpid(), count, d.MaxCount, errNum, d.MaxError)
if errNum > d.MaxError {
log.Println(dInfo, "启动子进程失败次数太多,退出")
os.Exit(1)
}
if d.MaxCount > 0 && count > d.MaxCount {
log.Println(dInfo, "重启次数太多退出")
os.Exit(0)
}
count++
t = time.Now().Unix() //启动时间戳
cmd, err := Background(d.LogFile, false)
if err != nil { //启动失败
log.Println(dInfo, "子进程启动失败;", "err:", err)
errNum++
continue
}
//子进程,
if cmd == nil {
log.Printf("子进程pid=%d: 开始运行...", os.Getpid())
break
}
//父进程: 等待子进程退出
err = cmd.Wait()
dat := time.Now().Unix() - t //子进程运行秒数
if dat < d.MinExitTime { //异常退出
errNum++
} else { //正常退出
errNum = 0
}
log.Printf("%s 监视到子进程(%d)退出, 共运行了%d秒: %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(), ": 打开日志文件错误:", err)
return nil, err
}
cmd.Stderr = stdout
cmd.Stdout = stdout
}
err := cmd.Start()
if err != nil {
return nil, err
}
return cmd, nil
}

View File

@@ -8,7 +8,7 @@ go-bindata-assetfs.exe -o=vue/vue.go -pkg=vue vue/dist/...
# linux
//生成普通发行版未upx压缩的
docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230403 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64.exe main.go
docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230525 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64.exe main.go
//可调试的centos