initial commit: recovered source code for idleminer
This commit is contained in:
227
main.go
Normal file
227
main.go
Normal file
@@ -0,0 +1,227 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
PauseThreshold float64 `json:"pause_threshold"`
|
||||
ResumeThreshold float64 `json:"resume_threshold"`
|
||||
MaxCPUUsage int `json:"max_cpu_usage"`
|
||||
XMRigPath string `json:"xmrig_path"`
|
||||
CPUPriority int `json:"cpu_priority"`
|
||||
AutoUpdate bool `json:"auto_update"`
|
||||
ForceUpdate bool `json:"force_update"`
|
||||
SkipUpdateCheck bool `json:"skip_update_check"`
|
||||
LogFile string `json:"log_file"`
|
||||
Verbose bool `json:"verbose"`
|
||||
}
|
||||
|
||||
type MinerManager struct {
|
||||
Config Config
|
||||
IsRunning bool
|
||||
MinerCmd *exec.Cmd
|
||||
MinerPID int
|
||||
LastStats CPUStats
|
||||
}
|
||||
|
||||
type CPUStats struct {
|
||||
User uint64
|
||||
Nice uint64
|
||||
System uint64
|
||||
Idle uint64
|
||||
Total uint64
|
||||
}
|
||||
|
||||
var httpClient = &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
func main() {
|
||||
config := parseFlags()
|
||||
|
||||
err := ensureXMRigBinary(&config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to ensure XMRig binary: %v", err)
|
||||
}
|
||||
|
||||
manager := &MinerManager{
|
||||
Config: config,
|
||||
}
|
||||
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
<-sigChan
|
||||
fmt.Println("\nStopping miner and exiting...")
|
||||
manager.stopMiner()
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
fmt.Println("=== XMRig Idle Manager ===")
|
||||
manager.monitorAndManage()
|
||||
}
|
||||
|
||||
func parseFlags() Config {
|
||||
var c Config
|
||||
flag.Float64Var(&c.PauseThreshold, "pause-threshold", 30.0, "CPU percentage to pause mining")
|
||||
flag.Float64Var(&c.ResumeThreshold, "resume-threshold", 15.0, "CPU percentage to resume mining")
|
||||
flag.IntVar(&c.MaxCPUUsage, "max-cpu-usage", 75, "Maximum CPU usage for XMRig")
|
||||
flag.StringVar(&c.XMRigPath, "xmrig-path", "", "Override XMRig binary location")
|
||||
flag.IntVar(&c.CPUPriority, "cpu-priority", 0, "CPU priority (0-5)")
|
||||
flag.BoolVar(&c.AutoUpdate, "auto-update", false, "Automatically download XMRig updates")
|
||||
flag.BoolVar(&c.ForceUpdate, "force-update", false, "Force update XMRig")
|
||||
flag.BoolVar(&c.SkipUpdateCheck, "skip-update-check", false, "Skip checking for XMRig updates")
|
||||
flag.StringVar(&c.LogFile, "log-file", "/tmp/xmrig.log", "Log file path")
|
||||
flag.BoolVar(&c.Verbose, "verbose", false, "Enable verbose logging")
|
||||
flag.Parse()
|
||||
return c
|
||||
}
|
||||
|
||||
func ensureXMRigBinary(c *Config) error {
|
||||
if c.XMRigPath != "" {
|
||||
if _, err := os.Stat(c.XMRigPath); err != nil {
|
||||
return fmt.Errorf("specified XMRig path not found: %s", c.XMRigPath)
|
||||
}
|
||||
fmt.Printf("Using user-specified XMRig: %s\n", c.XMRigPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
path := findXMRigBinary()
|
||||
if path == "" {
|
||||
fmt.Println("XMRig binary not found. Downloading...")
|
||||
return downloadAndInstallXMRig(c)
|
||||
}
|
||||
|
||||
c.XMRigPath = path
|
||||
if !c.SkipUpdateCheck {
|
||||
checkAndUpdateXMRig(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findXMRigBinary() string {
|
||||
paths := []string{"./xmrig", "/usr/bin/xmrig", expandPath("~/.local/bin/xmrig")}
|
||||
for _, p := range paths {
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func expandPath(path string) string {
|
||||
if strings.HasPrefix(path, "~/") {
|
||||
return filepath.Join(os.Getenv("HOME"), path[2:])
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func (m *MinerManager) monitorAndManage() {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
for range ticker.C {
|
||||
usage, err := m.getCPUUsage()
|
||||
if err != nil {
|
||||
fmt.Printf("Error during monitoring: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if usage > m.Config.PauseThreshold && m.IsRunning {
|
||||
fmt.Printf("CPU high (%.1f%%). Pausing miner...\n", usage)
|
||||
m.stopMiner()
|
||||
} else if usage < m.Config.ResumeThreshold && !m.IsRunning {
|
||||
fmt.Printf("CPU low (%.1f%%). Resuming miner...\n", usage)
|
||||
m.startMiner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MinerManager) getCPUUsage() (float64, error) {
|
||||
stats1, err := readCPUStat()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
stats2, err := readCPUStat()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
idle := float64(stats2.Idle - stats1.Idle)
|
||||
total := float64(stats2.Total - stats1.Total)
|
||||
if total == 0 { return 0, nil }
|
||||
return (1.0 - idle/total) * 100.0, nil
|
||||
}
|
||||
|
||||
func readCPUStat() (CPUStats, error) {
|
||||
f, err := os.Open("/proc/stat")
|
||||
if err != nil {
|
||||
return CPUStats{}, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var cpu string
|
||||
var user, nice, system, idle, iowait, irq, softirq, steal, guest, guestnice uint64
|
||||
_, err = fmt.Fscanf(f, "%s %d %d %d %d %d %d %d %d %d %d", &cpu, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guestnice)
|
||||
if err != nil {
|
||||
return CPUStats{}, err
|
||||
}
|
||||
|
||||
total := user + nice + system + idle + iowait + irq + softirq + steal
|
||||
return CPUStats{user, nice, system, idle, total}, nil
|
||||
}
|
||||
|
||||
func (m *MinerManager) startMiner() error {
|
||||
args := []string{
|
||||
"-o", "pool.gravitywell.xyz:11666",
|
||||
"-u", "48p7c...",
|
||||
"--cpu-max-threads-hint", strconv.Itoa(m.Config.MaxCPUUsage),
|
||||
}
|
||||
|
||||
m.MinerCmd = exec.Command(m.Config.XMRigPath, args...)
|
||||
m.MinerCmd.Stdout = os.Stdout
|
||||
m.MinerCmd.Stderr = os.Stderr
|
||||
|
||||
if err := m.MinerCmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start miner: %w", err)
|
||||
}
|
||||
|
||||
m.MinerPID = m.MinerCmd.Process.Pid
|
||||
m.IsRunning = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MinerManager) stopMiner() {
|
||||
if m.MinerCmd != nil && m.MinerCmd.Process != nil {
|
||||
m.MinerCmd.Process.Signal(syscall.SIGTERM)
|
||||
m.MinerCmd.Wait()
|
||||
}
|
||||
m.IsRunning = false
|
||||
}
|
||||
|
||||
func checkAndUpdateXMRig(c *Config) {}
|
||||
func downloadAndInstallXMRig(c *Config) error { return nil }
|
||||
func downloadFile(url string, path string) error { return nil }
|
||||
func verifyChecksum(path string, checksum string) error { return nil }
|
||||
func extractTarGz(src string, dest string) error { return nil }
|
||||
func copyFile(src string, dest string) error { return nil }
|
||||
func getLatestXMRigRelease() (string, string, error) { return "", "", nil }
|
||||
func getXMRigVersion(path string) (string, error) { return "", nil }
|
||||
func extractChecksum(data []byte, filename string) (string, error) { return "", nil }
|
||||
Reference in New Issue
Block a user