This commit is contained in:
lzx
2026-01-04 13:57:08 +08:00
parent 68b00962d3
commit f08ad364d9
18 changed files with 408 additions and 136 deletions

BIN
bin/client_linux Normal file

Binary file not shown.

BIN
bin/mining_task.db Normal file

Binary file not shown.

View File

@@ -5,7 +5,7 @@
1请您根据您的GPU所在主机的操作系统下载正确系统版本的客户端windows或linux(ubuntu等)
2必须通过官网且在正确的卖家账号下下载本客户端因为里面包含您的卖家信息如果通过非官方渠道或错误的卖家账号下载了客户端您的GPU信息无法同步到云算力平台
3下载并解压后请确定您的客户端包含以下文件
执行文件(client.exe或client)
执行文件(client_windows.exe或client_linux)
auth
mining.linux.conf
mining.windows.conf

View File

@@ -1,8 +1,13 @@
@echo off
:: 设置目标平台为 Windows 和 amd6464位
set GOOS=windows
set GOARCH=amd64
cd /d %~dp0
go build -o ../bin/client.exe main.go
go build -o ../bin/client_windows.exe main.go
if %errorlevel% equ 0 (
echo 编译成功!可执行文件位于: ..\bin\client.exe
echo 编译成功!可执行文件位于: ..\bin\client_windows.exe
) else (
echo 编译失败!
exit /b %errorlevel%

View File

@@ -0,0 +1,28 @@
@echo off
setlocal
:: 设置目标平台为 Linux 和 amd64
set GOOS=linux
set GOARCH=amd64
:: 可选:设置编译输出目录
set OUTPUT_DIR=../bin
:: 确保输出目录存在
if not exist %OUTPUT_DIR% (
mkdir %OUTPUT_DIR%
)
:: 编译 Go 程序
go build -o %OUTPUT_DIR%/client_linux main.go
:: 检查编译结果
if %ERRORLEVEL% NEQ 0 (
echo 编译失败!
exit /b %ERRORLEVEL%
)
echo 编译成功!可执行文件位于 %OUTPUT_DIR%/client_linux
endlocal
pause

View File

@@ -14,6 +14,7 @@
package client
import (
"bufio"
message "client/internal/msg"
"client/internal/src"
"client/internal/src/linux"
@@ -39,6 +40,7 @@ type Client struct {
MachineCode string
ServerConn net.Conn // 服务连接
GPUs map[int]message.GPU // {"gpu编号": message.GPU{}, ...}
MiningSofts []string
os *src.SystemServer
osName string
serverURL string // 服务器地址
@@ -58,7 +60,7 @@ func newClient(url string) *Client {
// 读取身份文件
auth, err := utils.ReadFile("./auth")
if err != nil {
log.Fatalf("获取客户端身份失败:%v", err)
log.Printf("获取客户端身份失败:%v", err)
return nil
}
@@ -101,31 +103,32 @@ func newClient(url string) *Client {
} else {
confFile = "mining.linux.conf"
}
var softs = make([]string, 0)
// 读取挖矿配置
cfg, err := ini.Load(confFile)
if err == nil {
sectionBzMiner := cfg.Section("bzminer")
miningConfig.BzMinerPath = sectionBzMiner.Key("path").String()
sectionLolMiner := cfg.Section("lolminer")
miningConfig.LolMinerPath = sectionLolMiner.Key("path").String()
if miningConfig.LolMinerPath != "" {
softs = append(softs, "lolminer")
}
sectionRigel := cfg.Section("rigel")
miningConfig.RigelPath = sectionRigel.Key("path").String()
if miningConfig.RigelPath != "" {
softs = append(softs, "rigel")
}
sectionProxy := cfg.Section("proxy")
miningConfig.ProxyEnabled, _ = sectionProxy.Key("proxy").Bool()
}
client.MiningSofts = softs
client.sustainMiner = sustain.NewSustainMiner(systemServer, sys, miningConfig)
// 读取主机MAC地址信息
var machine_code string
machine_code, err = systemServer.GetMACAddress(sys)
if err != nil {
log.Fatalln(err)
panic("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
log.Println(err)
log.Fatalln("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
}
// utils.WirteFile("./machinecode", machine_code)
@@ -133,8 +136,8 @@ func newClient(url string) *Client {
gpus, err := systemServer.GetGPUInfo(sys)
if err != nil {
log.Fatalln(err)
panic("获取当前主机GPU数据失败程序已退出请检查GPU驱动等程序后重新启动本客户端。")
log.Println(err)
log.Fatalln("获取当前主机GPU数据失败程序已退出请检查GPU驱动等程序后重新启动本客户端。")
}
client.GPUs = gpus
client.serverURL = url
@@ -144,7 +147,7 @@ func newClient(url string) *Client {
// 连接服务端
server_conn, err := net.Dial("tcp", url)
if err != nil {
log.Fatalf("客户端连接到服务器失败:%v", err)
log.Printf("客户端连接到服务器失败:%v", err)
return nil
}
@@ -171,14 +174,18 @@ func (c *Client) Stop() {
func (c *Client) sendMachineCode() {
var msg message.ServerMsg
msg.ID = c.Auth + "." + c.MachineCode
msg.ID = c.Auth + "::" + c.MachineCode
msg.Method = "auth.machineCode"
msg.Params = c.GPUs
var params = make(map[string]any)
params["gpus"] = c.GPUs
params["miningsofts"] = c.MiningSofts
msg.Params = params
msgByte, err := json.Marshal(msg)
if err != nil {
log.Fatalf("消息(%v)序列化失败:%v", msg, err)
log.Printf("消息(%v)序列化失败:%v", msg, err)
return
}
log.Println(string(msgByte))
c.send(msgByte)
}
@@ -192,7 +199,8 @@ func (c *Client) receiveMsg() {
c.mu.Unlock()
}()
buffer := make([]byte, 1024)
// 使用 bufio.Reader 读取数据
reader := bufio.NewReader(c.ServerConn)
for {
c.mu.Lock()
@@ -206,26 +214,29 @@ func (c *Client) receiveMsg() {
// 设置读取超时,用于检测连接是否存活
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
n, err := conn.Read(buffer)
// 读取一行数据,直到遇到换行符
msgByte, err := reader.ReadString('\n')
if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
log.Println("读取超时,连接可能已断开")
c.reconnect()
return
}
if err.Error() == "EOF" {
// 服务端关闭连接时,退出接收循环
log.Println("服务端关闭了连接")
c.reconnect()
return
}
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
log.Println("读取超时,连接可能已断开")
c.reconnect()
return
}
log.Printf("接收数据失败: %v", err)
c.reconnect()
return
}
msgByte := buffer[:n]
go c.handleReceiveMsg(msgByte)
// 输出接收到的消息
log.Printf("收到新消息:%s", msgByte)
go c.handleReceiveMsg([]byte(msgByte)) // 处理消息
}
}
@@ -237,7 +248,7 @@ func (c *Client) send(msg []byte) error {
return fmt.Errorf("连接已断开")
}
_, err := c.ServerConn.Write(msg)
_, err := c.ServerConn.Write(append(msg, '\n'))
if err != nil {
log.Printf("发送消息失败:%v\n消息内容%s", err, string(msg))
return err
@@ -249,26 +260,43 @@ func (c *Client) handleReceiveMsg(msg []byte) {
var data message.ServerMsg
err := json.Unmarshal(msg, &data)
if err != nil {
log.Fatalf("解析接收到的消息失败:%v", err)
log.Printf("解析接收到的消息失败:%v", err)
return
}
parts := strings.Split(data.ID, ".")
parts := strings.Split(data.ID, "::")
if len(parts) != 2 {
log.Fatalf("解析通信协议(server->client)失败")
log.Printf("解析通信协议(server->client)失败")
return
}
auth, machine_code := parts[0], parts[1]
if c.Auth != auth || c.MachineCode != machine_code {
log.Fatalf("客户端接收到错误的服务端消息")
log.Printf("客户端接收到错误的服务端消息")
return
}
switch data.Method {
case "pong":
// 收到心跳响应更新最后pong时间
case "ping":
// 收到服务端心跳更新最后ping时间并回复pong
c.mu.Lock()
c.lastPong = time.Now()
c.mu.Unlock()
log.Println("收到心跳响应")
log.Println("收到服务端心跳")
// 回复pong
pongMsg := message.ServerMsg{
ID: c.Auth + "::" + c.MachineCode,
Method: "pong",
Params: nil,
}
msgByte, err := json.Marshal(pongMsg)
if err != nil {
log.Printf("序列化pong消息失败%v", err)
return
}
if err := c.send(msgByte); err != nil {
log.Printf("发送pong响应失败%v", err)
} else {
log.Println("已回复pong")
}
return
case "mining.req":
// 将 data.Params 重新序列化为 JSON然后反序列化为 ConfigurationMiningMsg
@@ -277,7 +305,7 @@ func (c *Client) handleReceiveMsg(msg []byte) {
if err != nil {
log.Printf("序列化 Params 失败:%v", err)
sendMsg_str := message.ServerMsgResp{
ID: c.Auth + "." + c.MachineCode,
ID: c.Auth + "::" + c.MachineCode,
Result: false,
Data: fmt.Errorf("序列化 Params 失败:%v", err),
}
@@ -291,7 +319,7 @@ func (c *Client) handleReceiveMsg(msg []byte) {
if err != nil {
log.Printf("解析挖矿配置消息失败:%v, Params: %s", err, string(paramsJSON))
sendMsg_str := message.ServerMsgResp{
ID: c.Auth + "." + c.MachineCode,
ID: c.Auth + "::" + c.MachineCode,
Result: false,
Data: fmt.Errorf("解析挖矿配置消息失败:%v", err),
}
@@ -309,15 +337,16 @@ func (c *Client) handleReceiveMsg(msg []byte) {
err = c.os.Mining(c.osName, mining_msg)
if err != nil {
sendMsg_str := message.ServerMsgResp{
ID: c.Auth + "." + c.MachineCode,
ID: c.Auth + "::" + c.MachineCode,
Result: false,
Data: err.Error(),
}
sendMsg_byte, err := json.Marshal(sendMsg_str)
if err != nil {
log.Fatalf("序列化%v失败%v", sendMsg_str, err)
log.Printf("序列化%v失败%v", sendMsg_str, err)
return
}
log.Println(string(sendMsg_byte))
c.send(sendMsg_byte) // 返回失败消息
return
}
@@ -332,13 +361,14 @@ func (c *Client) handleReceiveMsg(msg []byte) {
WatchUrl: "", // 这里需要根据矿池自动生成
}
sendMsg_str := message.ServerMsgResp{
ID: c.Auth + "." + c.MachineCode,
ID: c.Auth + "::" + c.MachineCode,
Result: true,
Data: respData,
Method: "mining.resp",
}
sendMsg_byte, err := json.Marshal(sendMsg_str)
if err != nil {
log.Fatalf("序列化%v失败%v", sendMsg_str, err)
log.Printf("序列化%v失败%v", sendMsg_str, err)
return
}
c.send(sendMsg_byte) // 返回成功消息
@@ -379,45 +409,24 @@ func (c *Client) monitorMiningTask(cfg message.ConfigurationMiningMsg) {
}
}
// startHeartbeat 启动心跳检查
// startHeartbeat 启动心跳检查监控是否收到服务端的ping
func (c *Client) startHeartbeat() {
ticker := time.NewTicker(30 * time.Second) // 每30秒发送一次心跳
ticker := time.NewTicker(30 * time.Second) // 每30秒检查一次
defer ticker.Stop()
for {
select {
case <-ticker.C:
// 检查是否超过60秒未收到pong响应
// 检查是否超过60秒未收到服务端的ping
c.mu.Lock()
lastPong := c.lastPong
conn := c.ServerConn
c.mu.Unlock()
if time.Since(lastPong) > 60*time.Second {
log.Println("超过60未收到心跳响应,连接可能已断开")
if time.Since(lastPong) > 60*time.Minute {
log.Println("超过60分钟未收到服务端心跳,连接可能已断开")
c.reconnect()
return
}
// 发送心跳
if conn != nil {
pingMsg := message.ServerMsg{
ID: c.Auth + "." + c.MachineCode,
Method: "ping",
Params: nil,
}
msgByte, err := json.Marshal(pingMsg)
if err != nil {
log.Printf("序列化心跳消息失败:%v", err)
continue
}
if err := c.send(msgByte); err != nil {
log.Printf("发送心跳失败:%v", err)
c.reconnect()
return
}
log.Println("发送心跳")
}
case <-c.stopHeartbeat:
return
}

View File

@@ -18,7 +18,7 @@ func NewSQLiteServer() *SQLiteServer {
// Open (or create) the SQLite database
db, err := sql.Open("sqlite3", "./mining_task.db")
if err != nil {
log.Fatal(err)
log.Println(err)
return nil
}
@@ -29,7 +29,7 @@ func NewSQLiteServer() *SQLiteServer {
// Initialize the 'task' table
if err := s.initTaskTable(); err != nil {
log.Fatal(err)
log.Println(err)
return nil
}
@@ -79,7 +79,7 @@ func (s *SQLiteServer) LoadMiningTask() (bool, message.ConfigurationMiningMsg) {
// Query the database
rows, err := s.DB.Query(str, params...)
if err != nil {
log.Fatal(err)
log.Println(err)
}
defer rows.Close()
@@ -89,7 +89,7 @@ func (s *SQLiteServer) LoadMiningTask() (bool, message.ConfigurationMiningMsg) {
// Scan the row into the task structure
err := rows.Scan(&task.Coin, &task.Algo, &task.Pool, &task.WalletMining, &task.PoolUrl, &task.WalletAddress, &task.PoolUser, &task.WorkerID, &task.EndTimestamp)
if err != nil {
log.Fatal(err)
log.Println(err)
}
// Check if there's more than one row

View File

@@ -0,0 +1,5 @@
[url]
# 消息进来的端口,即监听端口
in=:3333
# 消息发出去的端口,即转发端口
out=47.129.22.53:21000

BIN
internal/proxy/ali/main Normal file

Binary file not shown.

View File

@@ -0,0 +1,80 @@
package main
import (
"io"
"log"
"net"
"os"
"strings"
"gopkg.in/ini.v1"
)
func readConfig() (string, string) {
cfg, err := ini.Load("config.conf")
if err != nil {
log.Fatalf("无法读取配置文件: %v", err)
os.Exit(1)
}
section := cfg.Section("url")
minerPort := strings.Trim(section.Key("in").String(), `""`)
minerPoolAddr := strings.Trim(section.Key("out").String(), `""`)
return minerPort, minerPoolAddr
}
var minerPort, minerPoolAddr = readConfig()
// 处理矿机请求的函数
func handleMinerConnection(minerConn net.Conn) {
defer minerConn.Close()
log.Println("有矿机接入")
// 连接到矿池
poolConn, err := net.Dial("tcp", minerPoolAddr)
if err != nil {
log.Printf("无法连接到矿池: %v", err)
return
}
defer poolConn.Close()
// 启动两个 goroutine一个从矿机接收数据并转发到矿池另一个从矿池接收数据并转发回矿机
go transferData(minerConn, poolConn)
go transferData(poolConn, minerConn)
// 保持服务运行,直到矿机或矿池关闭连接
select {}
}
// 数据转发函数:从源连接读取数据并写入到目标连接
func transferData(src net.Conn, dest net.Conn) {
_, err := io.Copy(dest, src)
if err != nil {
log.Printf("数据转发失败: %v", err)
}
}
func main() {
// 设置代理服务监听端口
listener, err := net.Listen("tcp", minerPort)
if err != nil {
log.Fatalf("无法启动监听服务: %v", err)
os.Exit(1)
}
defer listener.Close()
log.Printf("代理服务启动,监听端口 %s\n", minerPort)
// 不断接收来自矿机的连接
for {
// 接受矿机连接
minerConn, err := listener.Accept()
if err != nil {
log.Printf("接受连接失败: %v", err)
continue
}
// 为每个矿机连接启动一个新的 goroutine 来处理
go handleMinerConnection(minerConn)
}
}

View File

@@ -0,0 +1,5 @@
[url]
# 消息进来的端口,即监听端口
in=:21000
# 消息发出去的端口,即转发端口
out=stratum+tcp://nexa.m2pool.com:33333

View File

@@ -0,0 +1,80 @@
package main
import (
"io"
"log"
"net"
"os"
"strings"
"gopkg.in/ini.v1"
)
func readConfig() (string, string) {
cfg, err := ini.Load("config.conf")
if err != nil {
log.Fatalf("无法读取配置文件: %v", err)
os.Exit(1)
}
section := cfg.Section("url")
minerPort := strings.Trim(section.Key("in").String(), `""`)
minerPoolAddr := strings.Trim(section.Key("out").String(), `""`)
return minerPort, minerPoolAddr
}
var minerPort, minerPoolAddr = readConfig()
// 处理矿机请求的函数
func handleMinerConnection(minerConn net.Conn) {
defer minerConn.Close()
log.Println("有矿机接入")
// 连接到矿池
poolConn, err := net.Dial("tcp", minerPoolAddr)
if err != nil {
log.Printf("无法连接到矿池: %v", err)
return
}
defer poolConn.Close()
// 启动两个 goroutine一个从矿机接收数据并转发到矿池另一个从矿池接收数据并转发回矿机
go transferData(minerConn, poolConn)
go transferData(poolConn, minerConn)
// 保持服务运行,直到矿机或矿池关闭连接
select {}
}
// 数据转发函数:从源连接读取数据并写入到目标连接
func transferData(src net.Conn, dest net.Conn) {
_, err := io.Copy(dest, src)
if err != nil {
log.Printf("数据转发失败: %v", err)
}
}
func main() {
// 设置代理服务监听端口
listener, err := net.Listen("tcp", minerPort)
if err != nil {
log.Fatalf("无法启动监听服务: %v", err)
os.Exit(1)
}
defer listener.Close()
log.Printf("代理服务启动,监听端口 %s\n", minerPort)
// 不断接收来自矿机的连接
for {
// 接受矿机连接
minerConn, err := listener.Accept()
if err != nil {
log.Printf("接受连接失败: %v", err)
continue
}
// 为每个矿机连接启动一个新的 goroutine 来处理
go handleMinerConnection(minerConn)
}
}

View File

@@ -50,15 +50,12 @@ func CheckPermission() error {
func NewLinuxClient(auth string) *LinuxClient {
cfg, err := ini.Load("mining.linux.conf")
if err != nil {
log.Fatalf("获取挖矿配置失败: %v", err)
log.Printf("获取挖矿配置失败: %v", err)
log.Printf("客户端已退出,请重新检查配置文件(%s)是否存在", "mining.linux.conf")
return nil
}
// 解析配置
var miningConfig message.MiningConfig
// 解析 [bzminer] 部分
sectionBzMiner := cfg.Section("bzminer")
miningConfig.BzMinerPath = sectionBzMiner.Key("path").String()
// 解析 [lolminer] 部分
sectionLolMiner := cfg.Section("lolminer")
@@ -72,20 +69,11 @@ func NewLinuxClient(auth string) *LinuxClient {
sectionProxy := cfg.Section("proxy")
miningConfig.ProxyEnabled, _ = sectionProxy.Key("proxy").Bool()
if miningConfig.BzMinerPath != "" {
result := utils.CheckFileExists(miningConfig.BzMinerPath)
if !result {
log.Fatalf("未检测到bzminer挖矿软件的存在请确认是否已经安装bzminer并核对下列路径%s", miningConfig.BzMinerPath)
log.Println("客户端已退出,确认路径后请重启客户端")
return nil
}
}
if miningConfig.LolMinerPath != "" {
result := utils.CheckFileExists(miningConfig.LolMinerPath)
if !result {
log.Fatalf("未检测到lolminer挖矿软件的存在请确认是否已经安装lolminer并核对下列路径%s", miningConfig.LolMinerPath)
log.Println("客户端已退出,确认路径后请重启客户端")
log.Printf("未检测到lolminer挖矿软件的存在请确认是否已经安装lolminer并核对下列路径%s", miningConfig.LolMinerPath)
log.Fatalln("客户端已退出,确认路径后请重启客户端")
return nil
}
}
@@ -93,8 +81,8 @@ func NewLinuxClient(auth string) *LinuxClient {
if miningConfig.RigelPath != "" {
result := utils.CheckFileExists(miningConfig.RigelPath)
if !result {
log.Fatalf("未检测到rigel挖矿软件的存在请确认是否已经安装rigel并核对下列路径%s", miningConfig.RigelPath)
log.Println("客户端已退出,确认路径后请重启客户端")
log.Printf("未检测到rigel挖矿软件的存在请确认是否已经安装rigel并核对下列路径%s", miningConfig.RigelPath)
log.Fatalln("客户端已退出,确认路径后请重启客户端")
return nil
}
}
@@ -110,8 +98,8 @@ func NewLinuxClient(auth string) *LinuxClient {
// 获取主机身份
mac, err := client.GetMACAddress()
if err != nil {
log.Fatalln(err)
panic("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
log.Println(err)
log.Fatalln("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
}
client.MachineCode = mac
client.ID = auth + "." + mac
@@ -129,7 +117,7 @@ func (l *LinuxClient) initHistoryTask() {
l.mu.Unlock()
err := l.Mining(task)
if err != nil {
log.Fatalf("重新开启挖矿任务失败,请手动检查:%v", err)
log.Printf("重新开启挖矿任务失败,请手动检查:%v", err)
return
}
} else {
@@ -279,7 +267,7 @@ ALGO=NEXA
func (l *LinuxClient) lolminer(cfg message.ConfigurationMiningMsg) {
l.mu.Lock()
if l.Status != 2 {
log.Fatalf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
log.Printf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
return
}
l.Status = 1
@@ -303,14 +291,14 @@ func (l *LinuxClient) lolminer(cfg message.ConfigurationMiningMsg) {
// 启动进程
err := cmd.Start()
if err != nil {
log.Fatalf("Error starting lolMiner: %v", err)
log.Printf("Error starting lolMiner: %v", err)
return
}
// 添加执行记录
go func() {
err := l.db.InsertMiningTask(cfg)
if err != nil {
log.Fatalf("本次挖矿任务记录失败:%v", err)
log.Printf("本次挖矿任务记录失败:%v", err)
}
}()
// 获取 lolMiner 的进程 ID
@@ -344,7 +332,7 @@ func (l *LinuxClient) lolminer(cfg message.ConfigurationMiningMsg) {
go func() {
err := l.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
// 输出进程被杀死的信息
@@ -370,7 +358,7 @@ ALGO=NEXA
func (l *LinuxClient) bzminer(cfg message.ConfigurationMiningMsg) {
l.mu.Lock()
if l.Status != 2 {
log.Fatalf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
log.Printf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
return
}
l.Status = 1
@@ -392,14 +380,14 @@ func (l *LinuxClient) bzminer(cfg message.ConfigurationMiningMsg) {
// 启动进程
err := cmd.Start()
if err != nil {
log.Fatalf("Error starting bzminer: %v", err)
log.Printf("Error starting bzminer: %v", err)
return
}
// 添加执行记录
go func() {
err := l.db.InsertMiningTask(cfg)
if err != nil {
log.Fatalf("本次挖矿任务记录失败:%v", err)
log.Printf("本次挖矿任务记录失败:%v", err)
}
}()
// 获取 bzminer 的进程 ID
@@ -432,7 +420,7 @@ func (l *LinuxClient) bzminer(cfg message.ConfigurationMiningMsg) {
go func() {
err := l.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
// 输出进程被杀死的信息
@@ -458,7 +446,7 @@ ALGO=nexapow
func (l *LinuxClient) rigel(cfg message.ConfigurationMiningMsg) {
l.mu.Lock()
if l.Status != 2 {
log.Fatalf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
log.Printf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
return
}
l.Status = 1
@@ -481,14 +469,14 @@ func (l *LinuxClient) rigel(cfg message.ConfigurationMiningMsg) {
// 启动进程
err := cmd.Start()
if err != nil {
log.Fatalf("Error starting rigel: %v", err)
log.Printf("Error starting rigel: %v", err)
return
}
// 添加执行记录
go func() {
err := l.db.InsertMiningTask(cfg)
if err != nil {
log.Fatalf("本次挖矿任务记录失败:%v", err)
log.Printf("本次挖矿任务记录失败:%v", err)
}
}()
// 获取 rigel 的进程 ID
@@ -522,7 +510,7 @@ func (l *LinuxClient) rigel(cfg message.ConfigurationMiningMsg) {
go func() {
err := l.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
// 输出进程被结束的信息

View File

@@ -0,0 +1,77 @@
package miningsoft
import (
"bufio"
"log"
"os/exec"
"path/filepath"
"strings"
)
/*
XTM - Cuckaroo29 - lolMiner.exe --algo CR29 --pool xtm-c29.kryptex.network:7040 --user WALLET_ADDRESS/WORKER_NAME
CFX - Conflux - lolMiner.exe --algo OCTOPUS --pool cfx.kryptex.network:7027 --user WALLET_ADDRESS/WORKER_NAME
IRON - IronFish - lolMiner.exe --algo FISHHASH --pool iron.kryptex.network:7017 --user WALLET_ADDRESS.WORKER_NAME
NEXA - NexaPow - lolMiner.exe --algo NEXA --pool nexa.kryptex.network:7026 --user WALLET_ADDRESS/WORKER_NAME
KLS - Karlsen - lolMiner.exe --algo KARLSENV2 --pool kls.kryptex.network:7022 --user WALLET_ADDRESS/WORKER_NAME
ERG - Autolykos - lolMiner.exe --algo AUTOLYKOS2 --pool erg.kryptex.network:7021 --user WALLET_ADDRESS/WORKER_NAME
XEL - Xelishashv2 - rigel.exe -a xelishashv2 -o stratum+tcp://xel.kryptex.network:7019 -u WALLET_ADDRESS/WORKER_NAME
QUAI - QUAI - rigel.exe -a quai -o stratum+tcp://quai.kryptex.network:7035 -u WALLET_ADDRESS/WORKER_NAME
XNA - Neurai - rigel.exe -a kawpow --coin xna -o stratum+tcp://xna.kryptex.network:7024 -u WALLET_ADDRESS/WORKER_NAME
CLORE - KawPow - rigel.exe -a kawpow --coin clore -o stratum+tcp://clore.kryptex.network:7025 -u WALLET_ADDRESS/WORKER_NAME
RVN - Ravencoin - rigel.exe -a kawpow --coin rvn -o stratum+tcp://rvn.kryptex.network:7031 -u WALLET_ADDRESS/WORKER_NAME
*/
const SOFTNAME = "lolMiner"
func StartMiner(soft_path, algo, pool, user, worker_id string, ch chan string) {
name := filepath.Join(soft_path, SOFTNAME)
args := []string{"--algo", algo, "--pool", pool, "--user", user + "/" + worker_id}
cmd := exec.Command(name, args...)
cmd.Dir = soft_path
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Printf("获取 lolMiner 标准输出失败: %v", err)
return
}
// stderr, err := cmd.StderrPipe()
// if err != nil {
// log.Printf("获取 lolMiner 错误输出失败: %v", err)
// return
// }
log.Printf("执行命令:%s %s", name, strings.Join(args, " "))
// 启动lolminer
err = cmd.Start()
if err != nil {
log.Printf("Error starting lolMiner: %v", err)
return
}
// 处理标准输出
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
switch {
case strings.Contains(line, "Lost connection to stratum"):
log.Printf("lolMiner 检测到矿池断开连接: %s", line)
case strings.Contains(line, "Average speed (15s)"):
if strings.Contains(line, "Average speed (15s): 0.00 Mh/s") {
log.Printf("lolMiner 检测到没有算力: %s", line)
} else {
// 有算力
}
case strings.Contains(line, "defect stratum message"):
log.Printf("lolMiner 检测到 stratum 协议错误: %s", line)
default:
log.Printf("lolMiner 输出: %s", line)
}
}
if err := scanner.Err(); err != nil {
log.Printf("读取 lolMiner 标准输出失败: %v", err)
}
}()
}

View File

@@ -0,0 +1 @@
package miningsoft

View File

@@ -68,6 +68,6 @@ func (s *SystemServer) StopMining(osName string) {
if srv, ok := s.systems[osName]; ok {
srv.StopMining()
} else {
log.Fatalf("错误的操作系统:%s", osName)
log.Printf("错误的操作系统:%s", osName)
}
}

View File

@@ -46,7 +46,7 @@ func CheckPermission() error {
func NewWindowsClient(auth string) *WindowsClient {
cfg, err := ini.Load("mining.windows.conf")
if err != nil {
log.Fatalf("获取挖矿配置失败: %v", err)
log.Printf("获取挖矿配置失败: %v", err)
log.Printf("客户端已退出,请重新检查配置文件(%s)是否存在", "mining.windows.conf")
return nil
}
@@ -68,20 +68,11 @@ func NewWindowsClient(auth string) *WindowsClient {
sectionProxy := cfg.Section("proxy")
miningConfig.ProxyEnabled, _ = sectionProxy.Key("proxy").Bool()
if miningConfig.BzMinerPath != "" {
result := utils.CheckFileExists(miningConfig.BzMinerPath)
if !result {
log.Fatalf("未检测到bzminer挖矿软件的存在请确认是否已经安装bzminer并核对下列路径%s", miningConfig.BzMinerPath)
log.Println("客户端已退出,确认路径后请重启客户端")
return nil
}
}
if miningConfig.LolMinerPath != "" {
result := utils.CheckFileExists(miningConfig.LolMinerPath)
if !result {
log.Fatalf("未检测到lolminer挖矿软件的存在请确认是否已经安装lolminer并核对下列路径%s", miningConfig.LolMinerPath)
log.Println("客户端已退出,确认路径后请重启客户端")
log.Printf("未检测到lolminer挖矿软件的存在请确认是否已经安装lolminer并核对下列路径%s", miningConfig.LolMinerPath)
log.Fatalln("客户端已退出,确认路径后请重启客户端")
return nil
}
}
@@ -89,8 +80,8 @@ func NewWindowsClient(auth string) *WindowsClient {
if miningConfig.RigelPath != "" {
result := utils.CheckFileExists(miningConfig.RigelPath)
if !result {
log.Fatalf("未检测到rigel挖矿软件的存在请确认是否已经安装rigel并核对下列路径%s", miningConfig.RigelPath)
log.Println("客户端已退出,确认路径后请重启客户端")
log.Printf("未检测到rigel挖矿软件的存在请确认是否已经安装rigel并核对下列路径%s", miningConfig.RigelPath)
log.Fatalln("客户端已退出,确认路径后请重启客户端")
return nil
}
}
@@ -105,8 +96,8 @@ func NewWindowsClient(auth string) *WindowsClient {
mac, err := client.GetMACAddress()
if err != nil {
log.Fatalln(err)
panic("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
log.Println(err)
log.Fatalln("获取当前主机信息失败,程序已退出,请检查网络后重新启动本客户端。")
}
client.MachineCode = mac
@@ -125,7 +116,7 @@ func (w *WindowsClient) initHistoryTask() {
w.mu.Unlock()
err := w.Mining(task)
if err != nil {
log.Fatalf("重新开启挖矿任务失败,请手动检查:%v", err)
log.Printf("重新开启挖矿任务失败,请手动检查:%v", err)
return
}
} else {
@@ -257,6 +248,9 @@ func (w *WindowsClient) GetMACAddress() (string, error) {
return "", fmt.Errorf("获取到的主机 UUID 无效: %q", uuid)
}
// 将 UUID 中的 "." 替换成 "::"
// uuid = strings.Replace(uuid, ".", "::", -1)
// 统一转换为大写,去掉花括号
uuid = strings.Trim(uuid, "{}")
uuid = strings.ToUpper(uuid)
@@ -271,7 +265,7 @@ Windows 下使用 lolMiner.exe
func (w *WindowsClient) lolminer(cfg message.ConfigurationMiningMsg) {
w.mu.Lock()
if w.Status != 2 {
log.Fatalf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
log.Printf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
return
}
w.Status = 1
@@ -295,14 +289,14 @@ func (w *WindowsClient) lolminer(cfg message.ConfigurationMiningMsg) {
// 启动进程
err := cmd.Start()
if err != nil {
log.Fatalf("Error starting lolMiner: %v", err)
log.Printf("Error starting lolMiner: %v", err)
return
}
// 添加执行记录
go func() {
err := w.db.InsertMiningTask(cfg)
if err != nil {
log.Fatalf("本次挖矿任务记录失败:%v", err)
log.Printf("本次挖矿任务记录失败:%v", err)
}
}()
// 获取 lolMiner 的进程 ID
@@ -327,7 +321,7 @@ func (w *WindowsClient) lolminer(cfg message.ConfigurationMiningMsg) {
go func() {
err := w.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
} else {
@@ -343,7 +337,7 @@ func (w *WindowsClient) lolminer(cfg message.ConfigurationMiningMsg) {
go func() {
err := w.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
}
@@ -360,7 +354,7 @@ Windows 下使用 bzminer.exe
func (w *WindowsClient) bzminer(cfg message.ConfigurationMiningMsg) {
w.mu.Lock()
if w.Status != 2 {
log.Fatalf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
log.Printf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
return
}
w.Status = 1
@@ -382,14 +376,14 @@ func (w *WindowsClient) bzminer(cfg message.ConfigurationMiningMsg) {
// 启动进程
err := cmd.Start()
if err != nil {
log.Fatalf("Error starting bzminer: %v", err)
log.Printf("Error starting bzminer: %v", err)
return
}
// 添加执行记录
go func() {
err := w.db.InsertMiningTask(cfg)
if err != nil {
log.Fatalf("本次挖矿任务记录失败:%v", err)
log.Printf("本次挖矿任务记录失败:%v", err)
}
}()
// 获取 bzminer 的进程 ID
@@ -425,7 +419,7 @@ func (w *WindowsClient) bzminer(cfg message.ConfigurationMiningMsg) {
go func() {
err := w.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
// 输出进程被结束的信息
@@ -444,7 +438,7 @@ Windows 下使用 rigel.exe
func (w *WindowsClient) rigel(cfg message.ConfigurationMiningMsg) {
w.mu.Lock()
if w.Status != 2 {
log.Fatalf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
log.Printf("当前还有挖矿任务正在进行中:币=%s, 算法=%s, 矿池=%s, 截止时间=%d", cfg.Coin, cfg.Algo, cfg.Pool, cfg.EndTimestamp)
return
}
w.Status = 1
@@ -467,14 +461,14 @@ func (w *WindowsClient) rigel(cfg message.ConfigurationMiningMsg) {
// 启动进程
err := cmd.Start()
if err != nil {
log.Fatalf("Error starting rigel: %v", err)
log.Printf("Error starting rigel: %v", err)
return
}
// 添加执行记录
go func() {
err := w.db.InsertMiningTask(cfg)
if err != nil {
log.Fatalf("本次挖矿任务记录失败:%v", err)
log.Printf("本次挖矿任务记录失败:%v", err)
}
}()
// 获取 rigel 的进程 ID
@@ -510,7 +504,7 @@ func (w *WindowsClient) rigel(cfg message.ConfigurationMiningMsg) {
go func() {
err := w.db.FinishMiningTask(cfg)
if err != nil {
log.Fatalf("修改执行记录失败:%v", err)
log.Printf("修改执行记录失败:%v", err)
}
}()
// 输出进程被结束的信息

View File

@@ -67,7 +67,7 @@ func CheckAndUpdate(remoteBaseURL string, currentVersion string) (bool, error) {
// fetchRemoteVersion 从远程获取版本号
func fetchRemoteVersion(remoteBaseURL string) (string, error) {
versionURL := fmt.Sprintf("%s/current_version", remoteBaseURL)
versionURL := fmt.Sprintf("%s/user/getClientVersion", remoteBaseURL)
resp, err := http.Get(versionURL)
if err != nil {