当前位置: 首页 > news >正文

基于 GPUTasker 的 GPU 使用情况钉钉推送机器人实现

引言

https://github.com/cnstark/gputasker

随着 AI 模型的广泛应用,GPU 成为团队中最重要的资源之一。然而,如何实时监控 GPU 的使用情况并及时通知团队是一个值得关注的问题。为了更好地管理显卡资源,本文基于 GPUTasker,实现了一个定期向钉钉群推送显卡使用情况的机器人。

我们通过钉钉自定义机器人 API 和 GPU 监控工具,结合 Python 脚本实现了以下功能:

  1. 根据设定的 工作时间节假日规则,控制消息推送;
  2. 按指定时间间隔发送 GPU 的利用率、显存使用量以及正在使用显卡的用户信息;
  3. 自动跳过节假日和非工作时间,减少不必要的推送。

实现步骤

1. 获取钉钉机器人 Token 和 Secret

在钉钉群中创建一个自定义机器人,获取 Token 和 Secret。具体步骤如下:

  1. 登录钉钉 Web 端:
    打开 钉钉开放平台 或在钉钉桌面端打开需要管理的工作群。
  2. 添加机器人:
    • 点击群设置 -> 智能群助手 -> 添加机器人;
    • 选择 自定义机器人,并设置一个名称(如:GPU 使用监控机器人);
    • 配置机器人安全设置,选择 自定义关键词签名校验
  3. 记录 Token 和 Secret:
    • 添加完成后,系统会生成一个 Token;
    • 如果选择了签名校验,还会生成一个 Secret;
    • 这两个字段将在脚本中用于身份验证。

2. Messenger 类的实现

Messenger 类是整个系统的核心,负责构建和发送消息到钉钉群。以下是该类的详细实现及功能介绍。

2.1 文件路径

在项目中,新建以下文件路径:

dingding/dingding.py

将 Messenger 类的代码放入 dingding.py 文件中,供其他模块调用。

2.2 核心功能

以下是 Messenger 类的关键功能:

  1. 节假日跳过
    使用 chinese_calendar 库判断当前日期是否为中国法定节假日。如果是节假日,机器人将自动跳过消息推送。
  2. 工作时间设置
    支持自定义工作时间段(如上午 8:20 到 11:50,下午 13:10 到 17:30),并在非工作时间内停止推送消息。
  3. 固定时间间隔推送
    支持设置推送间隔时间(如每 30 分钟推送一次),避免频繁发送消息。
  4. 显卡使用信息格式化
    将显卡使用情况转化为 Markdown 格式,方便在钉钉群中以表格形式展示。

以下是 Messenger 类的完整代码:

