165 lines
3.4 KiB
Go
165 lines
3.4 KiB
Go
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)
|
||
}
|
||
}
|