妖灵网

搜索
查看: 87|回复: 0

Azure 一键挖矿脚本

[复制链接]
累计签到:107 天
连续签到:1 天

310

主题

339

帖子

1028万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
10283396
QQ
发表于 2021-5-20 21:01:26 | 显示全部楼层 |阅读模式
手上有大量的计算资源怎么办?正经业务用不上这么多,又不想浪费它们,不如来挖矿吧。花了两天时间学习了 Azure CLI,写了个一键创建所有机器占满所有配额,且能自动执行命令的 Python 脚本。本脚本适合挖不需要 GPU 的币,比如 XMR(门罗币)。一般矿池都会为你准备好一键脚本。运行本脚本后,只需输入矿池给你的一键脚本,即可批量用完所有配额创建虚拟机。

什么是Azure CLI?
Azure Command-Line Interface(Azure CLI)是一组用来创建和管理 Azure 资源的命令,可用来快速使用 Azure(侧重于自动化)。
思路
1、检查配额以确定订阅类型,并确定要开的虚拟机数量。默认每个区域的配额都相同,因此只需查询美国东部地区的配额。
2、创建资源组。资源组是用于保存虚拟机等资源的容器。
3、创建开机后要运行的脚本。
4、批量创建虚拟机并运行挖矿脚本。创建实例类型为 F/FS 系列的虚拟机,因为该系列针对计算优化。在创建虚拟机时创建 shell 脚本并指定 cloud-init 参数即可实现虚拟机创建成功后自动运行脚本。
5、信息汇总,显示共创建了多少台虚拟机。
get_default_cli 是一个可以通过 Python 使用 Azure CLI 的函数,但它类似于“print”命令,输出的内容无法简单地赋值给变量。因此需要将输出重定向到 io.StringIO 对象来捕获它:
  1. <font color="#48d1cc">f = io.StringIO()
  2. with redirect_stdout(f):
  3.    get_default_cli().invoke(['vm', 'list-usage', '--location', 'East US',
  4.                   '--query', '[?localName == \'Total Regional vCPUs\']'])
  5.    limit = f.getvalue()</font>
复制代码

Azure CLI 支持 JMESPath query,通过 JMESPath query 可以精确的把 Json 的内容取出。
比如列出所有虚拟机的名称
  1. <font color="#48d1cc">1az vm list --query</font>
复制代码
查询美国东部地区的配额
  1. <font color="#48d1cc">az vm list-usage --location "East US" --query "[?localName == 'Total Regional vCPUs'].limit"</font>
复制代码

关于Azure for Students、免费试用和即用即付订阅的配额,我在脚本里已经写得非常详细了。若你的订阅不是其中的一种或另外申请有配额,需要手动修改创建虚拟机的数量。

比如某企业订阅每个区域有50个vCPUs ,FSv2 系列也为50个vCPUs,那么可以创建6个 Standard_F8s_v2 实例(占用48个vCPUs),然后创建一个 Standard_F2s_v2 实例(占用2个vCPUs),这样就用满了所有配额。

2021年2月14日更新:后来发现选择 F/FS 系列 CPU 最少的实例来挖矿,收益更高,因为多核性能不是简单叠加。同样配额下,选择多个 CPU 数量少的实例比一个 CPU 数量多的实例要好。脚本就懒得改了,因为这三种订阅的默认配额都比较低,改了后差别不大,并且手上的计算资源有别的用途,改了我还要一个个测试订阅的运行结果。改起来很简单,F2s_v2 实例配额用完后用 F2s ,然后是 D2s_v4 系列。