import os
import time
import hmac
import json
import base64
import hashlib
import requests
import chinese_calendar as calendar
from urllib.parse import quote_plus
from datetime import datetimeclass Messenger:def __init__(self, token=os.getenv("DD_ACCESS_TOKEN"), secret=os.getenv("DD_SECRET")):"""初始化方法@param token: str, 钉钉机器人访问令牌@param secret: str, 钉钉机器人密钥"""self.token = tokenself.secret = secretself.URL = "https://oapi.dingtalk.com/robot/send"self.headers = {'Content-Type': 'application/json'}self.params = {'access_token': self.token}self.update_timestamp_and_sign()# GPU 参数self.total_memory_GB = 24self.utilization_thred = 0.6self.memory_used_thred = 0.5# 时间控制参数self.time_range = [('08:20', '11:50'), ('13:10', '17:30')]self.last_true_time = {}self.time_interval = 30  # 间隔30分钟推送一次def send_md(self, message_json, server_ip):"""发送 Markdown 格式的消息到钉钉。"""self.update_timestamp_and_sign()if self.should_call_function_during_chinese_workdays(server_ip):if not message_json:text = f"**服务器IP**: `{server_ip}`\n**状态**: **连接失败**"self.send_markdown_to_dingtalk("服务器连接失败", text)else:content, is_free = self.format_gpu_usage_to_markdown(message_json, server_ip)if is_free:self.send_markdown_to_dingtalk("显卡使用情况", content)def update_timestamp_and_sign(self):"""更新时间戳和签名。"""self.timestamp = str(round(time.time() * 1000))secret_enc = self.secret.encode('utf-8')string_to_sign = '{}\n{}'.format(self.timestamp, self.secret)string_to_sign_enc = string_to_sign.encode('utf-8')hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()self.sign = quote_plus(base64.b64encode(hmac_code))self.params['timestamp'] = self.timestampself.params['sign'] = self.signdef send_markdown_to_dingtalk(self, title, text):"""构建并通过钉钉发送 Markdown 消息。"""data = {"msgtype": "markdown","markdown": {"title": title,"text": text}}try:requests.post(url=self.URL, data=json.dumps(data), params=self.params, headers=self.headers)except Exception as e:print(f"发生错误: {e}")def format_gpu_usage_to_markdown(self, message_json, server_ip):"""格式化 GPU 使用信息为 Markdown 文本。"""rows = []rows.append(f"**{server_ip}**")rows.append("")rows.append("| ID | GPU利用率 | 显存使用量 | 用户 |")rows.append("|:-------:|:------------:|:----------------:|:------:|")is_any_free = Falsefor gpu in message_json:index = gpu['index']utilization = gpu['utilization.gpu']memory_used_MB = gpu['memory.used']memory_used_GB = memory_used_MB / 1024memory_percentage = (memory_used_MB / (self.total_memory_GB * 1024)) * 100users = [process['username'] for process in gpu['processes']]users_str = ', '.join(set(users)) if users else '-'is_free = utilization < 100 * self.utilization_thred and memory_used_MB < (self.total_memory_GB * 1024 * self.memory_used_thred)if is_free:is_any_free = Truerow = f"| <font color='green'>**{index}**</font> | <font color='green'>**{utilization}%**</font> | <font color='green'>**{memory_used_GB:.1f}GB ({memory_percentage:.0f}%)**</font> | <font color='green'>**{users_str}**</font> |"else:row = f"| {index} | {utilization}% | {memory_used_GB:.1f}GB ({memory_percentage:.0f}%) | {users_str} |"rows.append(row)return '\n'.join(rows), is_any_freedef should_call_function_during_chinese_workdays(self, server_ip):"""检查是否为中国工作日以及指定时间段。"""now = datetime.now()current_time = now.time()if not calendar.is_workday(now):return Falsein_any_time_range = Falsefor time_range in self.time_range:start_time = datetime.strptime(time_range[0], '%H:%M').time()end_time = datetime.strptime(time_range[1], '%H:%M').time()if start_time <= end_time:in_time_range = start_time <= current_time <= end_timeelse:in_time_range = start_time <= current_time or current_time <= end_timeif in_time_range:in_any_time_range = Truebreakif in_any_time_range:last_time = self.last_true_time.get(server_ip)if last_time is None or (now - last_time).total_seconds() >= self.time_interval * 60:self.last_true_time[server_ip] = nowreturn Truereturn False# 实例化类
messager = Messenger(token="xxxxxx",secret="xxxxxx")

2.3 调用 Messenger 类

将以下代码加入 gputasker/gpu_info/utils.py 中,通过 try 捕获异常并调用钉钉推送功能:

from dingding.dingding import messagerclass GPUInfoUpdater:def update_gpu_info(self):server_list = GPUServer.objects.all()for server in server_list:try:gpu_info_json = get_gpu_status(server.ip, self.user, server.port, self.private_key_path)except:gpu_info_json = Nonefinally:messager.send_md(gpu_info_json, server.ip)

3. 效果展示

以下是钉钉群中接收到的 GPU 使用情况推送示例:

**172.20.3.27**
| ID | GPU利用率 | 显存使用量 | 用户 |
|:-------:|:------------:|:----------------:|:------:|
| 0 | 0%  | 12.7GB (53%) | root|
| 1 | 87% | 16.7GB (70%) | root|
| 2 | 92% | 14.2GB (59%) | root|
| 3 | 87% | 14.2GB (59%) | root|
| 4 | 86% | 14.2GB (59%) | root|
| 5 | 83% | 14.2GB (59%) | root|
| 6 | 86% | 17.0GB (71%) | root|
| 7 | 0%  | 2.1GB (9%)   | root|

总结

通过本文的实现,可以将 GPU 使用情况实时推送到钉钉群,方便团队成员及时了解资源状态,提高显卡的利用效率。

相关文章:

基于 GPUTasker 的 GPU 使用情况钉钉推送机器人实现

引言 https://github.com/cnstark/gputasker 随着 AI 模型的广泛应用&#xff0c;GPU 成为团队中最重要的资源之一。然而&#xff0c;如何实时监控 GPU 的使用情况并及时通知团队是一个值得关注的问题。为了更好地管理显卡资源&#xff0c;本文基于 GPUTasker&#xff0c;实现了…...

