通过IDRAC依据显卡温度控制服务器风扇转速的方案

前言

之前搞了一台DELL R730的服务器,自从给这台机器插上一张NVIDIA的显卡,机器上面的风扇在开机的时候以及运行的时候转的跟飞机起飞一样的,长此以往听这噪音耳朵迟早要废掉。我研究了一下发现是插上显卡后系统默认风扇转速较高,所以,要解决这个问题,我决定搞一个程序,手动来控制服务器的风扇转速

在此感谢 “萌新” 大佬的帮助。

读取显卡温度

要依照显卡温度来控制服务器的风扇转速,我们首先要获取到服务器的显卡的温度。

我这个服务器上面插的是一张NVIDIA的K80显卡,当我们正常安装好驱动之后,我们可以通过nvidia-smi这个命令来读取到显卡的温度

但是一次输出这么多,我们只需要温度数据,所以我们加上一个参数

 nvidia-smi --query-gpu=index,name,temperature.gpu --format=csv,noheader

输出的内容就是下面这个样子了,更方便进行程序的解析了

控制风扇转速

获取到了显卡的温度,那么我们先来着手控制风扇的转速

首先我们先要找到IDRAC的界面(本文不负责细讲如何启用IDRAC,想要了解请点此

进入这个控制系统之后我们依次点击左侧的>IDRAC设置>网络>IPMI设置(如下图)

勾上启用LAN上的IPMI,点击应用保存修改

接下来在系统中安装IPMITOOLS(UBUNTU下直接apt-get install ipmitool即可)

接下来执行下面的命令

ipmitool -I lanplus -H ipaddress username -P password raw 0x30 0x30 0x01

其中ipaddress 是你的IDRAC的地址USERNAME 和PASSWORD是你的IDRAC账号以及密码,上面的这串命令的含义是关闭自动风扇调节。

接下来下面的命令就是用来手动调节风扇转速的

ipmitool -I lanplus -H ipaddress -U username -P password raw 0x30 0x30 0x02 0xff hex(speed)

其中hex(speed),speed代表风扇转速的百分比(1-100),hex代表取十六进制,即hex(speed)处应该替换为风扇转速百分比的十六进制值。

警告:手动调节风扇转速并且风扇转速过低,导致无法机器及时散出热量的话会导致服务器硬件过热最后烧毁!!!!!!

写出控制程序代码

了解完上面之后,“萌新”大佬就用PYTHON写出来一个依据显卡温度来进行风扇调节的小程序。

下面代码可能不是最新的,假如要最新的请前往https://gitlab.q2019.com/q2019715/idracontrol/-/tree/python_edition?ref_type=heads地址获取

import subprocess
from datetime import datetime
import pytz
import time
import csv
import io
import os
import threading

'''
设置服务器irdc的账户,ip地址
'''
username = 'q2019'
password = '123456'
ipaddress = '192.168.1.131'

'''
设置白天和黑夜时间段
'''
lightstart=6
lightend=23


'''
设置是否为手动控制
'''
isautomatic=True

#获取GPU所有信息命令
def getGPUAllinfo():
    result = subprocess.run(['nvidia-smi'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
    if result.returncode ==0:
        print("输出结果为: ")
        print(result.stdout)
    else:
        print("获取GPU信息失败")
        print(result.stderr)


#获取所有GPU温度信息
def getGPUtempinfo():
    result = subprocess.run(['nvidia-smi' ,'--query-gpu=index,name,temperature.gpu','--format=csv,noheader'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
    if result.returncode == 0:
        print("输出结果为: ")
        print(result.stdout)
        reader= csv.reader(io.StringIO(result.stdout))
        sum=0
        for row in reader:
            if len(row) == 3:
                index = row[0].strip()
                name = row[1].strip()
                temp = int(row[2].strip())
                sum+=temp
        if sum>0:
            return sum/2

    else:
        print("获取GPU信息失败")
        print(result.stderr)
        return 0

#获取ESXI硬件信息
def getESXIsdrinfo():
    result = subprocess.run(['ipmitool','-I','lanplus','-H',ipaddress,'-U',username,'-P',password,'sdr','list','full'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
    if result.returncode == 0:
        print("输出结果为: ")
        print(result.stdout)
    else:
        print("获取CPU信息失败")
        print(result.stderr)

#设置全部风扇速率
def setFen(speed):
    if speed>=100 or speed <=10:
        print("非法操作风扇")
    else:
        #subprocess.run(['ipmitool','-I','lanplus','-H',ipaddress,'-U',username,'-P',password,'raw' ,'0x30','0x30', '0x01', '0x00'])
        time.sleep(0.2)
        subprocess.run(['ipmitool','-I','lanplus','-H',ipaddress,'-U',username,'-P',password,'raw','0x30',' 0x30','0x02', '0xff',hex(speed)])


#启动动态调节ESXI风扇速率
def dynamicAdjustmentFen(stop_event):
    #获取当前时间
    '''
    针对白天时间段,适当根据显卡温度调节风扇速率,防止风扇速率过高导致的吵闹
    针对黑夜时间段,可以全力释放风扇的性能
    '''
    while not stop_event.is_set():
        os.system('clear')
        timezone = pytz.timezone('Asia/Shanghai')
        now = datetime.now(timezone)
        print("\n当前上海时间: ",now.strftime("%H"))
        tt=0
        if now.strftime("%H").isdigit():
            tt = int(now.strftime("%H"))
            #如果在白天
            if tt>=lightstart and tt<=lightend:
                temp=getGPUtempinfo()
                if temp!=0:
                    if temp>80:
                        setFen(50)
                    elif temp>70:
                        setFen(26)
                        #time.sleep(300)//直接暴力吹6分钟
                        #警告!上面这行代码会导致机器过热!!!!!!!!!!!!
                    else:
                        setFen(20)
            else:
                #如果在晚上
                #进行更激进的CPU散热
                temp=getGPUtempinfo()
                if temp!=0:             
                    if temp>85:
                        setFen(80)
                    elif temp>80:
                        setFen(70)
                    elif temp>70:
                        setFen(60)
                    elif temp>60:
                        setFen(50)
                    elif temp>50:
                        setFen(40)
                    else:
                        setFen(35)
        else:
            print("获取信息失败,请确保网络正确连接!")
        time.sleep(8)


#UI界面
def UI():
    os.system('clear')
    print("\r\n")
    print("*********欢迎使用温控自动化程序V0.2PY*********\n")
    print("输入wen -help or wen -h获取帮助\n")

#帮助
def Help():
    os.system('clear')
    print("\r\n")
    print("*********欢迎使用温控自动化程序*********\n")
    print("wen on启动自动调节 wen off 关闭自动调节")
    print("wen 百分比数字 设置风扇转速百分比 例如 wen 20")




if __name__ == '__main__':
    subprocess.run(['ipmitool','-I','lanplus','-H',ipaddress,'-U',username,'-P',password,'raw' ,'0x30','0x30', '0x01', '0x00'])
    os.system('clear')
    stop_event = None
    thread = None
    while True:
        os.system('clear')
        UI()
        user_input = input("请输入指令: ")
        user_input = user_input.strip()

        if not user_input:
            os.system('clear')
        args = user_input.split()

        if args[0] != 'wen':
            print("error code")

        if len(args)>1:
            command = args[1]
            if command == '-help' or command == '-h':
                Help()
                input()
            elif command=='on':
                if thread is None or not thread.is_alive():
                    stop_event= threading.Event()
                    thread = threading.Thread(target=dynamicAdjustmentFen,args=(stop_event,))
                    thread.start()
                else:
                    print("自动温度控制已启动")
            elif command == 'off':
                if thread is not None and thread.is_alive():
                    stop_event.set()
                    thread.join()
                else:
                    print("自动温度控制已关闭")
            elif command.isdigit():
                setFen(int(command))

这个程序可能有无法预料的缺陷!!!请仔细阅读完代码并评估风险后再使用,本人对此代码造成的问题概不负责!!!

使用方法:

1、首先修改代码,将自己的服务器的信息填入代码之中

2、安装好NVIDIA的显卡驱动(尤其是nvidia-smi组件)以及ipmitool组件

3、安装好python以及python依赖

4、执行命令:python3 代码文件名.py

5、输入wen on 指令开始自动化温度控制(以显卡温度为中心)

假如要退出自动控制程序,可以直接关闭程序(通过ctrl-c退出需要按两次,因为使用了多进程),或者在页面刷新之前输入wen off

在关闭自动控制的界面(请输入指令页面)输入wen+风扇转速百分比即可手动调节风扇,比如wen 99 代表直接将风扇转速升到99%,

感谢阅读

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,记得载明出处,(期待)。 内容有问题?请点此跟我反馈
上一篇
下一篇