多个模块,部分功能完成
This commit is contained in:
parent
53db7c174c
commit
866a1e35a2
|
|
@ -0,0 +1,198 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"backend-service/pkg/client"
|
||||
"backend-service/pkg/machine"
|
||||
"backend-service/pkg/service"
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// isDaemon 检查是否以守护进程模式运行
|
||||
func isDaemon() bool {
|
||||
return len(os.Args) > 1 && os.Args[1] == constants.DaemonFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
logger.Debug("Initializing...")
|
||||
if isDaemon() {
|
||||
logger.Debug("Starting daemon...")
|
||||
runDaemon()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
logger.Error("Application failed: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// run 程序主逻辑
|
||||
func run() error {
|
||||
// 初始化配置
|
||||
if err := initConfig(); err != nil {
|
||||
return fmt.Errorf("init config: %w", err)
|
||||
}
|
||||
|
||||
// 采集并发送机器信息
|
||||
info, err := collectAndSendMachineInfo()
|
||||
if err != nil {
|
||||
return fmt.Errorf("collect and send machine info: %w", err)
|
||||
}
|
||||
|
||||
// 显示欢迎信息
|
||||
showWelcomeMessage(info)
|
||||
|
||||
// 检查并启动守护进程
|
||||
if err := handleDaemonProcess(); err != nil {
|
||||
return fmt.Errorf("handle daemon process: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// initConfig 初始化配置
|
||||
func initConfig() error {
|
||||
viper.AddConfigPath(constants.ConfigPath)
|
||||
return viper.ReadInConfig()
|
||||
}
|
||||
|
||||
// collectAndSendMachineInfo 采集并发送机器信息
|
||||
func collectAndSendMachineInfo() (*machine.Info, error) {
|
||||
info := machine.CollectMachineInfo()
|
||||
if err := client.SendMachineInfo(info); err != nil {
|
||||
return nil, fmt.Errorf("send machine info: %w", err)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// handleDaemonProcess 处理守护进程相关逻辑
|
||||
func handleDaemonProcess() error {
|
||||
// 获取可执行文件路径
|
||||
exePath, err := os.Executable()
|
||||
if err != nil {
|
||||
return fmt.Errorf("get executable path: %w", err)
|
||||
}
|
||||
logger.Debug("Exe path: %s", filepath.Dir(exePath))
|
||||
|
||||
// 检查现有进程
|
||||
if err := checkExistingProcess(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 启动新的守护进程
|
||||
return startDaemonProcess()
|
||||
}
|
||||
|
||||
// checkExistingProcess 检查是否已有守护进程在运行
|
||||
func checkExistingProcess() error {
|
||||
pidFile := constants.PidFilePath
|
||||
pidBytes, err := os.ReadFile(pidFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("read pid file: %w", err)
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(string(pidBytes))
|
||||
if err != nil {
|
||||
return fmt.Errorf("parse pid: %w", err)
|
||||
}
|
||||
|
||||
process, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("find process: %w", err)
|
||||
}
|
||||
|
||||
if err := process.Signal(syscall.Signal(0)); err == nil {
|
||||
logger.Info("Daemon already running with PID: %d", pid)
|
||||
return fmt.Errorf("daemon already running")
|
||||
}
|
||||
|
||||
// 进程不存在,删除PID文件
|
||||
if err := os.Remove(pidFile); err != nil {
|
||||
logger.Error("Failed to remove old PID file: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatGoTime(format string) string {
|
||||
replacer := strings.NewReplacer(
|
||||
"%Y", "2006",
|
||||
"%m", "01",
|
||||
"%d", "02",
|
||||
"%H", "15",
|
||||
"%M", "04",
|
||||
"%S", "05",
|
||||
)
|
||||
return replacer.Replace(format)
|
||||
}
|
||||
|
||||
// startDaemonProcess 启动守护进程
|
||||
func startDaemonProcess() error {
|
||||
// 确保日志目录存在
|
||||
if err := os.MkdirAll(constants.LogFilePath, constants.LogFileMode); err != nil {
|
||||
return fmt.Errorf("create logs directory: %w", err)
|
||||
}
|
||||
|
||||
// 将 strftime 风格格式转换为 Go 的时间格式
|
||||
goTimeFormat := formatGoTime(constants.LogNameFormate)
|
||||
logFileName := time.Now().Format(goTimeFormat)
|
||||
logFilePath := filepath.Join(constants.LogFilePath, logFileName)
|
||||
|
||||
logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, constants.LogFileMode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open log file: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(os.Args[0], constants.DaemonFlag)
|
||||
cmd.Stdout = logFile
|
||||
cmd.Stderr = logFile
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setsid: true,
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return fmt.Errorf("start daemon: %w", err)
|
||||
}
|
||||
|
||||
// 写入 PID 文件
|
||||
pidStr := []byte(fmt.Sprintf("%d", cmd.Process.Pid))
|
||||
if err := os.WriteFile(constants.PidFilePath, pidStr, constants.LogFileMode); err != nil {
|
||||
return fmt.Errorf("write pid file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// runDaemon 守护进程主逻辑
|
||||
func runDaemon() {
|
||||
logger.Info("Daemon started with PID: %d", os.Getpid())
|
||||
service.Run()
|
||||
}
|
||||
|
||||
// showWelcomeMessage 显示欢迎信息
|
||||
func showWelcomeMessage(info *machine.Info) {
|
||||
message := fmt.Sprintf(`%s
|
||||
╔══════════════════════════════════════╗
|
||||
║ Welcome to Bash Security Service ║
|
||||
║ Hostname: %-20s ║
|
||||
║ OS: %-32s ║
|
||||
╚══════════════════════════════════════╝%s`,
|
||||
constants.ColorGreen, info.Hostname, info.OS, constants.ColorReset)
|
||||
|
||||
fmt.Println(message)
|
||||
}
|
||||
|
|
@ -1,3 +1,21 @@
|
|||
module backend-service
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.12.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spf13/viper v1.20.1 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bash_go_service/shared/pkg/client"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
|
||||
"backend-service/pkg/machine"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var (
|
||||
apiEndpoint string // 从常量改为变量
|
||||
)
|
||||
|
||||
func init() {
|
||||
viper.SetDefault("machine_registry.endpoint", "none")
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Success bool `json:"success"` // 使用大写字段名,并添加json tag
|
||||
}
|
||||
|
||||
func SendMachineInfo(info *machine.Info) error {
|
||||
// 如果是none直接打一个log之后返回
|
||||
if viper.GetString("machine_registry.endpoint") == "none" {
|
||||
logger.InfoLogger.Printf("Machine info: %+v", info)
|
||||
return nil
|
||||
}
|
||||
var result Result
|
||||
client := client.NewClient()
|
||||
client.Post("/machine/info", info, nil, &result)
|
||||
|
||||
if !result.Success {
|
||||
panic("Failed to send machine info")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
package machine
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Info struct {
|
||||
Hostname string
|
||||
OS string
|
||||
Kernel string
|
||||
CPU string
|
||||
Memory string
|
||||
}
|
||||
|
||||
func CollectMachineInfo() *Info {
|
||||
return &Info{
|
||||
Hostname: getHostname(),
|
||||
OS: getOSInfo(),
|
||||
Kernel: getKernelVersion(),
|
||||
CPU: getCPUInfo(),
|
||||
Memory: getMemoryInfo(),
|
||||
}
|
||||
}
|
||||
|
||||
func getHostname() string {
|
||||
name, err := os.Hostname()
|
||||
if err != nil {
|
||||
return "unknown"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func getOSInfo() string {
|
||||
if runtime.GOOS == "linux" {
|
||||
out, err := exec.Command("lsb_release", "-d").Output()
|
||||
if err == nil {
|
||||
parts := strings.Split(string(out), ":")
|
||||
if len(parts) > 1 {
|
||||
return strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
// 尝试读取 /etc/os-release
|
||||
file, err := os.Open("/etc/os-release")
|
||||
if err == nil {
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "PRETTY_NAME=") {
|
||||
return strings.Trim(strings.TrimPrefix(line, "PRETTY_NAME="), "\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return runtime.GOOS
|
||||
}
|
||||
|
||||
func getKernelVersion() string {
|
||||
if runtime.GOOS == "linux" {
|
||||
out, err := exec.Command("uname", "-r").Output()
|
||||
if err == nil {
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func getCPUInfo() string {
|
||||
if runtime.GOOS == "linux" {
|
||||
out, err := exec.Command("lscpu").Output()
|
||||
if err == nil {
|
||||
return parseCPUInfo(string(out))
|
||||
}
|
||||
}
|
||||
return runtime.GOARCH
|
||||
}
|
||||
|
||||
func parseCPUInfo(output string) string {
|
||||
scanner := bufio.NewScanner(strings.NewReader(output))
|
||||
var model, cores string
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Contains(line, "Model name:") {
|
||||
model = strings.TrimSpace(strings.Split(line, ":")[1])
|
||||
}
|
||||
if strings.Contains(line, "CPU(s):") {
|
||||
cores = strings.TrimSpace(strings.Split(line, ":")[1])
|
||||
}
|
||||
}
|
||||
|
||||
if model != "" && cores != "" {
|
||||
return fmt.Sprintf("%s (%s cores)", model, cores)
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func getMemoryInfo() string {
|
||||
if runtime.GOOS == "linux" {
|
||||
file, err := os.Open("/proc/meminfo")
|
||||
if err == nil {
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
var totalMem, availMem string
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "MemTotal:") {
|
||||
totalMem = strings.TrimSpace(strings.TrimPrefix(line, "MemTotal:"))
|
||||
} else if strings.HasPrefix(line, "MemAvailable:") {
|
||||
availMem = strings.TrimSpace(strings.TrimPrefix(line, "MemAvailable:"))
|
||||
}
|
||||
|
||||
if totalMem != "" && availMem != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if totalMem != "" && availMem != "" {
|
||||
return fmt.Sprintf("Total: %s, Available: %s", totalMem, availMem)
|
||||
}
|
||||
}
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bash_go_service/config-loader/pkg/manager"
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
)
|
||||
|
||||
// ConfigManagerTask 配置管理器任务
|
||||
|
||||
type ConfigManagerTask struct {
|
||||
manager *manager.ConfigManager
|
||||
}
|
||||
|
||||
func NewConfigManagerTask() *ConfigManagerTask {
|
||||
return &ConfigManagerTask{
|
||||
manager: manager.NewConfigManager(constants.ConfigFile, 5*time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *ConfigManagerTask) Execute(ctx context.Context) {
|
||||
// 初始化配置管理器
|
||||
if err := t.manager.Initialize(); err != nil {
|
||||
logger.Error("Failed to initialize config manager: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 启动配置监控
|
||||
t.manager.StartWatching()
|
||||
|
||||
// 等待上下文取消
|
||||
<-ctx.Done()
|
||||
|
||||
// 停止配置管理器
|
||||
t.manager.Stop()
|
||||
|
||||
// 清理共享内存
|
||||
if err := t.manager.ClearSharedMemory(); err != nil {
|
||||
logger.Error("Failed to clear shared memory: %v", err)
|
||||
}
|
||||
|
||||
logger.Info("Config manager task stopped")
|
||||
}
|
||||
|
||||
func (t *ConfigManagerTask) Name() string {
|
||||
return "ConfigManagerTask"
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
lockFile = "/tmp/bash_service.lock"
|
||||
)
|
||||
|
||||
// Task 接口定义后台任务
|
||||
type Task interface {
|
||||
Execute(ctx context.Context)
|
||||
Name() string
|
||||
}
|
||||
|
||||
// WorkerPool 工作池结构体
|
||||
type WorkerPool struct {
|
||||
tasks []Task
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewWorkerPool 创建工作池
|
||||
func NewWorkerPool(tasks []Task) *WorkerPool {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &WorkerPool{
|
||||
tasks: tasks,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// Start 启动工作池中的所有任务
|
||||
func (wp *WorkerPool) Start() {
|
||||
for _, task := range wp.tasks {
|
||||
wp.wg.Add(1)
|
||||
go func(t Task) {
|
||||
defer wp.wg.Done()
|
||||
logger.Info("Starting task: %s", t.Name())
|
||||
t.Execute(wp.ctx)
|
||||
}(task)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop 停止所有任务
|
||||
func (wp *WorkerPool) Stop() {
|
||||
wp.cancel()
|
||||
wp.wg.Wait()
|
||||
}
|
||||
|
||||
// Service 服务结构体
|
||||
type Service struct {
|
||||
workerPool *WorkerPool
|
||||
}
|
||||
|
||||
// NewService 创建服务实例
|
||||
func NewService() *Service {
|
||||
tasks := []Task{
|
||||
NewConfigManagerTask(), // 添加配置管理器任务
|
||||
}
|
||||
|
||||
return &Service{
|
||||
workerPool: NewWorkerPool(tasks),
|
||||
}
|
||||
}
|
||||
|
||||
func CheckExistingInstance() bool {
|
||||
if data, err := os.ReadFile(lockFile); err == nil {
|
||||
existingPid := string(data)
|
||||
logger.Debug("Found existing instance with PID: %s", existingPid)
|
||||
return true
|
||||
}
|
||||
|
||||
pid := os.Getpid()
|
||||
os.WriteFile(lockFile, []byte(fmt.Sprintf("%d", pid)), 0644)
|
||||
logger.Debug("Created new lock file with PID: %d", pid)
|
||||
return false
|
||||
}
|
||||
|
||||
func Run() {
|
||||
service := NewService()
|
||||
|
||||
// 信号处理
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
// 启动所有任务
|
||||
service.workerPool.Start()
|
||||
|
||||
// 等待信号
|
||||
sig := <-sigChan
|
||||
logger.Info("Received signal: %v", sig)
|
||||
|
||||
// 停止所有任务
|
||||
service.workerPool.Stop()
|
||||
cleanup()
|
||||
}
|
||||
|
||||
func cleanup() {
|
||||
os.Remove(lockFile)
|
||||
}
|
||||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"bash_go_service/config-loader/internal/constants"
|
||||
"bash_go_service/config-loader/internal/manager"
|
||||
"bash_go_service/config-loader/pkg/manager"
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package models
|
||||
|
||||
import "bash_go_service/config-loader/internal/constants"
|
||||
import "bash_go_service/shared/pkg/constants"
|
||||
|
||||
// Rule 映射 C 结构体
|
||||
type Rule struct {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"bash_go_service/config-loader/internal/constants"
|
||||
"bash_go_service/config-loader/internal/models"
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"bash_go_service/config-loader/internal/constants"
|
||||
"bash_go_service/config-loader/internal/models"
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
machine_registry:
|
||||
endpoint: "http://localhost:9900"
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8=
|
||||
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
|
||||
cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY=
|
||||
cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU=
|
||||
cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
|
||||
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
|
||||
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ=
|
||||
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
|
||||
google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
[37m2025-04-11 20:19:02.230[0m [[34mDEBUG [0m] [1mlogger.go:64[0m | Initializing...
|
||||
[37m2025-04-11 20:19:02.230[0m [[34mDEBUG [0m] [1mlogger.go:64[0m | Starting daemon...
|
||||
[37m2025-04-11 20:19:02.230[0m [[32mINFO [0m] [1mlogger.go:60[0m | Daemon started with PID: 1759543
|
||||
[37m2025-04-11 20:19:02.231[0m [[32mINFO [0m] [1mlogger.go:60[0m | Starting task: ConfigManagerTask
|
||||
[37m2025-04-11 20:19:02.231[0m [[32mINFO [0m] [1mconfig_manager.go:40[0m | Initializing ConfigManager
|
||||
[37m2025-04-11 20:19:02.231[0m [[34mDEBUG [0m] [1mshm.go:84[0m | Starting to read configuration from shared memory
|
||||
[37m2025-04-11 20:19:02.233[0m [[32mINFO [0m] [1mshm.go:109[0m | Configuration successfully read from shared memory
|
||||
[37m2025-04-11 20:19:02.233[0m [[32mINFO [0m] [1mconfig_manager.go:45[0m | Loaded existing configuration from shared memory. Enabled: true, Rule Count: 8
|
||||
[37m2025-04-11 20:19:02.233[0m [[32mINFO [0m] [1mconfig_manager.go:65[0m | Started watching configuration file for changes
|
||||
[37m2025-04-11 20:19:07.236[0m [[32mINFO [0m] [1mconfig_manager.go:162[0m | Configuration file changed, reloading
|
||||
[37m2025-04-11 20:19:07.236[0m [[34mDEBUG [0m] [1mconfig_manager.go:107[0m | Loading configuration from file: ./config/execve_rules.json
|
||||
[37m2025-04-11 20:19:07.236[0m [[34mDEBUG [0m] [1mconfig_loader.go:13[0m | Loading config from file: ./config/execve_rules.json
|
||||
[37m2025-04-11 20:19:07.236[0m [[32mINFO [0m] [1mconfig_loader.go:55[0m | Configuration successfully loaded from file with skip rules added
|
||||
[37m2025-04-11 20:19:07.236[0m [[34mDEBUG [0m] [1mconfig_loader.go:60[0m | Converting JSON config to C config
|
||||
[37m2025-04-11 20:19:07.236[0m [[32mINFO [0m] [1mconfig_loader.go:86[0m | Successfully converted JSON config to C config
|
||||
[37m2025-04-11 20:19:07.236[0m [[34mDEBUG [0m] [1mshm.go:51[0m | Starting to write configuration to shared memory
|
||||
[37m2025-04-11 20:19:07.237[0m [[32mINFO [0m] [1mshm.go:78[0m | Configuration successfully written to shared memory
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
baseURL string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
type ClientOption func(*Client)
|
||||
|
||||
func WithBaseURL(baseURL string) ClientOption {
|
||||
return func(c *Client) {
|
||||
if baseURL != "" {
|
||||
c.baseURL = baseURL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(opts ...ClientOption) *Client {
|
||||
client := &Client{
|
||||
baseURL: constants.BaseUrl, // 默认使用环境变量
|
||||
client: &http.Client{
|
||||
Timeout: constants.ClientTimeout,
|
||||
},
|
||||
}
|
||||
|
||||
// 应用可选参数
|
||||
for _, opt := range opts {
|
||||
opt(client)
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *Client) Get(uri string, query map[string]string, result interface{}) error {
|
||||
// 构建URL
|
||||
u, err := url.Parse(c.baseURL)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to parse base URL: %v", err)
|
||||
return err
|
||||
}
|
||||
u.Path = path.Join(u.Path, uri)
|
||||
|
||||
// 添加query参数
|
||||
q := u.Query()
|
||||
for k, v := range query {
|
||||
q.Set(k, v)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
// 发送请求
|
||||
resp, err := c.client.Get(u.String())
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("GET request failed: %v", err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 读取响应
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to read response body: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析JSON
|
||||
if err := json.Unmarshal(body, result); err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to unmarshal response: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Post(uri string, body interface{}, query map[string]string, result interface{}) error {
|
||||
// 构建URL
|
||||
u, err := url.Parse(c.baseURL)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to parse base URL: %v", err)
|
||||
return err
|
||||
}
|
||||
u.Path = path.Join(u.Path, uri)
|
||||
|
||||
// 添加query参数(如果有)
|
||||
if query != nil {
|
||||
q := u.Query()
|
||||
for k, v := range query {
|
||||
q.Set(k, v)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
// 序列化请求体
|
||||
payload, err := json.Marshal(body)
|
||||
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to marshal request body: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
resp, err := c.client.Post(u.String(), "application/json", bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("POST request failed: %v", err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 读取响应
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
|
||||
logger.DebugLogger.Printf("Response body: %s", string(respBody))
|
||||
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to read response body: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析JSON
|
||||
if err := json.Unmarshal(respBody, result); err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to unmarshal response: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Put(uri string, body interface{}, query map[string]string, result interface{}) error {
|
||||
u, err := url.Parse(c.baseURL)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to parse base URL: %v", err)
|
||||
return err
|
||||
}
|
||||
u.Path = path.Join(u.Path, uri)
|
||||
|
||||
if query != nil {
|
||||
q := u.Query()
|
||||
for k, v := range query {
|
||||
q.Set(k, v)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to marshal request body: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPut, u.String(), bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to create PUT request: %v", err)
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("PUT request failed: %v", err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to read response body: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(respBody, result); err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to unmarshal response: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Delete(uri string, query map[string]string, result interface{}) error {
|
||||
u, err := url.Parse(c.baseURL)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to parse base URL: %v", err)
|
||||
return err
|
||||
}
|
||||
u.Path = path.Join(u.Path, uri)
|
||||
|
||||
if query != nil {
|
||||
q := u.Query()
|
||||
for k, v := range query {
|
||||
q.Set(k, v)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodDelete, u.String(), nil)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to create DELETE request: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("DELETE request failed: %v", err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to read response body: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(respBody, result); err != nil {
|
||||
logger.ErrorLogger.Printf("Failed to unmarshal response: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
ColorRed = "\033[31m"
|
||||
ColorGreen = "\033[32m"
|
||||
ColorYellow = "\033[33m"
|
||||
ColorBlue = "\033[34m"
|
||||
ColorPurple = "\033[35m"
|
||||
ColorCyan = "\033[36m"
|
||||
ColorGray = "\033[37m"
|
||||
ColorReset = "\033[0m"
|
||||
ColorBold = "\033[1m"
|
||||
)
|
||||
|
|
@ -10,4 +10,11 @@ const (
|
|||
ShmKey = 0x78945 // 共享内存的键值
|
||||
ShmSize = 512 * 1024 // 共享内存的大小(字节)
|
||||
ConfigFile = "./config/execve_rules.json" // 配置文件路径
|
||||
PidFilePath = "/tmp/bash_service.pid" // PID 文件路径
|
||||
DaemonFlag = "-daemon" // 后台进程标志
|
||||
ConfigFileMode = 0644 // 文件权限
|
||||
ConfigPath = "./config" // 配置文件路径
|
||||
LogFileMode = 0755 // 日志文件权限
|
||||
LogFilePath = "./logs" // 日志文件路径
|
||||
LogNameFormate = "%Y-%m-%d.log" // 日志文件名称格式
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package constants
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
BaseUrl = "http://localhost:9956"
|
||||
ClientTimeout = 30 * time.Second
|
||||
)
|
||||
|
|
@ -1,83 +1,73 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
const (
|
||||
colorRed = "\033[31m"
|
||||
colorGreen = "\033[32m"
|
||||
colorYellow = "\033[33m"
|
||||
colorBlue = "\033[34m"
|
||||
colorPurple = "\033[35m"
|
||||
colorCyan = "\033[36m"
|
||||
colorGray = "\033[37m"
|
||||
colorReset = "\033[0m"
|
||||
colorBold = "\033[1m"
|
||||
"bash_go_service/shared/pkg/constants"
|
||||
)
|
||||
|
||||
var (
|
||||
InfoLogger *log.Logger
|
||||
DebugLogger *log.Logger
|
||||
ErrorLogger *log.Logger
|
||||
WarningLogger *log.Logger
|
||||
InfoLogger *log.Logger
|
||||
DebugLogger *log.Logger
|
||||
ErrorLogger *log.Logger
|
||||
WarningLogger *log.Logger
|
||||
)
|
||||
|
||||
type LogWriter struct {
|
||||
prefix string
|
||||
color string
|
||||
prefix string
|
||||
color string
|
||||
}
|
||||
|
||||
func (w *LogWriter) Write(p []byte) (n int, err error) {
|
||||
// 获取调用信息
|
||||
_, file, line, ok := runtime.Caller(3) // 调整调用深度
|
||||
if !ok {
|
||||
file = "???"
|
||||
line = 0
|
||||
}
|
||||
|
||||
// 获取短文件名
|
||||
filename := filepath.Base(file)
|
||||
|
||||
// 当前时间
|
||||
now := time.Now().Format("2006-01-02 15:04:05.000")
|
||||
|
||||
// 构建日志前缀
|
||||
logPrefix := fmt.Sprintf("%s%s%s [%s%-7s%s] %s%s:%d%s | ",
|
||||
colorGray, now, colorReset,
|
||||
w.color, w.prefix, colorReset,
|
||||
colorBold, filename, line, colorReset,
|
||||
)
|
||||
|
||||
// 写入完整日志
|
||||
return os.Stdout.Write([]byte(logPrefix + string(p)))
|
||||
// 获取调用信息
|
||||
_, file, line, ok := runtime.Caller(3) // 调整调用深度
|
||||
if !ok {
|
||||
file = "???"
|
||||
line = 0
|
||||
}
|
||||
|
||||
// 获取短文件名
|
||||
filename := filepath.Base(file)
|
||||
|
||||
// 当前时间
|
||||
now := time.Now().Format("2006-01-02 15:04:05.000")
|
||||
|
||||
// 构建日志前缀
|
||||
logPrefix := fmt.Sprintf("%s%s%s [%s%-7s%s] %s%s:%d%s | ",
|
||||
constants.ColorGray, now, constants.ColorReset,
|
||||
w.color, w.prefix, constants.ColorReset,
|
||||
constants.ColorBold, filename, line, constants.ColorReset,
|
||||
)
|
||||
|
||||
// 写入完整日志
|
||||
return os.Stdout.Write([]byte(logPrefix + string(p)))
|
||||
}
|
||||
|
||||
func init() {
|
||||
InfoLogger = log.New(&LogWriter{prefix: "INFO", color: colorGreen}, "", 0)
|
||||
DebugLogger = log.New(&LogWriter{prefix: "DEBUG", color: colorBlue}, "", 0)
|
||||
ErrorLogger = log.New(&LogWriter{prefix: "ERROR", color: colorRed}, "", 0)
|
||||
WarningLogger = log.New(&LogWriter{prefix: "WARN", color: colorYellow}, "", 0)
|
||||
InfoLogger = log.New(&LogWriter{prefix: "INFO", color: constants.ColorGreen}, "", 0)
|
||||
DebugLogger = log.New(&LogWriter{prefix: "DEBUG", color: constants.ColorBlue}, "", 0)
|
||||
ErrorLogger = log.New(&LogWriter{prefix: "ERROR", color: constants.ColorRed}, "", 0)
|
||||
WarningLogger = log.New(&LogWriter{prefix: "WARN", color: constants.ColorYellow}, "", 0)
|
||||
}
|
||||
|
||||
// 辅助函数封装
|
||||
func Info(format string, v ...interface{}) {
|
||||
InfoLogger.Printf(format, v...)
|
||||
InfoLogger.Printf(format, v...)
|
||||
}
|
||||
|
||||
func Debug(format string, v ...interface{}) {
|
||||
DebugLogger.Printf(format, v...)
|
||||
DebugLogger.Printf(format, v...)
|
||||
}
|
||||
|
||||
func Error(format string, v ...interface{}) {
|
||||
ErrorLogger.Printf(format, v...)
|
||||
ErrorLogger.Printf(format, v...)
|
||||
}
|
||||
|
||||
func Warn(format string, v ...interface{}) {
|
||||
WarningLogger.Printf(format, v...)
|
||||
WarningLogger.Printf(format, v...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
module tests
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
bash_go_service/shared v0.0.0-00010101000000-000000000000
|
||||
golang.org/x/sys v0.15.0
|
||||
)
|
||||
|
||||
replace bash_go_service/shared => ../shared
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bash_go_service/shared/pkg/client"
|
||||
"bash_go_service/shared/pkg/logger"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
client := client.NewClient(client.WithBaseURL("http://localhost:9956"))
|
||||
|
||||
// GET请求
|
||||
var user User
|
||||
err := client.Get("/users/1", map[string]string{"fields": "id,name"}, &user)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// POST请求
|
||||
var newUser User
|
||||
err = client.Post("/users", User{Name: "John"}, nil, &newUser)
|
||||
|
||||
// 输出结果
|
||||
logger.InfoLogger.Printf("User: %+v", newUser)
|
||||
|
||||
// PUT请求
|
||||
var updatedUser User
|
||||
err = client.Put("/users/1", User{Name: "Jane"}, nil, &updatedUser)
|
||||
|
||||
// 输出结果
|
||||
logger.InfoLogger.Printf("Updated User: %+v", updatedUser)
|
||||
|
||||
// DELETE请求
|
||||
var deletedUser User
|
||||
err = client.Delete("/users/1", nil, &deletedUser)
|
||||
|
||||
// 输出结果
|
||||
logger.InfoLogger.Printf("Deleted User: %+v", deletedUser)
|
||||
}
|
||||
Loading…
Reference in New Issue