本文介绍如何在DSW实例中使用OpenClaw实现GPU自动化监控,包括训练任务状态通知、异常智能识别、OOM自动恢复以及定时报告生成等功能。
背景介绍
在模型训练过程中,训练任务可能因各种原因(如CUDA内存溢出、显存不足、GPU利用率异常等)而中断或效率降低。通过配置OpenClaw,您可以实现对DSW实例中GPU状态的自动化监控,及时发现问题并自动处理,从而提高训练效率并节省人工成本。
完成本文档配置后,您的DSW实例将具备以下能力:
任务状态自动通知:训练任务完成或异常中断时,通过钉钉即时发送通知。
异常智能识别:自动检测GPU利用率骤降、Loss发散、内存溢出等异常情况。
故障自动干预:检测到OOM后自动调整参数并重启训练任务。
定时状态汇总:每日自动生成训练任务状态报告,便于掌控全局进度。
前提条件
已完成OpenClaw的基础部署,详细操作请参见在DSW中部署OpenClaw。
已配置钉钉通知渠道,确保OpenClaw能够正常发送钉钉消息,详细操作请参见通过钉钉访问OpenClaw(可选)。
建议将本文档中的脚本存放在DSW实例的
/mnt/workspace/目录下。
场景一:配置训练任务完成通知
应用场景
当您提交长时间运行的训练任务(例如需要数小时完成的微调任务)后,通常需要定期检查任务是否完成。通过配置OpenClaw任务完成通知,您可以在训练任务结束时自动接收钉钉消息,无需手动监控任务状态。
实现方法
在训练脚本末尾添加OpenClaw消息发送命令,使训练任务完成或失败时自动发送通知。
训练脚本基础示例
# 执行训练命令
python train.py --model qwen-7b --lr 2e-5 --epochs 3
# 训练结束后发送通知($?为训练脚本的退出码)
openclaw message send --channel dingtalk --target "user:<staffid>" -m "训练任务已结束,退出码:$?"注意请将
<staffid>替换为您真实的staffid,获取方式可直接在DSW的web UI中询问OpenClaw:请帮我查看staffid。退出码为0表示任务正常结束,非零值表示任务异常退出。
训练脚本增强示例(包含训练结果信息)
python train.py --model qwen-7b --lr 2e-5 --epochs 3
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
FINAL_LOSS=$(tail -n 5 train.log | grep -oP 'loss=\K[\d.]+' | tail -1)
openclaw message send --channel dingtalk --target "user:<staffid>" -m "训练完成!最终 loss:${FINAL_LOSS},请查看训练结果"
else
openclaw message send --channel dingtalk --target "user:<staffid>" -m "训练任务异常终止,退出码:${EXIT_CODE},请检查日志文件"
fi场景二:配置训练过程异常监控
应用场景
训练任务在执行过程中可能出现异常情况(如GPU利用率骤降、显存占用接近上限、温度异常等),这些异常往往预示着训练任务即将失败或效率降低。通过配置定时监控,OpenClaw可以在异常发生时及时发送告警,避免算力浪费。
实现方法
创建GPU监控脚本/mnt/workspace/gpu_monitor.py:
import subprocess
import sys
def get_gpu_stats():
"""获取GPU关键指标"""
result = subprocess.run(
['nvidia-smi', '--query-gpu=utilization.gpu,memory.used,memory.total,temperature.gpu',
'--format=csv,noheader,nounits'],
capture_output=True, text=True
)
stats = []
for i, line in enumerate(result.stdout.strip().split('\n')):
util, mem_used, mem_total, temp = [x.strip() for x in line.split(',')]
stats.append({
'gpu_id': i,
'utilization': int(util),
'memory_used': int(mem_used),
'memory_total': int(mem_total),
'memory_pct': round(int(mem_used) / int(mem_total) * 100, 1),
'temperature': int(temp)
})
return stats
def check_anomaly(stats):
"""检测异常,返回告警信息列表"""
alerts = []
for s in stats:
gid = s['gpu_id']
# GPU利用率过低(训练任务应保持高利用率)
if s['utilization'] < 20:
alerts.append(f"GPU {gid} 利用率仅 {s['utilization']}%,可能存在任务阻塞")
# 显存接近上限
if s['memory_pct'] > 90:
alerts.append(f"GPU {gid} 显存占用 {s['memory_pct']}%,存在OOM风险")
# 温度过高
if s['temperature'] > 85:
alerts.append(f"GPU {gid} 温度 {s['temperature']}°C,请注意散热")
return alerts
if __name__ == '__main__':
stats = get_gpu_stats()
alerts = check_anomaly(stats)
if alerts:
# 检测到异常,输出告警内容并返回非零退出码
for alert in alerts:
print(alert)
sys.exit(1)
else:
print("HEARTBEAT_OK")
sys.exit(0)配置OpenClaw定时监控任务:
openclaw cron add \
--name "GPU健康巡检" \
--cron "*/15 * * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--message "请执行 GPU 健康检查:
1. 运行命令:python /mnt/workspace/gpu_monitor.py
2. 如果输出 HEARTBEAT_OK,一切正常,不需要通知我
3. 如果检测到异常,请:
- 通过钉钉把完整的告警信息发给我
- 结合当前的训练进程状态,判断是否需要我介入
- 给出你的处理建议" \
--announce上述配置将每15分钟自动执行一次GPU健康检查,仅在检测到异常时发送钉钉通知。
验证定时任务
# 查看所有定时任务
openclaw cron list
# 手动触发测试(用实际的job_id替换<job_id>)
openclaw cron run <job_id>场景三:配置OOM自动恢复
应用场景
CUDA内存溢出(OOM)是模型训练中的常见问题。通过配置OOM自动恢复机制,OpenClaw可以在检测到OOM后自动调整训练参数(如降低batch_size)并重启训练任务,无需人工干预。
实现方法
创建训练配置文件/mnt/workspace/train_config.json:
{
"model": "qwen-7b",
"batch_size": 16,
"lr": 2e-5,
"epochs": 3,
"max_length": 512,
"oom_retry_count": 0
}创建OOM自动恢复脚本/mnt/workspace/auto_recover.py:
import json
import subprocess
import sys
from pathlib import Path
CONFIG_PATH = Path("/mnt/workspace/train_config.json")
LOG_PATH = Path("/mnt/workspace/train.log")
def load_config():
return json.loads(CONFIG_PATH.read_text())
def save_config(config):
CONFIG_PATH.write_text(json.dumps(config, indent=2))
def check_oom():
"""检查最近的日志中是否存在OOM错误"""
if not LOG_PATH.exists():
return False
recent_lines = LOG_PATH.read_text().split('\n')[-50:]
oom_keywords = ['CUDA out of memory', 'OutOfMemoryError', 'OOM']
return any(kw in line for line in recent_lines for kw in oom_keywords)
def recover():
config = load_config()
if config['oom_retry_count'] >= 3:
print(f"已自动重试 {config['oom_retry_count']} 次,batch_size 降至 {config['batch_size']},仍然出现OOM,需要人工介入")
sys.exit(2) # 退出码2表示需要人工处理
# 将batch_size减半
old_batch = config['batch_size']
config['batch_size'] = max(1, old_batch // 2)
config['oom_retry_count'] += 1
save_config(config)
print(f"检测到OOM,已将batch_size从 {old_batch} 调整为 {config['batch_size']}(第 {config['oom_retry_count']} 次自动恢复),正在重启训练任务...")
# 重启训练任务(后台运行)
subprocess.Popen([
'python', 'train.py',
'--batch_size', str(config['batch_size']),
'--lr', str(config['lr']),
'--epochs', str(config['epochs'])
], stdout=open(str(LOG_PATH), 'a'), stderr=subprocess.STDOUT)
sys.exit(0)
if __name__ == '__main__':
if check_oom():
recover()
else:
print("HEARTBEAT_OK")配置OpenClaw OOM监控任务:
openclaw cron add \
--name "OOM自愈守卫" \
--cron "*/5 * * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--message "执行 OOM 自愈检查:
1. 运行:python /mnt/workspace/auto_recover.py
2. 如果输出 HEARTBEAT_OK,不需要任何操作
3. 如果输出包含'已将 batch_size 调整',通过钉钉告诉我调整详情,并说明训练已自动重启
4. 如果退出码为 2(需要人工介入),立刻通过钉钉通知我,附上最后 20 行训练日志" \
--announce自动恢复工作流程
训练任务发生OOM。
OpenClaw在5分钟内检测到OOM错误。
自动将batch_size减半并重启训练任务。
通过钉钉发送处理结果通知。
如连续3次自动恢复失败,则通知用户人工介入。
场景四:配置每日训练报告
应用场景
通过配置每日训练报告,您可以在每天固定时间(如每日上午9点)自动接收DSW实例的全局状态汇总,包括当前运行的训练任务、GPU资源使用情况以及最近的实验结果,便于掌控整体训练进度。
实现方法
创建日报生成脚本/mnt/workspace/daily_report.py:
import subprocess
import json
from datetime import datetime, timedelta
from pathlib import Path
def get_running_jobs():
"""获取当前正在运行的训练进程"""
result = subprocess.run(['ps', 'aux'], capture_output=True, text=True)
jobs = [line for line in result.stdout.split('\n')
if 'train.py' in line or 'finetune.py' in line]
return jobs
def get_gpu_summary():
result = subprocess.run(
['nvidia-smi', '--query-gpu=index,name,utilization.gpu,memory.used,memory.total',
'--format=csv,noheader'],
capture_output=True, text=True
)
return result.stdout.strip()
def get_experiment_log_summary():
"""读取实验记录"""
log_path = Path("/mnt/workspace/experiment_log.md")
if not log_path.exists():
return "暂无实验记录"
# 返回最后30行
lines = log_path.read_text().split('\n')
return '\n'.join(lines[-30:])
if __name__ == '__main__':
now = datetime.now().strftime('%Y-%m-%d %H:%M')
running = get_running_jobs()
gpu = get_gpu_summary()
exp_log = get_experiment_log_summary()
report = f"""=== DSW 日报 {now} ===
【当前运行中的任务】
{chr(10).join(running) if running else '无正在运行的训练任务'}
【GPU 状态】
{gpu}
【最近实验记录】
{exp_log}
"""
print(report)配置OpenClaw每日报告任务:
openclaw cron add \
--name "每日训练日报" \
--cron "0 9 * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--message "生成今日 DSW 工作日报:
1. 运行:python /mnt/workspace/daily_report.py
2. 根据输出内容,生成一份简洁的日报,包括:
- 当前正在运行的任务简述
- GPU 资源使用情况
- 最近实验结果摘要(如有)
- 如发现任何异常,提醒我关注
3. 通过钉钉发送这份日报,格式友好易读" \
--announce任务管理
您可以同时配置并运行上述所有监控任务,它们相互独立且互不干扰。
监控任务汇总
任务名称 | 触发时机 | 功能说明 |
GPU健康巡检 | 每15分钟 | 监控GPU利用率、显存占用、温度等指标,异常时发送告警 |
OOM自愈守卫 | 每5分钟 | 检测OOM错误并自动调整参数重启训练 |
每日训练日报 | 每天9:00 | 汇总并推送当前任务状态、GPU使用情况、实验记录 |
训练结束通知 | 训练脚本结束时 | 任务完成或失败时即时通知 |
管理定时任务
# 查看所有定时任务
openclaw cron list
# 禁用某个任务(使用实际的job_id替换<job_id>)
openclaw cron disable <job_id>
# 重新启用任务
openclaw cron enable <job_id>常见问题
Q:未收到钉钉通知,如何排查?
# 检查OpenClaw服务状态
openclaw status
# 发送测试消息
openclaw message send -m "测试消息,如果收到此消息说明钉钉配置正常"Q:定时任务已触发但脚本未执行?
# 查看所有定时任务
openclaw cron list
# 查看指定任务的执行日志(使用实际的job_id替换<job_id>)
openclaw cron logs <job_id> --tail 20Q:如何批量禁用所有监控任务?
您可以使用以下命令批量禁用或启用所有定时任务(需安装jq工具):
# 批量禁用所有任务
openclaw cron list --json | jq -r '.[].id' | xargs -I {} openclaw cron disable {}
# 批量启用所有任务
openclaw cron list --json | jq -r '.[].id' | xargs -I {} openclaw cron enable {}或者,您可以直接告诉OpenClaw执行批量操作:
帮我把所有 cron 定时任务都禁用,周一早上 9 点再全部重新启用