Files
go-process-guardian/main.go
2025-07-14 19:03:06 +08:00

165 lines
3.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"bufio"
"context"
"flag"
"fmt"
"go-process-guardian/services"
"io"
"log"
"os"
"os/exec"
"os/signal"
"strings"
"sync"
"syscall"
)
var (
v = flag.Bool("v", false, "查看版本")
start = flag.String("start", "", "启动文件地址")
name = flag.String("name", "", "名称")
restart = flag.String("restart", "", "重启")
stop = flag.String("stop", "", "停止")
dir = flag.String("dir", "", "项目目录")
projectType = flag.String("type", "", "项目类型")
install = flag.Bool("install", false, "安装") // 安装
uninstall = flag.Bool("uninstall", false, "卸载") // 卸载
)
func main() {
flag.Parse()
if *v {
fmt.Println("1.0.1")
return
}
if *install {
services.InstallService()
return
}
if *uninstall {
services.UninstallService()
return
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cmd := createCommandContext(ctx, *projectType, *start, *dir)
// 创建新的会话组脱离主进程控制
if *start != "" {
fmt.Println("启动:", *start)
}
if *name != "" {
fmt.Println("名称:", *name)
}
if *restart != "" {
fmt.Println("重启:", *restart)
}
if *stop != "" {
fmt.Println("停止:", *stop)
}
if *dir != "" {
cmd.Dir = *dir
} else {
cmd.Dir = "."
}
// if err := cmd.Start(); err != nil {
// fmt.Println("运行报错")
// }
// 创建管道捕获标准输出
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Errorf("创建标准输出管道失败: %v", err)
}
// 创建管道捕获标准错误
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Errorf("创建标准错误管道失败: %v", err)
}
// 启动命令
if err := cmd.Start(); err != nil {
fmt.Errorf("启动命令失败: %v", err)
}
// 使用 WaitGroup 等待输出处理完成
var wg sync.WaitGroup
wg.Add(2)
// 处理标准输出
go func() {
defer wg.Done()
scanAndCapture(stdout, "STDOUT")
}()
// 处理标准错误
go func() {
defer wg.Done()
scanAndCapture(stderr, "STDERR")
}()
// 等待命令执行完成
if err := cmd.Wait(); err != nil {
fmt.Errorf("命令执行失败: %v", err)
}
setupSignalHandler()
// 等待所有输出处理完成
wg.Wait()
cmd.Wait()
}
// 扫描并捕获输出
func scanAndCapture(reader io.Reader, prefix string) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
var outputLines []string
// 捕获输出行最多保留1000行
outputLines = append(outputLines, line)
if len(outputLines) > 1000 {
outputLines = outputLines[1:]
}
// 实时显示
// fmt.Printf("[%s] %s\n", prefix, line)
log.Println(line)
}
}
func setupSignalHandler() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("\n接收到中断信号停止子进程...")
os.Exit(0)
}()
}
func createCommandContext(ctx context.Context, projectType string, start string, dir string) *exec.Cmd {
var fileType string
if projectType != "" {
fileType = projectType
} else {
typeArr := strings.Split(start, ".")
fileType = typeArr[len(typeArr)-1]
}
log.Println()
switch fileType {
case "go":
return exec.CommandContext(ctx, "go", "run", start)
case "node":
return exec.CommandContext(ctx, "node", start)
case "exe":
return exec.CommandContext(ctx, dir+"\\"+start)
default:
return exec.CommandContext(ctx, "go", "run", start)
}
}