Python自学 - 函数初步(内置函数、模块函数、自定义函数)

1 Python自学 - 函数初步(内置函数、模块函数、自定义函数) 1.1 内置函数 几乎所有的编程都会提供一些内置函数&#xff0c;以便完成一些最基本的任务&#xff0c;Python提供了丰富的内置函数&#xff0c;熟悉内置函数可以给工作带来极大便利。   Python官方的内置函数介绍网…...

【生活】冬天如何选口罩(医用口罩,N95, KN95还是KP95?带不带呼吸阀门?带不带活性炭?)

&#x1f4a1;总结一下就是&#xff1a; 日常防护的话&#xff0c;医用口罩就可以啦。要是想长时间佩戴N95&#xff08;KN95&#xff09;口罩的话也可以. 在高风险环境&#xff08;像医院、疫情防控期间&#xff09;&#xff0c;一定要选不带呼吸阀门的N95口罩KN95&#xff09…...

HTML5新特性|01 音频视频

音频 1、Audio (音频) HTML5提供了播放音频文件的标准 2、control(控制器) control 属性供添加播放、暂停和音量控件 3、标签: <audio> 定义声音 <source> 规定多媒体资源,可以是多个<!DOCTYPE html> <html lang"en"> <head><…...

迅为RK3568开发板编译Android12源码包-设置屏幕配置

在源码编译之前首先要确定自己想要使用的屏幕并修改源码&#xff0c;在编译镜像&#xff0c;烧写镜像。如下图所示&#xff1a; 第一步&#xff1a;确定要使用的屏幕种类&#xff0c;屏幕种类选择如下所示&#xff1a; iTOP-3568 开发板支持以下种类屏幕&#xff1a; 迅为 LV…...

力扣hot100——图论

