From 6ac80d211a2ba80e4212283f1e412be346b5bda6 Mon Sep 17 00:00:00 2001 From: Snider Date: Sun, 9 Nov 2025 03:10:55 +0000 Subject: [PATCH] Add logOutput field to control stdout/stderr logging and update miner management --- cmd/mining/cmd/serve.go | 86 ++++++++++++++++++++++++++++++++++++++--- docs/docs.go | 4 ++ docs/swagger.json | 4 ++ docs/swagger.yaml | 3 ++ pkg/mining/manager.go | 16 +++++--- pkg/mining/mining.go | 3 +- pkg/mining/xmrig.go | 16 ++++++-- 7 files changed, 116 insertions(+), 16 deletions(-) diff --git a/cmd/mining/cmd/serve.go b/cmd/mining/cmd/serve.go index 232d927..44a8972 100644 --- a/cmd/mining/cmd/serve.go +++ b/cmd/mining/cmd/serve.go @@ -40,8 +40,10 @@ var serveCmd = &cobra.Command{ displayAddr := fmt.Sprintf("%s:%d", displayHost, port) listenAddr := fmt.Sprintf("%s:%d", host, port) - manager := mining.NewManager() - service := mining.NewService(manager, listenAddr, displayAddr, namespace) + // Use the global manager instance + mgr := getManager() // This ensures we get the manager initialized by initManager + + service := mining.NewService(mgr, listenAddr, displayAddr, namespace) // Pass the global manager // Start the server in a goroutine go func() { @@ -75,11 +77,83 @@ var serveCmd = &cobra.Command{ return } - rootCmd.SetArgs(strings.Fields(line)) - if err := rootCmd.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) + parts := strings.Fields(line) + if len(parts) == 0 { + fmt.Print(">> ") + continue + } + + command := strings.ToLower(parts[0]) + cmdArgs := parts[1:] + + switch command { + case "start": + if len(cmdArgs) < 1 { + fmt.Println("Error: start command requires miner type (e.g., 'start xmrig')") + } else { + minerType := cmdArgs[0] + // Use default pool and wallet for interactive shell for simplicity + config := &mining.Config{ + Pool: "pool.hashvault.pro:443", + Wallet: "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", // Corrected wallet address + LogOutput: true, // Enable logging for interactive shell + // Add other default config values if necessary + } + miner, err := mgr.StartMiner(minerType, config) + if err != nil { + fmt.Fprintf(os.Stderr, "Error starting miner: %v\n", err) + } else { + fmt.Printf("Miner %s started successfully.\n", miner.GetName()) + } + } + case "status": + if len(cmdArgs) < 1 { + fmt.Println("Error: status command requires miner name (e.g., 'status xmrig')") + } else { + minerName := cmdArgs[0] + miner, err := mgr.GetMiner(minerName) + if err != nil { + fmt.Fprintf(os.Stderr, "Error getting miner status: %v\n", err) + } else { + stats, err := miner.GetStats() + if err != nil { + fmt.Fprintf(os.Stderr, "Error getting miner stats: %v\n", err) + } else { + fmt.Printf("Miner Status for %s:\n", strings.Title(minerName)) + fmt.Printf(" Hash Rate: %d H/s\n", stats.Hashrate) + fmt.Printf(" Shares: %d\n", stats.Shares) + fmt.Printf(" Rejected: %d\n", stats.Rejected) + fmt.Printf(" Uptime: %d seconds\n", stats.Uptime) + fmt.Printf(" Algorithm: %s\n", stats.Algorithm) + } + } + } + case "stop": + if len(cmdArgs) < 1 { + fmt.Println("Error: stop command requires miner name (e.g., 'stop xmrig')") + } else { + minerName := cmdArgs[0] + err := mgr.StopMiner(minerName) + if err != nil { + fmt.Fprintf(os.Stderr, "Error stopping miner: %v\n", err) + } else { + fmt.Printf("Miner %s stopped successfully.\n", minerName) + } + } + case "list": + miners := mgr.ListMiners() + if len(miners) == 0 { + fmt.Println("No miners currently running.") + } else { + fmt.Println("Running Miners:") + for _, miner := range miners { + fmt.Printf(" - %s\n", miner.GetName()) + } + } + default: + fmt.Fprintf(os.Stderr, "Unknown command: %s. Only 'start', 'status', 'stop', 'list' are directly supported in this shell.\n", command) + fmt.Fprintf(os.Stderr, "For other commands, please run them directly from your terminal (e.g., 'miner-cli doctor').\n") } - rootCmd.SetArgs([]string{}) fmt.Print(">> ") } }() diff --git a/docs/docs.go b/docs/docs.go index 564114c..4ca1eaf 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -416,6 +416,10 @@ const docTemplate = `{ "logFile": { "type": "string" }, + "logOutput": { + "description": "New field to control stdout/stderr logging", + "type": "boolean" + }, "miner": { "type": "string" }, diff --git a/docs/swagger.json b/docs/swagger.json index a2129f2..fbea780 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -410,6 +410,10 @@ "logFile": { "type": "string" }, + "logOutput": { + "description": "New field to control stdout/stderr logging", + "type": "boolean" + }, "miner": { "type": "string" }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index f61a47e..ff3a3f6 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -75,6 +75,9 @@ definitions: type: boolean logFile: type: string + logOutput: + description: New field to control stdout/stderr logging + type: boolean miner: type: string nicehash: diff --git a/pkg/mining/manager.go b/pkg/mining/manager.go index 9d33e52..12c3607 100644 --- a/pkg/mining/manager.go +++ b/pkg/mining/manager.go @@ -27,21 +27,24 @@ func (m *Manager) StartMiner(minerType string, config *Config) (Miner, error) { return nil, fmt.Errorf("unsupported miner type: %s", minerType) } - if _, exists := m.miners[miner.GetName()]; exists { - return nil, fmt.Errorf("miner already started: %s", miner.GetName()) + // Ensure the miner's internal name is used for map key + minerKey := miner.GetName() + if _, exists := m.miners[minerKey]; exists { + return nil, fmt.Errorf("miner already started: %s", minerKey) } if err := miner.Start(config); err != nil { return nil, err } - m.miners[miner.GetName()] = miner + m.miners[minerKey] = miner return miner, nil } // StopMiner stops a running miner func (m *Manager) StopMiner(name string) error { - miner, exists := m.miners[name] + minerKey := strings.ToLower(name) // Normalize input name to lowercase + miner, exists := m.miners[minerKey] if !exists { return fmt.Errorf("miner not found: %s", name) } @@ -50,13 +53,14 @@ func (m *Manager) StopMiner(name string) error { return err } - delete(m.miners, name) + delete(m.miners, minerKey) return nil } // GetMiner retrieves a miner by ID func (m *Manager) GetMiner(name string) (Miner, error) { - miner, exists := m.miners[name] + minerKey := strings.ToLower(name) // Normalize input name to lowercase + miner, exists := m.miners[minerKey] if !exists { return nil, fmt.Errorf("miner not found: %s", name) } diff --git a/pkg/mining/mining.go b/pkg/mining/mining.go index 50e5101..e31cfaf 100644 --- a/pkg/mining/mining.go +++ b/pkg/mining/mining.go @@ -111,6 +111,7 @@ type Config struct { HealthPrintTime int `json:"healthPrintTime,omitempty"` NoColor bool `json:"noColor,omitempty"` Verbose bool `json:"verbose,omitempty"` + LogOutput bool `json:"logOutput,omitempty"` // New field to control stdout/stderr logging // Misc options Background bool `json:"background,omitempty"` @@ -177,7 +178,7 @@ type XMRigSummary struct { SharesTotal uint64 `json:"shares_total"` } `json:"results"` Uptime uint64 `json:"uptime"` - Algorithm string `json:"algo"` + Algorithm string `json:"algorithm"` } // AvailableMiner represents a miner that is available to be started diff --git a/pkg/mining/xmrig.go b/pkg/mining/xmrig.go index 03c0caa..c5ddbeb 100644 --- a/pkg/mining/xmrig.go +++ b/pkg/mining/xmrig.go @@ -295,9 +295,9 @@ func (m *XMRigMiner) Start(config *Config) error { args = append(args, "--rig-id", config.RigID) } // TLS is handled by config file, but --tls-fingerprint is a CLI option - if config.TLS { // If TLS is true in config, ensure --tls is passed if not already in config file - args = append(args, "--tls") - } + //if config.TLS { // If TLS is true in config, ensure --tls is passed if not already in config file + args = append(args, "--tls") + //} if config.TLSSingerprint != "" { args = append(args, "--tls-fingerprint", config.TLSSingerprint) } @@ -467,7 +467,17 @@ func (m *XMRigMiner) Start(config *Config) error { args = append(args, "--no-dmi") } + // Print the command being executed for debugging + fmt.Fprintf(os.Stderr, "Executing XMRig command: %s %s\n", m.MinerBinary, strings.Join(args, " ")) + m.cmd = exec.Command(m.MinerBinary, args...) + + // If LogOutput is true, redirect stdout and stderr + if config.LogOutput { + m.cmd.Stdout = os.Stdout + m.cmd.Stderr = os.Stderr + } + if err := m.cmd.Start(); err != nil { return err }