完整代码

  1. <font color="#48d1cc"><font color="#48d1cc"># -*- coding :  utf-8 -*-
  2. # @Time      :  2021-01-03
  3. # @Author    :  Github@sslspace
  4. # @Blog      : https://blog.shelike.me/
  5. # @Software  :  Pycharm

  6. import io
  7. import json
  8. import time
  9. from contextlib import redirect_stdout
  10. from azure.cli.core import get_default_cli

  11. # 1.检查配额以确定订阅类型,并确定要开的虚拟机数量
  12. # 初始化区域列表,共31个区域
  13. # Azure for Students和即用即付订阅均不支持 South India 和 West India 区域
  14. locations = ['eastus', 'eastus2', 'westus', 'centralus', 'northcentralus', 'southcentralus',
  15.              'northeurope', 'westeurope', 'eastasia', 'southeastasia', 'japaneast',
  16.              'japanwest', 'australiaeast', 'australiasoutheast', 'australiacentral',
  17.              'brazilsouth', 'centralindia', 'canadacentral', 'canadaeast', 'westus2',
  18.              'uksouth', 'ukwest', 'koreacentral', 'koreasouth', 'francecentral',
  19.              'southafricanorth', 'uaenorth', 'switzerlandnorth', 'germanywestcentral',
  20.              'norwayeast', 'westcentralus']

  21. # 捕获 get_default_cli().invoke 的标准输出
  22. f = io.StringIO()
  23. with redirect_stdout(f):
  24.     get_default_cli().invoke(['vm', 'list-usage', '--location', 'East US', '--query',
  25.                               '[?localName == \'Total Regional vCPUs\'].limit'])
  26.     limit = f.getvalue()

  27. # 默认每个区域的配额都相同,因此只需查询美国东部地区的配额
  28. # Azure for Students订阅每个区域的vCPU总数为6,
  29. # 标准FSv2系列vCPUs为4,标准FS系列vCPUs为4
  30. # 所以创建一个Standard_F4s_v2实例(占用4个vCPUs),
  31. # 一个Standard_F2s实例(占用2个vCPUs)
  32. if '6' in limit:
  33.     print("当前订阅为Azure for Students")
  34.     size1_name = "Standard_F4s_v2"
  35.     size1_abbreviation = "F4s_v2"
  36.     size1_count = 1
  37.     size2_name = "Standard_F2s"
  38.     size2_abbreviation = "F2s"
  39.     size2_count = 1
  40.     type = 0

  41. # 即用即付订阅每个区域的vCPU总数为10,与标准FSv2系列的vCPUs相同
  42. # 因此创建一个Standard_F8s_v2实例(占用8个vCPUs),
  43. # 一个Standard_F2s_v2实例(占用2个vCPUs)
  44. elif '10' in limit:
  45.     print("当前订阅为即用即付")
  46.     size1_name = "Standard_F8s_v2"
  47.     size1_abbreviation = "F8s_v2"
  48.     size1_count = 1
  49.     size2_name = "Standard_F2s_v2"
  50.     size2_abbreviation = "F2s_v2"
  51.     size2_count = 1
  52.     type = 1

  53. # 免费试用订阅每个区域的vCPU总数为4,与标准FSv2系列的vCPUs相同
  54. # 因此创建1个Standard_F4s_v2实例(共占用4个vCPUs)
  55. elif '4' in limit:
  56.     print("当前订阅为免费试用,每个区域的配额仅为4 vCPUs,建议升级后再用。"
  57.           "若升级后仍看到本消息,请等待十分钟再运行脚本。")
  58.     selection = input("输入Y继续运行,任意键退出")
  59.     if selection != "Y" or "y":
  60.         exit(0)
  61.     size1_name = "Standard_F4s_v2"
  62.     size1_abbreviation = "F4s_v2"
  63.     size1_count = 1
  64.     type = 2

  65. else:
  66.     print("未知订阅,请手动修改创建虚拟机的数量")
  67.     print("若当前订阅为Azure for Students、免费试用或即用即付,"
  68.           "请进入“创建虚拟机”界面,任意填写信息,"
  69.           "一直到“查看+创建”项(创建虚拟机的最后一步)"
  70.           "显示“验证通过”即可自动刷新配额")
  71.     print("假如还未解决,请直接修改limit = f.getvalue()中的"
  72.           "f.getvalue()为'区域配额'(包括英文引号)。Azure for"
  73.           " Students是6,即用即付是10,免费试用订阅是4")
  74.     exit(0)

  75. # 2.创建资源组
  76. # 资源组只是资源的逻辑容器,资源组内的资源不必与资源组位于同一区域
  77. get_default_cli().invoke(['group', 'create', '--name', 'myResourceGroup',
  78.                           '--location', 'eastus'])
  79. # 除非订阅被禁用,其他任何情况下创建资源组都会成功(重名也返回成功)
  80. print("创建资源组成功")

  81. # 3.创建开机后要运行的脚本
  82. init = input("请输入机器开机后要执行的命令(仅一行):  ")
  83. with open("./cloud-init.txt", "w") as f:
  84.     f.write("#cloud-config" + "\n")
  85.     f.write("runcmd:" + "\n")
  86.     f.write("  - sudo -s" + "\n")
  87.     f.write(f"  - {init}")

  88. # 4.批量创建虚拟机并运行挖矿脚本
  89. for location in locations:
  90.     # Azure for Students订阅不支持 norwayeast 区域
  91.     if location == "norwayeast" and type == 0:
  92.         continue

  93.     # westcentralus 区域不支持 FSv2 系列,
  94.     # Azure for Students订阅不支持 F/FS 系列
  95.     if location == "westcentralus" and type == 0:
  96.         size1_name = "Standard_D4ds_v4"
  97.         size1_abbreviation = "D4ds_v4"
  98.         size2_name = "Standard_D2s_v4"
  99.         size2_abbreviation = "D2s_v4"
  100.     if location == "westcentralus" and type == 1:
  101.         size1_name = "Standard_F8s"
  102.         size1_abbreviation = "F8s"
  103.         size2_name = "Standard_F2s"
  104.         size2_abbreviation = "F2s"
  105.     if location == "westcentralus" and type == 2:
  106.         size1_name = "Standard_F4s"
  107.         size1_abbreviation = "F4s"

  108.     count = 0
  109.     for a in range(0, size1_count):
  110.         count += 1
  111.         print("正在 " + str(location) + " 区域创建第 " + str(count)
  112.               + f" 个 {size1_name} 实例,共 " + str(size1_count) + " 个")
  113.         get_default_cli().invoke(
  114.             ['vm', 'create', '--resource-group', 'myResourceGroup', '--name',
  115.              f'{location}-{size1_abbreviation}-{count}', '--image', 'UbuntuLTS',
  116.              '--size', f'{size1_name}', '--location', f'{location}', '--admin-username',
  117.              'azureuser', '--admin-password', '6uPF5Cofvyjcew9', '--custom-data',
  118.              'cloud-init.txt', "--no-wait"])
  119.     if type != 2:
  120.         count = 0
  121.         for a in range(0, size2_count):
  122.             count += 1
  123.             print("正在 " + str(location) + " 区域创建第 " + str(count)
  124.                   + f" 个 {size2_name} 实例,共 " + str(size2_count) + " 个")
  125.             get_default_cli().invoke(
  126.                 ['vm', 'create', '--resource-group', 'myResourceGroup', '--name',
  127.                  f'{location}-{size2_abbreviation}-{count}', '--image', 'UbuntuLTS',
  128.                  '--size', f'{size2_name}', '--location', f'{location}', '--admin-username',
  129.                  'azureuser', '--admin-password', '6uPF5Cofvyjcew9', '--custom-data',
  130.                  'cloud-init.txt', "--no-wait"])

  131. # 5.信息汇总
  132. # 获取所有vm的名字
  133. print("\n------------------------------------------------------------------------------\n")
  134. print("大功告成!在31个区域创建虚拟机的命令已成功执行")
  135. for i in range(120, -1, -1):
  136.     print("\r正在等待Azure生成统计信息,还需等待{}秒".format(i), end="", flush=True)
  137.     time.sleep(1)
  138. print("\n------------------------------------------------------------------------------\n")
  139. print("以下是已创建的虚拟机列表:")
  140. get_default_cli().invoke(['vm', 'list', '--query', '[*].name'])
  141. print("\n\n-----------------------------------------------------------------------------\n")



  142. # 如果想删除脚本创建的所有资源,取消注释以下语句
  143. # get_default_cli().invoke(['group', 'delete', '--name', 'myResourceGroup',
  144. # '--no-wait', '--yes'])
  145. # print("删除资源组成功")</font></font>