200. 岛屿数量 class Solution { public:int numIslands(vector<vector<char>>& grid) {int ans 0;vector<int> dx { 0, 1, 0, -1 };vector<int> dy { 1, 0, -1, 0 };int n grid.size(), m grid[0].size();vector<vector<int>> …...

Docker- Unable to find image “hello-world“locally

Docker- Unable to find image “hello-world“locally 文章目录 Docker- Unable to find image “hello-world“locally问题描述一. 切换镜像1. 编辑镜像源2. 切换镜像内容 二、 检查设置1、 重启dockers2、 检查配置是否生效3. Docker镜像源检查4. Dokcer执行测试 三、自定义…...

spring-boot启动源码分析(二)之SpringApplicationRunListener

在上一篇《spring-boot启动源码分析&#xff08;一&#xff09;之SpringApplication实例构造》后&#xff0c;继续看了一个月的Spring boot启动源码&#xff0c;初步把流程看完了&#xff0c;接下来会不断输出总结&#xff0c;以巩固这段时间的学习。同时也希望能帮到同样感兴趣…...

ELK入门教程(超详细)

什么是ELK&#xff1f; ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称(后来出现的filebeat属于beats家族中的一员&#xff0c;可以用来替代logstash的数据收集功能&#xff0c;比较轻量级)&#xff0c;也被称为Elastic Stack。 Filebeat Filebeat是用于转…...

人工智能知识分享第六天-机器学习_​逻辑回归(Logistic Regression)

简介 在机器学习中&#xff0c;分类问题是一种常见的任务&#xff0c;目标是根据输入特征将数据点分配到不同的类别中。为了实现分类&#xff0c;我们需要训练一个分类器&#xff0c;该分类器能够根据输入数据的特征进行预测。 逻辑回归&#xff08;Logistic Regression&…...

基于Springboot + vue实现的校园周边美食探索及分享平台

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…...

初学STM32 --- 外部SRAM

目录 SRAM简介 SRAM特性: XM8A51216 功能框图 8080并口读时序​编辑 8080并口写时序 SRAM 读写操作步骤 FSMC介绍 FSMC时序介绍 FSMC控制器对内核地址映射​编辑 FSMC HAL库相关驱动 SRAM驱动步骤 SRAM简介 静态随机存取存储器&#xff08;Static Random-Access Memory&am…...

创龙3588——debian根文件系统制作

文章目录 build.sh debian 执行流程build.sh源码流程 30-rootfs.sh源码流程 mk-rootfs-bullseys.sh源码流程 mk-sysroot.sh源码流程 mk-image.sh源码流程 post-build.sh 大致流程系统制作步骤 build.sh debian 执行流程 build.sh 源码 run_hooks() {DIR"$1"shiftf…...

javacript中function (res) {}与箭头函数表达式(res) =>{}的区别

javacript中function (res) {}与(res) &#xff1e;{}的区别 function (res) {} 代码演示 let shape {name:长方形,say:function(){console.log(我是this.name)setTimeout(function(){console.log(3秒后输出我是: this.name); //this.name为undefined}, 3000)} }shape.sa…...

kylin安装docker

1. 前言 本文详细介绍如何在kylin v10上安装docker。系统环境如下&#xff1a; dockder: 20.10.7 linux os: kylinv 10 (GFB) linux kernel: 4.19.90-52.23.v2207.gfb01.ky10.aarch642. 安装docker 2.1. 下载docker二进制包 wget https://mirror.nju.edu.cn…...

【Yarn】通过JMX采集yarn相关指标的Flink任务核心逻辑

通过JMX采集yarn相关指标的Flink任务核心逻辑 文章目录 通过JMX采集yarn相关指标的Flink任务核心逻辑通过jmx接口查询Yarn队列指标请求JMX配置项核心处理流程输出到kafka格式通过jmx接口查询ResourceManager核心指标请求JMX读取配置yaml配置文件核心处理逻辑输出Kafka格式彩蛋 …...

鸿蒙HarmonyOS开发:基于Swiper组件和自定义指示器实现多图片进度条轮播功能

文章目录 一、概述1、场景介绍2、技术选型 二、实现方案1、图片区域实现2、底部导航点设计3、手动切换 三、所有代码1、设置沉浸式2、外层Tabs效果3、ImageSwiper组件 四、效果展示 一、概述 在短视频平台上&#xff0c;经常可以见到多图片合集。它的特点是&#xff1a;由多张…...

Excel 身份证号计算年龄

1. 设置身份证号列格式 复制身份证列值到记事本或其他地方重新设置身份证号列单元格格式为“文本”将复制出去的身份证号重新复制粘贴回来 2. 年龄列单元格中添加公式 DATEDIF(DATE(LEFT(MID(A2, 7, 8), 4), MID(MID(A2, 7, 8), 5, 2), RIGHT(MID(A2, 7, 8), 2)), TODAY(), …...

【2024年-6月-14日-开源社区openEuler实践记录】探索 test - tools:高效测试的开源宝库

开篇引言 大家好&#xff0c;我是 fzr123&#xff0c;在软件开发领域深耕多年&#xff0c;一直致力于探索各种提升效率的工具与技术。今天&#xff0c;我将为大家深入介绍一款在测试领域极具价值的开源项目——test - tools&#xff0c;它为开发者们提供了一系列强大的测试功能…...

2022浙江大学信号与系统笔记

原视频地址&#xff1a;2022浙江大学信号与系统&#xff08;含配套课件和代码&#xff09; - 胡浩基老师-哔哩哔哩 ⭐⭐⭐ 我的笔记&#xff1a;飞书链接 - 信号与系统 基于视频&#xff0c;记得笔记&#xff0c;加了点自己的补充&#xff08;有的是问 ChatGPT 的&#xff09;…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前&#xff0c;首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例&#xff0c;用_OBJECT_TYPE这个结构来解析它&#xff0c;0x80处就是今天要介绍的回调链表&#xff0c;但是先不着急&#xff0c;先把目光…...

node.js的初步学习

那什么是node.js呢&#xff1f; 和JavaScript又是什么关系呢&#xff1f; node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说&#xff0c; 需要在node.js的环境上进行当JavaScript作为前端开发语言来说&#xff0c;需要在浏览器的环境上进行 Node.js 可…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

【Java多线程从青铜到王者】单例设计模式(八)

wait和sleep的区别 我们的wait也是提供了一个还有超时时间的版本&#xff0c;sleep也是可以指定时间的&#xff0c;也就是说时间一到就会解除阻塞&#xff0c;继续执行 wait和sleep都能被提前唤醒(虽然时间还没有到也可以提前唤醒)&#xff0c;wait能被notify提前唤醒&#xf…...

RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上

一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema&#xff0c;不需要复杂的查询&#xff0c;只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 &#xff1a;在几秒钟…...

HTML中各种标签的作用

一、HTML文件主要标签结构及说明 1. <&#xff01;DOCTYPE html> 作用&#xff1a;声明文档类型&#xff0c;告知浏览器这是 HTML5 文档。 必须&#xff1a;是。 2. <html lang“zh”>. </html> 作用&#xff1a;包裹整个网页内容&#xff0c;lang"z…...