From cc33b9c94a0dd1eaca3114626a366e892e9fd955 Mon Sep 17 00:00:00 2001 From: "qcqcqc@wsl" <1220204124@zust.edu.cn> Date: Fri, 11 Apr 2025 23:58:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ewelcome=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=88=B0service=E4=B8=AD=EF=BC=8C?= =?UTF-8?q?=E8=A7=84=E8=8C=83=E6=97=A5=E5=BF=97=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-service/cmd/main.go | 8 + backend-service/go.mod | 6 + backend-service/pkg/client/client.go | 2 +- backend-service/pkg/service/service.go | 1 + backend-service/pkg/service/welcome.go | 56 +++++++ config-loader/cmd/manager/main.go | 10 +- config-loader/internal/shm/shm.go | 12 +- config-loader/internal/utils/config_loader.go | 16 +- config-loader/pkg/manager/config_manager.go | 22 +-- go.work | 3 + logs/2025-04-11.log | 40 +++++ shared/pkg/client/client.go | 42 +++--- shared/pkg/constants/colors.go | 3 + shared/pkg/constants/welcome.go | 5 + shared/pkg/logger/logger.go | 26 ++-- tests/testcase/http/http.go | 6 +- tests/testcase/userlogin/userlogin.go | 137 ++++++++++++++++++ welcome-service.log | 71 +++++++++ welcome/go.mod | 10 ++ welcome/service/service.go | 137 ++++++++++++++++++ 20 files changed, 545 insertions(+), 68 deletions(-) create mode 100644 backend-service/pkg/service/welcome.go create mode 100644 shared/pkg/constants/welcome.go create mode 100644 tests/testcase/userlogin/userlogin.go create mode 100644 welcome-service.log create mode 100644 welcome/go.mod create mode 100644 welcome/service/service.go diff --git a/backend-service/cmd/main.go b/backend-service/cmd/main.go index 95abfa9..bc8762e 100644 --- a/backend-service/cmd/main.go +++ b/backend-service/cmd/main.go @@ -28,11 +28,19 @@ func init() { logger.Debug("Initializing...") if isDaemon() { logger.Debug("Starting daemon...") + err := checkExistingProcess() + if err != nil { + logger.Error("Error starting daemon.") + return + } runDaemon() } } func main() { + if isDaemon() { + return + } if err := run(); err != nil { logger.Error("Application failed: %v", err) os.Exit(1) diff --git a/backend-service/go.mod b/backend-service/go.mod index 35354fb..6eeffd9 100644 --- a/backend-service/go.mod +++ b/backend-service/go.mod @@ -18,4 +18,10 @@ require ( golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + + bash_go_service/shared v0.0.0-00010101000000-000000000000 + bash_go_service/welcome v0.0.0-00010101000000-000000000000 ) + +replace bash_go_service/shared => ../shared +replace bash_go_service/welcome => ../welcome \ No newline at end of file diff --git a/backend-service/pkg/client/client.go b/backend-service/pkg/client/client.go index 24ee79f..4388553 100644 --- a/backend-service/pkg/client/client.go +++ b/backend-service/pkg/client/client.go @@ -24,7 +24,7 @@ type Result struct { func SendMachineInfo(info *machine.Info) error { // 如果是none直接打一个log之后返回 if viper.GetString("machine_registry.endpoint") == "none" { - logger.InfoLogger.Printf("Machine info: %+v", info) + logger.Info("Machine info: %+v", info) return nil } var result Result diff --git a/backend-service/pkg/service/service.go b/backend-service/pkg/service/service.go index 4dc1cea..7f4c95b 100644 --- a/backend-service/pkg/service/service.go +++ b/backend-service/pkg/service/service.go @@ -66,6 +66,7 @@ type Service struct { func NewService() *Service { tasks := []Task{ NewConfigManagerTask(), // 添加配置管理器任务 + NewWelcomeTask(), } return &Service{ diff --git a/backend-service/pkg/service/welcome.go b/backend-service/pkg/service/welcome.go new file mode 100644 index 0000000..89b7c5e --- /dev/null +++ b/backend-service/pkg/service/welcome.go @@ -0,0 +1,56 @@ +package service + +import ( + "context" + "os" + "os/signal" + "syscall" + + "bash_go_service/shared/pkg/logger" + "bash_go_service/welcome/service" +) + +// WelcomeTask 欢迎服务任务 +type WelcomeTask struct { + service *welcome.Service +} + +// NewWelcomeTask 创建欢迎服务任务实例 +func NewWelcomeTask() *WelcomeTask { + return &WelcomeTask{} +} + +// Execute 执行任务 +func (t *WelcomeTask) Execute(ctx context.Context) { + // 初始化logger + // 创建welcome service + service, err := welcome.NewService() + if err != nil { + logger.Error("Failed to create welcome service:", err) + return + } + t.service = service + defer t.service.Stop() + + // 启动服务 + if err := t.service.Start(); err != nil { + logger.Error("Failed to start welcome service:", err) + return + } + + // 等待上下文取消或中断信号 + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + select { + case <-ctx.Done(): + logger.Info("Context cancelled, shutting down welcome service...") + case sig := <-sigChan: + logger.Info("Received signal %v, shutting down welcome service...", sig) + } +} + +// Name 返回任务名称 +func (t *WelcomeTask) Name() string { + return "WelcomeTask" +} diff --git a/config-loader/cmd/manager/main.go b/config-loader/cmd/manager/main.go index 80c92c7..01be957 100644 --- a/config-loader/cmd/manager/main.go +++ b/config-loader/cmd/manager/main.go @@ -17,7 +17,7 @@ func main() { // Initialize the manager if err := configManager.Initialize(); err != nil { - logger.ErrorLogger.Printf("Failed to initialize config manager: %v", err) + logger.Error("Failed to initialize config manager: %v", err) os.Exit(1) } @@ -28,17 +28,17 @@ func main() { signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) - logger.InfoLogger.Println("Configuration manager started. Press Ctrl+C to exit.") + logger.Info("Configuration manager started. Press Ctrl+C to exit.") // Wait for shutdown signal <-signalChan - logger.InfoLogger.Println("Shutdown signal received") + logger.Info("Shutdown signal received") // Clean up configManager.Stop() if err := configManager.ClearSharedMemory(); err != nil { - logger.ErrorLogger.Printf("Failed to clear shared memory: %v", err) + logger.Error("Failed to clear shared memory: %v", err) } - logger.InfoLogger.Println("Configuration manager shutdown complete") + logger.Info("Configuration manager shutdown complete") } diff --git a/config-loader/internal/shm/shm.go b/config-loader/internal/shm/shm.go index 9a3507c..0cb8463 100644 --- a/config-loader/internal/shm/shm.go +++ b/config-loader/internal/shm/shm.go @@ -48,19 +48,19 @@ func shmdt(shmaddr unsafe.Pointer) error { // WriteConfigToSharedMemory 将配置数据写入共享内存 // config: 要写入的配置数据 func WriteConfigToSharedMemory(config *models.ConfigData) error { - logger.DebugLogger.Println("Starting to write configuration to shared memory") + logger.Debug("Starting to write configuration to shared memory") // 创建或获取共享内存段 shmID, err := shmget(constants.ShmKey, constants.ShmSize, unix.IPC_CREAT|0666) if err != nil { - logger.ErrorLogger.Printf("shmget failed: %v", err) + logger.Error("shmget failed: %v", err) return fmt.Errorf("shmget failed: %w", err) } // 将共享内存段附加到进程地址空间 shmPtr, err := shmat(shmID, 0, 0) if err != nil { - logger.ErrorLogger.Printf("shmat failed: %v", err) + logger.Error("shmat failed: %v", err) return fmt.Errorf("shmat failed: %w", err) } defer shmdt(shmPtr) // 确保在函数结束时分离共享内存 @@ -75,13 +75,13 @@ func WriteConfigToSharedMemory(config *models.ConfigData) error { data := (*[constants.ShmSize]byte)(unsafe.Pointer(config))[:] copy((*[constants.ShmSize]byte)(shmPtr)[:], data) - logger.InfoLogger.Println("Configuration successfully written to shared memory") + logger.Info("Configuration successfully written to shared memory") return nil } // ReadConfigFromSharedMemory 从共享内存读取配置数据 func ReadConfigFromSharedMemory() (*models.ConfigData, error) { - logger.DebugLogger.Println("Starting to read configuration from shared memory") + logger.Debug("Starting to read configuration from shared memory") // 获取共享内存段 shmID, err := shmget(constants.ShmKey, constants.ShmSize, 0) @@ -106,6 +106,6 @@ func ReadConfigFromSharedMemory() (*models.ConfigData, error) { // 从共享内存复制数据到配置对象 copy((*[constants.ShmSize]byte)(unsafe.Pointer(config))[:], (*[constants.ShmSize]byte)(shmPtr)[:]) - logger.InfoLogger.Println("Configuration successfully read from shared memory") + logger.Info("Configuration successfully read from shared memory") return config, nil } diff --git a/config-loader/internal/utils/config_loader.go b/config-loader/internal/utils/config_loader.go index e35883c..0c1a84a 100644 --- a/config-loader/internal/utils/config_loader.go +++ b/config-loader/internal/utils/config_loader.go @@ -10,18 +10,18 @@ import ( ) func LoadConfigFromFile(filename string) (*models.JSONConfig, error) { - logger.DebugLogger.Printf("Loading config from file: %s", filename) + logger.Debug("Loading config from file: %s", filename) data, err := os.ReadFile(filename) if err != nil { - logger.ErrorLogger.Printf("Failed to read config file: %v", err) + logger.Error("Failed to read config file: %v", err) return nil, err } var config models.JSONConfig err = json.Unmarshal(data, &config) if err != nil { - logger.ErrorLogger.Printf("Failed to unmarshal config: %v", err) + logger.Error("Failed to unmarshal config: %v", err) return nil, err } @@ -52,12 +52,12 @@ func LoadConfigFromFile(filename string) (*models.JSONConfig, error) { // 将规则添加到配置中 config.Rules = append(config.Rules, skipRules...) - logger.InfoLogger.Println("Configuration successfully loaded from file with skip rules added") + logger.Info("Configuration successfully loaded from file with skip rules added") return &config, nil } func ConvertToCConfig(jsonConfig *models.JSONConfig) *models.ConfigData { - logger.DebugLogger.Println("Converting JSON config to C config") + logger.Debug("Converting JSON config to C config") cConfig := &models.ConfigData{ Enabled: jsonConfig.Enabled, @@ -66,7 +66,7 @@ func ConvertToCConfig(jsonConfig *models.JSONConfig) *models.ConfigData { for i, rule := range jsonConfig.Rules { if i >= constants.MaxRules { - logger.WarningLogger.Printf("Exceeded maximum rules limit (%d)", constants.MaxRules) + logger.Warn("Exceeded maximum rules limit (%d)", constants.MaxRules) break } copy(cConfig.Rules[i].Cmd[:], rule.Cmd) @@ -76,13 +76,13 @@ func ConvertToCConfig(jsonConfig *models.JSONConfig) *models.ConfigData { for j, arg := range rule.Args { if j >= constants.MaxArgs { - logger.WarningLogger.Printf("Exceeded maximum arguments limit (%d) for rule %d", constants.MaxArgs, i) + logger.Warn("Exceeded maximum arguments limit (%d) for rule %d", constants.MaxArgs, i) break } copy(cConfig.Rules[i].Args[j][:], arg) } } - logger.InfoLogger.Println("Successfully converted JSON config to C config") + logger.Info("Successfully converted JSON config to C config") return cConfig } diff --git a/config-loader/pkg/manager/config_manager.go b/config-loader/pkg/manager/config_manager.go index 16908b0..8e23238 100644 --- a/config-loader/pkg/manager/config_manager.go +++ b/config-loader/pkg/manager/config_manager.go @@ -37,18 +37,18 @@ func NewConfigManager(configFile string, watchInterval time.Duration) *ConfigMan // Initialize 加载初始配置并开始监控配置文件的变化 func (cm *ConfigManager) Initialize() error { - logger.InfoLogger.Println("Initializing ConfigManager") + logger.Info("Initializing ConfigManager") // 尝试从共享内存中读取现有配置 if config, err := shm.ReadConfigFromSharedMemory(); err == nil { cm.currentConfig = config - logger.InfoLogger.Printf("Loaded existing configuration from shared memory. Enabled: %v, Rule Count: %d", + logger.Info("Loaded existing configuration from shared memory. Enabled: %v, Rule Count: %d", config.Enabled, config.RuleCount) if config.RuleCount == 0 { cm.ForceSync() // 如果规则数量为 0,强制同步配置 } } else { - logger.WarningLogger.Printf("Failed to read from shared memory: %v", err) + logger.Warn("Failed to read from shared memory: %v", err) // 如果从共享内存读取失败,则从文件加载 if err := cm.syncFromFile(); err != nil { return fmt.Errorf("initial configuration load failed: %w", err) @@ -62,12 +62,12 @@ func (cm *ConfigManager) Initialize() error { func (cm *ConfigManager) StartWatching() { cm.wg.Add(1) go cm.watchConfigFile() - logger.InfoLogger.Println("Started watching configuration file for changes") + logger.Info("Started watching configuration file for changes") } // Stop 优雅地停止配置管理器 func (cm *ConfigManager) Stop() { - logger.InfoLogger.Println("Stopping ConfigManager") + logger.Info("Stopping ConfigManager") close(cm.stopChan) cm.wg.Wait() } @@ -81,13 +81,13 @@ func (cm *ConfigManager) GetCurrentConfig() *models.ConfigData { // ForceSync 强制从文件重新加载配置 func (cm *ConfigManager) ForceSync() error { - logger.InfoLogger.Println("Force syncing configuration from file") + logger.Info("Force syncing configuration from file") return cm.syncFromFile() } // ClearSharedMemory 清除共享内存中的配置 func (cm *ConfigManager) ClearSharedMemory() error { - logger.InfoLogger.Println("Clearing shared memory configuration") + logger.Info("Clearing shared memory configuration") // 这里可以实现实际的清除逻辑 // 当前仅写入一个空配置 emptyConfig := &models.ConfigData{ @@ -104,7 +104,7 @@ func (cm *ConfigManager) syncFromFile() error { cm.mu.Lock() defer cm.mu.Unlock() - logger.DebugLogger.Printf("Loading configuration from file: %s", cm.configFile) + logger.Debug("Loading configuration from file: %s", cm.configFile) // 从文件加载 JSON 配置 jsonConfig, err := utils.LoadConfigFromFile(cm.configFile) @@ -136,11 +136,11 @@ func (cm *ConfigManager) watchConfigFile() { for { select { case <-cm.stopChan: - logger.InfoLogger.Println("Stopping configuration file watcher") + logger.Info("Stopping configuration file watcher") return case <-ticker.C: if err := cm.checkAndReloadConfig(); err != nil { - logger.ErrorLogger.Printf("Error checking/reloading config: %v", err) + logger.Error("Error checking/reloading config: %v", err) } } } @@ -159,7 +159,7 @@ func (cm *ConfigManager) checkAndReloadConfig() error { // 如果文件修改时间更新,则重新加载配置 if fileInfo.ModTime().After(lastMod) { - logger.InfoLogger.Println("Configuration file changed, reloading") + logger.Info("Configuration file changed, reloading") return cm.syncFromFile() } diff --git a/go.work b/go.work index 9dc7c10..84c81c4 100644 --- a/go.work +++ b/go.work @@ -3,4 +3,7 @@ go 1.24.2 use ( ./backend-service ./config-loader + ./shared + ./tests + ./welcome ) diff --git a/logs/2025-04-11.log b/logs/2025-04-11.log index abeb4bf..bf445c5 100755 --- a/logs/2025-04-11.log +++ b/logs/2025-04-11.log @@ -15,3 +15,43 @@ 2025-04-11 20:19:07.236 [INFO ] config_loader.go:86 | Successfully converted JSON config to C config 2025-04-11 20:19:07.236 [DEBUG ] shm.go:51 | Starting to write configuration to shared memory 2025-04-11 20:19:07.237 [INFO ] shm.go:78 | Configuration successfully written to shared memory +2025-04-11 23:48:43.186 [DEBUG ] logger.go:64 | Initializing... +2025-04-11 23:48:43.186 [DEBUG ] logger.go:64 | Starting daemon... +2025-04-11 23:48:43.186 [INFO ] logger.go:60 | Daemon started with PID: 1837284 +2025-04-11 23:48:43.186 [INFO ] logger.go:60 | Starting task: WelcomeTask +2025-04-11 23:48:43.186 [INFO ] logger.go:60 | Starting task: ConfigManagerTask +2025-04-11 23:48:43.186 [INFO ] config_manager.go:40 | Initializing ConfigManager +2025-04-11 23:48:43.186 [DEBUG ] shm.go:84 | Starting to read configuration from shared memory +2025-04-11 23:48:43.186 [INFO ] logger.go:60 | Service started +2025-04-11 23:48:43.188 [INFO ] shm.go:109 | Configuration successfully read from shared memory +2025-04-11 23:48:43.188 [INFO ] config_manager.go:45 | Loaded existing configuration from shared memory. Enabled: true, Rule Count: 8 +2025-04-11 23:48:43.188 [INFO ] config_manager.go:65 | Started watching configuration file for changes +2025-04-11 23:48:44.187 [ERROR ] logger.go:68 | Error opening terminal /dev/pts/ptmx: open /dev/pts/ptmx: permission denied +2025-04-11 23:48:44.187 [INFO ] service.go:136 | Welcome message sent to /dev/pts/19 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/6 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/0 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/3 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/7 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/12 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/1 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/8 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/13 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/9 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/2 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/20 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/10 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/21 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/14 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/11 +2025-04-11 23:48:44.188 [INFO ] service.go:136 | Welcome message sent to /dev/pts/15 +2025-04-11 23:48:48.191 [INFO ] config_manager.go:162 | Configuration file changed, reloading +2025-04-11 23:48:48.191 [DEBUG ] config_manager.go:107 | Loading configuration from file: ./config/execve_rules.json +2025-04-11 23:48:48.191 [DEBUG ] config_loader.go:13 | Loading config from file: ./config/execve_rules.json +2025-04-11 23:48:48.191 [INFO ] config_loader.go:55 | Configuration successfully loaded from file with skip rules added +2025-04-11 23:48:48.191 [DEBUG ] config_loader.go:60 | Converting JSON config to C config +2025-04-11 23:48:48.192 [INFO ] config_loader.go:86 | Successfully converted JSON config to C config +2025-04-11 23:48:48.192 [DEBUG ] shm.go:51 | Starting to write configuration to shared memory +2025-04-11 23:48:48.192 [INFO ] shm.go:78 | Configuration successfully written to shared memory +2025-04-11 23:48:49.431 [INFO ] service.go:136 | Welcome message sent to /dev/pts/4 +2025-04-11 23:48:52.535 [INFO ] service.go:136 | Welcome message sent to /dev/pts/5 +2025-04-11 23:49:36.800 [INFO ] service.go:136 | Welcome message sent to /dev/pts/18 diff --git a/shared/pkg/client/client.go b/shared/pkg/client/client.go index c9a2c1e..7ac9db4 100644 --- a/shared/pkg/client/client.go +++ b/shared/pkg/client/client.go @@ -47,7 +47,7 @@ func (c *Client) Get(uri string, query map[string]string, result interface{}) er // 构建URL u, err := url.Parse(c.baseURL) if err != nil { - logger.ErrorLogger.Printf("Failed to parse base URL: %v", err) + logger.Error("Failed to parse base URL: %v", err) return err } u.Path = path.Join(u.Path, uri) @@ -62,7 +62,7 @@ func (c *Client) Get(uri string, query map[string]string, result interface{}) er // 发送请求 resp, err := c.client.Get(u.String()) if err != nil { - logger.ErrorLogger.Printf("GET request failed: %v", err) + logger.Error("GET request failed: %v", err) return err } defer resp.Body.Close() @@ -70,13 +70,13 @@ func (c *Client) Get(uri string, query map[string]string, result interface{}) er // 读取响应 body, err := io.ReadAll(resp.Body) if err != nil { - logger.ErrorLogger.Printf("Failed to read response body: %v", err) + logger.Error("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) + logger.Error("Failed to unmarshal response: %v", err) return err } @@ -87,7 +87,7 @@ func (c *Client) Post(uri string, body interface{}, query map[string]string, res // 构建URL u, err := url.Parse(c.baseURL) if err != nil { - logger.ErrorLogger.Printf("Failed to parse base URL: %v", err) + logger.Error("Failed to parse base URL: %v", err) return err } u.Path = path.Join(u.Path, uri) @@ -105,14 +105,14 @@ func (c *Client) Post(uri string, body interface{}, query map[string]string, res payload, err := json.Marshal(body) if err != nil { - logger.ErrorLogger.Printf("Failed to marshal request body: %v", err) + logger.Error("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) + logger.Error("POST request failed: %v", err) return err } defer resp.Body.Close() @@ -120,16 +120,16 @@ func (c *Client) Post(uri string, body interface{}, query map[string]string, res // 读取响应 respBody, err := io.ReadAll(resp.Body) - logger.DebugLogger.Printf("Response body: %s", string(respBody)) + logger.Debug("Response body: %s", string(respBody)) if err != nil { - logger.ErrorLogger.Printf("Failed to read response body: %v", err) + logger.Error("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) + logger.Error("Failed to unmarshal response: %v", err) return err } @@ -139,7 +139,7 @@ func (c *Client) Post(uri string, body interface{}, query map[string]string, res 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) + logger.Error("Failed to parse base URL: %v", err) return err } u.Path = path.Join(u.Path, uri) @@ -154,32 +154,32 @@ func (c *Client) Put(uri string, body interface{}, query map[string]string, resu payload, err := json.Marshal(body) if err != nil { - logger.ErrorLogger.Printf("Failed to marshal request body: %v", err) + logger.Error("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) + logger.Error("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) + logger.Error("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) + logger.Error("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) + logger.Error("Failed to unmarshal response: %v", err) return err } @@ -189,7 +189,7 @@ func (c *Client) Put(uri string, body interface{}, query map[string]string, resu 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) + logger.Error("Failed to parse base URL: %v", err) return err } u.Path = path.Join(u.Path, uri) @@ -204,25 +204,25 @@ func (c *Client) Delete(uri string, query map[string]string, result interface{}) req, err := http.NewRequest(http.MethodDelete, u.String(), nil) if err != nil { - logger.ErrorLogger.Printf("Failed to create DELETE request: %v", err) + logger.Error("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) + logger.Error("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) + logger.Error("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) + logger.Error("Failed to unmarshal response: %v", err) return err } diff --git a/shared/pkg/constants/colors.go b/shared/pkg/constants/colors.go index c0af954..304df7d 100644 --- a/shared/pkg/constants/colors.go +++ b/shared/pkg/constants/colors.go @@ -10,4 +10,7 @@ const ( ColorGray = "\033[37m" ColorReset = "\033[0m" ColorBold = "\033[1m" + // 样式 + Bold = "\033[1m" + Underline = "\033[4m" ) diff --git a/shared/pkg/constants/welcome.go b/shared/pkg/constants/welcome.go new file mode 100644 index 0000000..86e968d --- /dev/null +++ b/shared/pkg/constants/welcome.go @@ -0,0 +1,5 @@ +package constants + +const ( + UtmpDir = "/dev/pts/" +) diff --git a/shared/pkg/logger/logger.go b/shared/pkg/logger/logger.go index d1e0330..d200d8f 100644 --- a/shared/pkg/logger/logger.go +++ b/shared/pkg/logger/logger.go @@ -12,10 +12,10 @@ import ( ) 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 { @@ -25,7 +25,7 @@ type LogWriter struct { func (w *LogWriter) Write(p []byte) (n int, err error) { // 获取调用信息 - _, file, line, ok := runtime.Caller(3) // 调整调用深度 + _, file, line, ok := runtime.Caller(4) // 调整调用深度 if !ok { file = "???" line = 0 @@ -49,25 +49,25 @@ func (w *LogWriter) Write(p []byte) (n int, err error) { } func init() { - 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) + 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...) } diff --git a/tests/testcase/http/http.go b/tests/testcase/http/http.go index 1cdc8a5..4bdf8bc 100644 --- a/tests/testcase/http/http.go +++ b/tests/testcase/http/http.go @@ -26,19 +26,19 @@ func main() { err = client.Post("/users", User{Name: "John"}, nil, &newUser) // 输出结果 - logger.InfoLogger.Printf("User: %+v", newUser) + logger.Info("User: %+v", newUser) // PUT请求 var updatedUser User err = client.Put("/users/1", User{Name: "Jane"}, nil, &updatedUser) // 输出结果 - logger.InfoLogger.Printf("Updated User: %+v", updatedUser) + logger.Info("Updated User: %+v", updatedUser) // DELETE请求 var deletedUser User err = client.Delete("/users/1", nil, &deletedUser) // 输出结果 - logger.InfoLogger.Printf("Deleted User: %+v", deletedUser) + logger.Info("Deleted User: %+v", deletedUser) } diff --git a/tests/testcase/userlogin/userlogin.go b/tests/testcase/userlogin/userlogin.go new file mode 100644 index 0000000..5d41912 --- /dev/null +++ b/tests/testcase/userlogin/userlogin.go @@ -0,0 +1,137 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/signal" + "path/filepath" + "syscall" + "time" + + "github.com/fsnotify/fsnotify" +) + +const ( + utmpDir = "/dev/pts/" + + // ANSI转义序列定义颜色 + colorReset = "\033[0m" + colorRed = "\033[31m" + colorGreen = "\033[32m" + colorYellow = "\033[33m" + colorBlue = "\033[34m" + colorPurple = "\033[35m" + colorCyan = "\033[36m" + colorWhite = "\033[37m" + + // 样式 + bold = "\033[1m" + underline = "\033[4m" +) + +func main() { + logFile, err := os.OpenFile("./welcome-service.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + log.Fatal(err) + } + defer logFile.Close() + log.SetOutput(logFile) + + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + err = watcher.Add(utmpDir) + if err != nil { + log.Fatal(err) + } + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + checkExistingTerminals() + + log.Println("Service started") + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + if event.Op&fsnotify.Create == fsnotify.Create { + go handleNewTerminal(event.Name) + } + + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Printf("Watcher error: %v", err) + + case sig := <-sigChan: + log.Printf("Received signal: %v", sig) + return + } + } +} + +func checkExistingTerminals() { + entries, err := os.ReadDir(utmpDir) + if err != nil { + log.Printf("Error reading %s: %v", utmpDir, err) + return + } + + for _, entry := range entries { + if !entry.IsDir() { + go handleNewTerminal(filepath.Join(utmpDir, entry.Name())) + } + } +} + +func handleNewTerminal(path string) { + time.Sleep(time.Second) + + f, err := os.OpenFile(path, os.O_WRONLY, 0) + if err != nil { + log.Printf("Error opening terminal %s: %v", path, err) + return + } + defer f.Close() + + // 使用颜色和样式的欢迎信息 + welcomeMsg := fmt.Sprintf(` +%s%s╔════════════════════════════════════════════╗%s +%s%s║ Welcome to the System! ║%s +%s%s║---------------------------------------- ║%s +%s%s║ Terminal: %s%s%-30s%s ║%s +%s%s║ Time: %s%s%-35s%s ║%s +%s%s╚════════════════════════════════════════════╝%s +`, + bold, colorCyan, colorReset, + bold, colorCyan, colorReset, + bold, colorCyan, colorReset, + bold, colorCyan, colorGreen, underline, path, colorCyan, colorReset, + bold, colorCyan, colorYellow, underline, time.Now().Format("2006-01-02 15:04:05"), colorCyan, colorReset, + bold, colorCyan, colorReset, + ) + + // 写入欢迎信息 + _, err = f.WriteString(welcomeMsg) + if err != nil { + log.Printf("Error writing to terminal %s: %v", path, err) + return + } + + // 模拟按下回车键 + _, err = f.Write([]byte{'\n'}) + if err != nil { + log.Printf("Error sending newline to terminal %s: %v", path, err) + return + } + + log.Printf("Welcome message sent to %s", path) +} diff --git a/welcome-service.log b/welcome-service.log new file mode 100644 index 0000000..ffe244a --- /dev/null +++ b/welcome-service.log @@ -0,0 +1,71 @@ +2025/04/11 23:18:24 Service started +2025/04/11 23:18:25 Error opening terminal /dev/pts/ptmx: open /dev/pts/ptmx: permission denied +2025/04/11 23:18:25 Welcome message sent to /dev/pts/20 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/19 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/6 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/7 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/9 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/18 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/2 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/14 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/13 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/3 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/1 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/11 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/15 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/21 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/10 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/12 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/8 +2025/04/11 23:18:25 Welcome message sent to /dev/pts/0 +2025/04/11 23:18:28 Welcome message sent to /dev/pts/4 +2025/04/11 23:18:34 Welcome message sent to /dev/pts/5 +2025/04/11 23:19:45 Welcome message sent to /dev/pts/22 +2025/04/11 23:20:00 Welcome message sent to /dev/pts/5 +2025/04/11 23:24:13 Received signal: interrupt +2025/04/11 23:24:14 Service started +2025/04/11 23:24:15 Error opening terminal /dev/pts/ptmx: open /dev/pts/ptmx: permission denied +2025/04/11 23:24:15 Welcome message sent to /dev/pts/9 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/15 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/19 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/0 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/3 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/7 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/6 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/1 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/10 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/8 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/21 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/18 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/11 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/4 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/2 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/13 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/12 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/20 +2025/04/11 23:24:15 Welcome message sent to /dev/pts/14 +2025/04/11 23:24:24 Welcome message sent to /dev/pts/5 +2025/04/11 23:25:50 Received signal: interrupt +2025/04/11 23:25:51 Service started +2025/04/11 23:25:52 Welcome message sent to /dev/pts/11 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/18 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/4 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/10 +2025/04/11 23:25:52 Error opening terminal /dev/pts/ptmx: open /dev/pts/ptmx: permission denied +2025/04/11 23:25:52 Welcome message sent to /dev/pts/15 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/6 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/2 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/1 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/7 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/5 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/0 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/8 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/20 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/21 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/3 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/19 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/9 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/14 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/12 +2025/04/11 23:25:52 Welcome message sent to /dev/pts/13 +2025/04/11 23:28:16 Received signal: interrupt diff --git a/welcome/go.mod b/welcome/go.mod new file mode 100644 index 0000000..bb890e0 --- /dev/null +++ b/welcome/go.mod @@ -0,0 +1,10 @@ +module welcome + +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 \ No newline at end of file diff --git a/welcome/service/service.go b/welcome/service/service.go new file mode 100644 index 0000000..b10b67d --- /dev/null +++ b/welcome/service/service.go @@ -0,0 +1,137 @@ +package welcome + +import ( + "fmt" + "os" + "os/signal" + "path/filepath" + "syscall" + "time" + + "bash_go_service/shared/pkg/constants" + "bash_go_service/shared/pkg/logger" + + "github.com/fsnotify/fsnotify" +) + +type Service struct { + watcher *fsnotify.Watcher + sigChan chan os.Signal + stopChan chan struct{} +} + +func NewService() (*Service, error) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return nil, err + } + + return &Service{ + watcher: watcher, + sigChan: make(chan os.Signal, 1), + stopChan: make(chan struct{}), + }, nil +} + +func (s *Service) checkExistingTerminals() { + entries, err := os.ReadDir(constants.UtmpDir) + if err != nil { + logger.Error("Error reading %s: %v", constants.UtmpDir, err) + return + } + + for _, entry := range entries { + if !entry.IsDir() { + go s.handleNewTerminal(filepath.Join(constants.UtmpDir, entry.Name())) + } + } +} + +func (s *Service) Start() error { + err := s.watcher.Add(constants.UtmpDir) + if err != nil { + return err + } + + signal.Notify(s.sigChan, syscall.SIGINT, syscall.SIGTERM) + + s.checkExistingTerminals() + + logger.Info("Service started") + + go s.watch() + + return nil +} + +func (s *Service) Stop() { + close(s.stopChan) + s.watcher.Close() + signal.Stop(s.sigChan) +} + +func (s *Service) watch() { + for { + select { + case event, ok := <-s.watcher.Events: + if !ok { + return + } + if event.Op&fsnotify.Create == fsnotify.Create { + go s.handleNewTerminal(event.Name) + } + + case err, ok := <-s.watcher.Errors: + if !ok { + return + } + logger.Error("Watcher error: %v", err) + + case sig := <-s.sigChan: + logger.Debug("Received signal: %v", sig) + return + + case <-s.stopChan: + return + } + } +} + +func (s *Service) handleNewTerminal(path string) { + time.Sleep(time.Second) + + f, err := os.OpenFile(path, os.O_WRONLY, 0) + if err != nil { + logger.Error("Error opening terminal %s: %v", path, err) + return + } + defer f.Close() + + welcomeMsg := fmt.Sprintf(` +%s%s╔════════════════════════════════════════════╗%s +%s%s║ Welcome to the System! ║%s +%s%s║---------------------------------------- ║%s +%s%s║ Terminal: %s%s%-30s%s ║%s +%s%s║ Time: %s%s%-35s%s ║%s +%s%s╚════════════════════════════════════════════╝%s +`, + constants.Bold, constants.ColorCyan, constants.ColorReset, + constants.Bold, constants.ColorCyan, constants.ColorReset, + constants.Bold, constants.ColorCyan, constants.ColorReset, + constants.Bold, constants.ColorCyan, constants.ColorGreen, constants.Underline, path, constants.ColorCyan, constants.ColorReset, + constants.Bold, constants.ColorCyan, constants.ColorYellow, constants.Underline, time.Now().Format("2006-01-02 15:04:05"), constants.ColorCyan, constants.ColorReset, + constants.Bold, constants.ColorCyan, constants.ColorReset, + ) + + if _, err = f.WriteString(welcomeMsg); err != nil { + logger.Error("Error writing to terminal %s: %v", path, err) + return + } + + if _, err = f.Write([]byte{'\n'}); err != nil { + logger.Error("Error sending newline to terminal %s: %v", path, err) + return + } + + logger.Info("Welcome message sent to %s", path) +}