复制代码

点击下载脚本:

运行环境

Python 3.9以下版本,azure-cli 模块,contextlib 模块。

首先确保你的Azure账号开过虚拟机,否则的话先随意创建一台机器,到了创建的最后一步,显示“验证通过”就可以关闭页面了,不需要真正创建。

运行这个脚本最简单的方法是进入Azure门户,点击右上角的命令行图标    进入Azure Cloud Shell


选择“创建存储”

选择“Bash”

输入

  1. <font color="#48d1cc">pip install azure-cli</font>
复制代码

等待安装完成后,创建一个文件,复制粘贴代码,然后用  python 文件名  运行它

2021年3月21日更新:也许是 get_default_cli() 更新后导致 f.getvalue() 取不到值。手动修改第29行 limit = f.getvalue() 中的 f.getvalue() 为"区域配额"(包括英文引号)即可。Azure for Students是6,即用即付是10,免费试用订阅是4。虚拟机创建完成后显示虚拟机列表,无需理会最后的报错。需要注意的是,若你的账号不是老号,或者有一定消费的号,对于这种大量开机器的行为(即使不挖矿)基本上会被匹配为恶意用户,在任何一个云计算平台都会封号,或者要求验证信用卡账单。对于Azure for Students订阅,新号几乎100%封号,别用了本脚本又来说封号。新号还不如只开几台来挖,老号才适合本脚本。使用本脚本一键把配额用满,因为计费系统有延迟,100美元余额能用到500美元左右订阅才被禁用。(余额更新不及时,最好几天后再去看)

故障排查

你的脚本无法运行

首先看看你的脚本是否能在最新的Ubuntu机器上运行。你的脚本能在普通的机器上运行,但批量创建机器后无法运行使用用户名azureuser和密码6uPF5Cofvyjcew9登录虚拟机,检查  /var/log/cloud-init-output.log  和  /var/log/cloud-init.log  的错误日志。可能是环境变量的问题。由于在初始化阶段没有环境变量,会导致对环境变量的调用失败。解决方法:修改你的脚本,声明环境变量;或者在输入命令时使用  export 环境变量=值 && 你的脚本 。比如 c3pool 的一键脚本用到  $HOME  ,那么解决方法就是  export HOME=/root && 一键脚本 。

其他情况

有多个目录或订阅?若在 portal.azure.com 使用 Azure Cloud Shell 运行此脚本,所有命令默认在当前所在目录的默认订阅中执行。若有多个订阅,需要手动指定订阅。查询所有目录下的所有订阅:

  1. <font color="#2e8b57">az account list --output table</font>
复制代码

切换到你要使用的订阅:

  1. <font color="#2e8b57">az account set --subscription "订阅 ID"</font>
复制代码

然后再运行脚本。

不是这三种订阅?你可以任意修改25-63行的值。


此脚本是其他作者所写,本站只是学习相关脚本技术而已,请大家遵守国家的法律法规。






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册 手机动态码快速登录

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 手机动态码快速登录

本版积分规则

快速回复 返回顶部 返回列表