initial commit
This commit is contained in:
19
LICENSE
Normal file
19
LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright © 2017 Scott Alfter
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
123
README.md
Normal file
123
README.md
Normal file
@@ -0,0 +1,123 @@
|
||||
nvOC MiningPoolHub Switcher
|
||||
===========================
|
||||
|
||||
nvOC makes it easy to squeeze more hashrate out of your GPUs. MiningPoolHub
|
||||
makes it easy to mine altcoins and get paid in Bitcoin. However, nvOC is a
|
||||
customized Ubuntu Linux and the management software MiningPoolHub recommends
|
||||
for profit switching only runs under Windows. Their approach to
|
||||
coin-switching with nVidia GPUs under Linux is to loop through a bunch of
|
||||
different miners, erroring out on all but the currently-profitable coin. I
|
||||
lost nearly four hours this morning when a miner didn't exit properly during
|
||||
a switch.
|
||||
|
||||
This set of scripts bridges the gap. With them, you can use the miners
|
||||
included in nvOC (and others that you might add) to mine whatever's most
|
||||
profitable at MiningPoolHub. For each supported algorithm, you can
|
||||
customize power, clockspeed, and fan speed settings as you consider
|
||||
appropriate.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
1. ssh into your mining rig's m1 account.
|
||||
2. Clone these files into the same directory as nvOC's oneBash script.
|
||||
3. Disable oneBash by commenting out all lines in ~/2unix. oneBash should
|
||||
be invoked manually if you add/remove GPUs so it can reconfigure
|
||||
/etc/X11/xorg.conf, but it otherwise isn't used. To keep gnome-terminal
|
||||
from sucking down CPU cycles by constantly restarting the 2unix script, you
|
||||
might want to include something like "sleep 86400" at the end.
|
||||
4. Edit mph_conf.json. You'll set your user and miner names here. You can
|
||||
also customize your overclocking settings for each algorithm here.
|
||||
5. If your network is IPv6-enabled, note that nvOC (as of v17) has a problem
|
||||
connecting to IPv6 hosts. MiningPoolHub makes its API available over both IPv6
|
||||
and IPv4, so to force it to use IPv4 in the meantime, edit /etc/hosts as
|
||||
follows:
|
||||
|
||||
`104.27.168.52 miningpoolhub.com`
|
||||
6. Set mph_switch.py to launch with a cronjob:
|
||||
|
||||
`0,10,20,30,40,50 * * * * (cd /media/m1/1263-A96E && python2.7 mph_switch.py mph_conf.json)`
|
||||
|
||||
Every 10 minutes, the script will run and determine which miner needs to
|
||||
start up. If it's already running, it will leave it alone. If it needs to
|
||||
switch, it kills one miner and starts the other. If nothing's running
|
||||
(because the rig just rebooted or the miner crashed), it will start the
|
||||
miner.
|
||||
|
||||
current-profit is a text file that will be updated on every run of switch.py
|
||||
to show which is currently the most profitable. Profitability is determined
|
||||
by the MiningPoolHub API and is a unitless number; higher is better.
|
||||
|
||||
algo-log is a list of coins and algorithms the switcher has selected when
|
||||
run. If you start seeing repeats of the same algo every 10 minutes, that's
|
||||
a sign that something has gone wrong with your GPUs and you might want to
|
||||
consider a reboot.
|
||||
|
||||
Miners are started in Screen sessions (http://www.gnu.org/software/screen)
|
||||
that can be viewed over an ssh login session:
|
||||
|
||||
`screen -dr miner`
|
||||
|
||||
When the rig switches algorithms, the Screen session will be closed and a
|
||||
new one opened. Repeat the above to monitor it, or you could use something
|
||||
like this on a monitoring workstation:
|
||||
|
||||
`while true; do screen -dr miner; done`
|
||||
|
||||
Adding Algorithms
|
||||
-----------------
|
||||
|
||||
Some algorithms supported by MiningPoolHub can't be mined with the miners
|
||||
included in nvOC. If you add the appropriate software, though, you can mine
|
||||
these as well. Instructions to add these capabilities will follow.
|
||||
|
||||
Sia
|
||||
---
|
||||
|
||||
To add the miner:
|
||||
|
||||
`sudo apt install golang-go
|
||||
mkdir /home/m1/gocode
|
||||
GOPATH=/home/m1/gocode go get github.com/robvanmieghem/gominer`
|
||||
|
||||
To enable mining, create a new object named "sia" within the "miners"
|
||||
list in mph_conf.json. Here's what I use:
|
||||
|
||||
```
|
||||
"miners":
|
||||
{
|
||||
[existing entries deleted for brevity]
|
||||
"Sia":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a sia -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
CryptoNight
|
||||
-----------
|
||||
|
||||
To add the miner:
|
||||
|
||||
`cd /home/m1
|
||||
git clone https://github.com/KlausT/ccminer-cryptonight KTccminer-cryptonight
|
||||
cd KTccminer-cryptonight
|
||||
./autoreconf.sh
|
||||
./configure --with-cuda-/usr/local/cuda-8.0
|
||||
make`
|
||||
|
||||
To enable mining, create a new object named "cryptonight" within the "miners"
|
||||
list in mph_conf.json. Here's what I use:
|
||||
|
||||
```
|
||||
"miners":
|
||||
{
|
||||
[existing entries deleted for brevity]
|
||||
"Cryptonight":
|
||||
{
|
||||
"bin": "/home/m1/KTccminer-cryptonight/ccminer -a cryptonight -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": -200, "mem_oc": 1000, "fan": [70,75,70]
|
||||
}
|
||||
}
|
||||
```
|
||||
68
mph_conf.json
Normal file
68
mph_conf.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"user_name": "salfter",
|
||||
"miner_name": "miner10",
|
||||
"card_type": "nvidia",
|
||||
"miners":
|
||||
{
|
||||
"Blake-Vanilla":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a vanilla -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Equihash":
|
||||
{
|
||||
"bin": "/home/m1/zec/v3_4/miner --eexit 3 --fee 0 --pec --server {HOST} --user {NAME}.{MINER} --pass z --port {PORT}",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Ethash":
|
||||
{
|
||||
"bin": "/home/m1/eth/Genoil-U/ethminer -S {HOST}:{PORT} -O {NAME}.{MINER}:x -U",
|
||||
"power_limit": [115,115,95], "gpu_oc": -200, "mem_oc": 1000, "fan": [70,75,70]
|
||||
},
|
||||
"Groestl":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a groestl -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Keccak":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a keccak -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Lyra2RE2":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a lyra2v2 -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Myriad-Groestl":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a myr-gr -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"NeoScrypt":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a neoscrypt -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Qubit":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a qubit -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Scrypt":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a scrypt -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"Skein":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a skein -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
},
|
||||
"X11":
|
||||
{
|
||||
"bin": "/home/m1/SPccminer/ccminer -a x11 -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
|
||||
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
|
||||
}
|
||||
}
|
||||
}
|
||||
123
mph_switch.py
Normal file
123
mph_switch.py
Normal file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env python2.7
|
||||
|
||||
import pprint
|
||||
import json
|
||||
import urllib2
|
||||
import sys
|
||||
import datetime
|
||||
import time
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
# load config
|
||||
|
||||
cfg=json.loads(open(sys.argv[1]).read())
|
||||
|
||||
card_type=cfg["card_type"]
|
||||
miners=cfg["miners"]
|
||||
user_name=cfg["user_name"]
|
||||
miner_name=cfg["miner_name"]
|
||||
|
||||
os.environ["DISPLAY"]=":0"
|
||||
|
||||
# grab something from a website
|
||||
|
||||
def fetch(url):
|
||||
r=urllib2.Request(url)
|
||||
r.add_header("User-Agent", "Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1")
|
||||
r.add_header("Pragma", "no-cache")
|
||||
return urllib2.build_opener().open(r).read()
|
||||
|
||||
# main
|
||||
|
||||
data=json.loads(fetch("http://miningpoolhub.com/?page=api&action=getminingandprofitsstatistics"))["return"]
|
||||
|
||||
coins={}
|
||||
for i in reversed(data): # weed out unconfigured algos, do string substitutions
|
||||
try:
|
||||
miner=miners[i["algo"]]
|
||||
coins[i["coin_name"]]=miner["bin"].format(HOST=i["host"], PORT=str(i["port"]), NAME=user_name, MINER=miner_name)
|
||||
except:
|
||||
data.remove(i)
|
||||
|
||||
sort={}
|
||||
for i in data:
|
||||
sort[i["coin_name"]+" ("+i["algo"]+")"]=i["normalized_profit_"+card_type]
|
||||
sort=sorted(sort.items(), key=lambda x:x[1], reverse=True)
|
||||
log=open("current-profit", "w")
|
||||
for i in sort:
|
||||
log.write(i[0]+": "+str(i[1])+"\n")
|
||||
log.close()
|
||||
|
||||
max_profit_val=0 # find the most profitable coin
|
||||
for i in data:
|
||||
if i["normalized_profit_"+card_type]>max_profit_val:
|
||||
max_profit=i
|
||||
max_profit_val=i["normalized_profit_"+card_type]
|
||||
|
||||
miner=miners[max_profit["algo"]]
|
||||
coin=coins[max_profit["coin_name"]]
|
||||
|
||||
# see if miner's already running
|
||||
|
||||
try:
|
||||
subprocess.check_output(["pgrep", "-f", "^"+coin.replace("+", "\\+")])
|
||||
current=1
|
||||
except:
|
||||
current=0
|
||||
if (current==0):
|
||||
other=0
|
||||
for algo in coins:
|
||||
try:
|
||||
subprocess.check_output(["pgrep", "-f", "^"+coins[algo].replace("+", "\\+")])
|
||||
other=1
|
||||
except:
|
||||
pass
|
||||
|
||||
if (current==0):
|
||||
# log a change
|
||||
algo_log=open("algo-log", "a")
|
||||
algo_log.write(str(datetime.datetime.now())+": "+max_profit["coin_name"]+" ("+max_profit["algo"]+")\n")
|
||||
algo_log.close()
|
||||
if (other==1):
|
||||
# kill existing miners
|
||||
for algo in coins:
|
||||
subprocess.call(["pkill", "-f", "^"+coins[algo].replace("+", "\\+")])
|
||||
time.sleep(3)
|
||||
if card_type=="nvidia": # update card settings
|
||||
cards=int(subprocess.check_output("nvidia-smi --query-gpu=count --format=csv,noheader,nounits".split(" ")).split("\n")[-2])
|
||||
for i in range(0, cards):
|
||||
# power limit
|
||||
if type(miner["power_limit"]) is int:
|
||||
subprocess.call(("sudo nvidia-smi -i "+str(i)+" -pl "+str(miner["power_limit"])).split(" "))
|
||||
else:
|
||||
subprocess.call(("sudo nvidia-smi -i "+str(i)+" -pl "+str(miner["power_limit"][i])).split(" "))
|
||||
# core overclock
|
||||
if type(miner["gpu_oc"]) is int:
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[2]="+str(miner["gpu_oc"])).split(" "))
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[3]="+str(miner["gpu_oc"])).split(" "))
|
||||
else:
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[2]="+str(miner["gpu_oc"][i])).split(" "))
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[3]="+str(miner["gpu_oc"][i])).split(" "))
|
||||
# memory overclock
|
||||
if type(miner["mem_oc"]) is int:
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[2]="+str(miner["mem_oc"])).split(" "))
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[3]="+str(miner["mem_oc"])).split(" "))
|
||||
else:
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[2]="+str(miner["mem_oc"][i])).split(" "))
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[3]="+str(miner["mem_oc"][i])).split(" "))
|
||||
# fan speed
|
||||
if type(miner["fan"]) is int:
|
||||
if (miner["fan"]==0):
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=0").split(" "))
|
||||
else:
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=1").split(" "))
|
||||
subprocess.call(("nvidia-settings -a [fan:"+str(i)+"]/GPUTargetFanSpeed="+str(miner["fan"])).split(" "))
|
||||
else:
|
||||
if (miner["fan"][i]==0):
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=0").split(" "))
|
||||
else:
|
||||
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=1").split(" "))
|
||||
subprocess.call(("nvidia-settings -a [fan:"+str(i)+"]/GPUTargetFanSpeed="+str(miner["fan"][i])).split(" "))
|
||||
# launch new miner
|
||||
subprocess.call(("screen -dmS miner "+coin).split(" "))
|
||||
Reference in New Issue
Block a user