ms-swift定时任务:夜间自动执行训练计划
1. 为什么需要夜间自动训练?
你有没有遇到过这样的情况:白天要跑实验,GPU卡被占满,等晚上回家想继续训练,却发现忘记启动了?或者训练到一半突然断电,所有进度清零?又或者想让模型在空闲时段悄悄学习,第二天一早就能看到最新结果?
ms-swift本身不内置定时调度功能,但它提供了足够灵活的命令行接口和稳定可靠的训练机制,配合系统级定时工具(如cron),就能轻松实现“夜间自动执行训练计划”——就像给你的AI训练装上了一个智能闹钟。
这不是一个高深莫测的黑科技,而是一套简单、可靠、可复现的工程实践方案。本文将手把手带你搭建一套完整的夜间训练自动化流程,涵盖环境准备、脚本编写、错误防护、日志管理、结果通知等关键环节,让你从此告别手动值守,真正实现“提交即离开,醒来见成果”。
整个方案完全基于Linux系统原生能力,无需额外部署复杂调度平台,零学习成本,5分钟即可上线。
2. 核心思路:命令行 + 系统定时器 = 自动化训练
2.1 本质逻辑很朴素
ms-swift的所有训练、推理、导出操作,都通过swift命令完成。它本质上就是一个Python CLI工具,输入参数明确,输出日志规范,退出码语义清晰(0表示成功,非0表示失败)。这正是自动化调度最理想的接口形态。
我们只需要做三件事:
- 把训练命令写成一个可独立运行的Shell脚本
- 给这个脚本加上健壮的容错和状态检查
- 用系统cron在指定时间(比如凌晨2点)触发它
就这么简单。没有魔法,只有工程细节。
2.2 为什么选cron而不是其他方案?
- 轻量无依赖:Linux发行版默认自带,无需安装额外服务(如Airflow、Celery)
- 稳定可靠:运行数十年,是服务器运维的基石工具
- 精准可控:支持秒级精度(通过systemd timer可扩展)、可指定用户、可限制资源
- 调试友好:日志直接输出到文件,出问题一眼可见
当然,如果你用的是Kubernetes集群,也可以用CronJob;如果是Windows,可用任务计划程序。但本文聚焦最通用、最落地的Linux场景。
3. 实战:从零搭建夜间训练脚本
3.1 准备工作:确保ms-swift环境就绪
首先确认你的训练环境已配置完毕。以下命令应在任意终端中能正常执行:
# 检查ms-swift版本(确保≥1.10.0) swift --version # 测试基础命令是否可用 swift sft --help | head -n 5如果提示command not found,请先完成环境安装:
# 创建专用conda环境(推荐,避免污染主环境) conda create -n swift-nightly python=3.10 conda activate swift-nightly pip install 'ms-swift[all]' -U -i https://pypi.tuna.tsinghua.edu.cn/simple # 验证安装 swift --version小贴士:强烈建议为自动化任务创建独立环境。这样即使你日常开发升级了ms-swift,也不会影响夜间任务的稳定性。
3.2 编写核心训练脚本:nightly_sft.sh
下面是一个生产级可用的夜间训练脚本。它不是简单的一行命令,而是包含了路径安全检查、GPU占用检测、训练状态判断、失败重试、日志归档等实用功能。
请将以下内容保存为~/scripts/nightly_sft.sh(路径可自定义):
#!/bin/bash # ============================================= # ms-swift 夜间自动训练脚本 # 功能:每日凌晨2:30执行Qwen2.5-7B-Instruct的LoRA微调 # 作者:AI工程实践者 # 最后更新:2024-09-01 # ============================================= # --- 配置区(按需修改)--- MODEL_ID="Qwen/Qwen2.5-7B-Instruct" DATASET="AI-ModelScope/alpaca-gpt4-data-zh#500" OUTPUT_DIR="/data/train/nightly-qwen25" LOG_DIR="/data/log/nightly-sft" MAX_RETRY=3 RETRY_DELAY=60 # 秒 # --- 环境与路径检查 --- set -e # 任何命令失败立即退出 export PATH="/opt/conda/bin:$PATH" # 确保conda命令可用 source /opt/conda/etc/profile.d/conda.sh conda activate swift-nightly # 创建必要目录 mkdir -p "$OUTPUT_DIR" "$LOG_DIR" # 检查GPU是否空闲(避免与其他任务冲突) GPU_BUSY=$(nvidia-smi --query-compute-apps=pid --format=csv,noheader | wc -l) if [ "$GPU_BUSY" -gt 0 ]; then echo "[$(date)] GPU BUSY! $(nvidia-smi --query-compute-apps=pid,used_memory --format=csv) -> 退出本次训练" >> "$LOG_DIR/error.log" exit 1 fi # --- 训练主逻辑(带重试)--- ATTEMPT=1 while [ $ATTEMPT -le $MAX_RETRY ]; do echo "[$(date)] 开始第 $ATTEMPT 次训练尝试..." # 生成唯一时间戳用于日志和输出目录 TIMESTAMP=$(date +"%Y%m%d-%H%M%S") RUN_LOG="$LOG_DIR/sft_${TIMESTAMP}.log" RUN_OUTPUT="$OUTPUT_DIR/run_${TIMESTAMP}" # 执行ms-swift训练命令(精简版,仅保留关键参数) CUDA_VISIBLE_DEVICES=0 \ swift sft \ --model "$MODEL_ID" \ --dataset "$DATASET" \ --train_type lora \ --output_dir "$RUN_OUTPUT" \ --num_train_epochs 1 \ --per_device_train_batch_size 1 \ --learning_rate 1e-4 \ --lora_rank 8 \ --max_length 2048 \ --logging_steps 10 \ --save_steps 50 \ --eval_steps 50 \ --torch_dtype bfloat16 \ --seed 42 \ 2>&1 | tee "$RUN_LOG" # 检查训练是否成功(ms-swift成功结束会返回0) if [ $? -eq 0 ]; then echo "[$(date)] 训练成功!结果保存在: $RUN_OUTPUT" echo "[$(date)] 日志详见: $RUN_LOG" # 可选:发送成功通知(例如邮件或企业微信机器人) # curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx" \ # -H 'Content-Type: application/json' \ # -d '{"msgtype": "text", "text": {"content": " 夜间训练成功!\n模型: '$MODEL_ID'\n时间: '$TIMESTAMP'\n路径: '$RUN_OUTPUT'"}}' exit 0 else echo "[$(date)] 第 $ATTEMPT 次训练失败,等待 $RETRY_DELAY 秒后重试..." sleep $RETRY_DELAY ATTEMPT=$((ATTEMPT + 1)) fi done echo "[$(date)] 已达到最大重试次数($MAX_RETRY),训练失败。" >> "$LOG_DIR/error.log" exit 1脚本关键设计说明:
set -e:确保任一命令失败立即终止,防止错误累积nvidia-smi检测:避免与白天任务抢GPU,提升成功率- 时间戳命名:每次运行生成独立日志和输出目录,永不覆盖
- 重试机制:网络抖动、磁盘瞬时IO等问题可自动恢复
tee命令:同时输出到控制台和日志文件,便于调试
3.3 赋予执行权限并测试
# 添加执行权限 chmod +x ~/scripts/nightly_sft.sh # 手动运行一次,验证脚本是否能正常工作(注意:首次运行会下载模型,较慢) ~/scripts/nightly_sft.sh # 检查输出目录和日志 ls -lh /data/train/nightly-qwen25/ tail -n 20 /data/log/nightly-sft/sft_*.log如果看到类似Saving model checkpoint to ...和End time of running main的日志,说明脚本已就绪。
4. 配置系统定时器:让脚本准时开工
4.1 编辑当前用户的crontab
# 编辑定时任务列表 crontab -e在打开的编辑器中,添加以下一行:
# 每日凌晨2:30执行夜间训练 30 2 * * * /home/your_username/scripts/nightly_sft.sh >> /data/log/nightly-sft/cron.log 2>&1注意替换
your_username为你实际的用户名,并确保路径与你保存脚本的位置一致。
30 2 * * *的含义是:每月每天的2点30分执行。cron语法格式为:分 时 日 月 周。
4.2 验证cron是否生效
# 查看当前用户的定时任务 crontab -l # 查看cron服务状态(通常默认启用) sudo systemctl status cron # 手动触发一次(用于测试,不等待到2:30) # 注意:cron会以用户身份运行,所以环境变量可能不同,务必在脚本内显式激活conda4.3 关键:解决cron环境变量问题
这是新手最容易踩的坑!cron执行时不会加载你的.bashrc或.zshrc,因此conda、python路径、CUDA环境变量全都不生效。
正确解法已在脚本中体现:
- 在脚本开头显式
source /opt/conda/etc/profile.d/conda.sh - 显式
conda activate swift-nightly - 使用绝对路径调用
swift(或确保PATH已正确设置)
你也可以在crontab中直接设置环境变量:
# 在crontab顶部添加(推荐方式) SHELL=/bin/bash PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin HOME=/home/your_username 30 2 * * * /home/your_username/scripts/nightly_sft.sh >> /data/log/nightly-sft/cron.log 2>&15. 进阶:让夜间训练更聪明、更省心
5.1 智能跳过:只在有新数据时才训练
频繁训练同一份数据意义不大。我们可以加一层“数据新鲜度”检查:
# 在脚本中加入(放在nvidia-smi检查之后) DATA_SOURCE="/data/dataset/alpaca-zh" LAST_MODIFIED=$(stat -c "%y" "$DATA_SOURCE" 2>/dev/null | cut -d' ' -f1) TODAY=$(date +%Y-%m-%d) if [ "$LAST_MODIFIED" != "$TODAY" ]; then echo "[$(date)] 数据源 $DATA_SOURCE 今日未更新(最后修改:$LAST_MODIFIED),跳过训练" exit 0 fi这样,只有当天数据有更新,夜间任务才会启动。
5.2 结果自动归档与清理
避免日志和模型堆积如山。在脚本末尾添加:
# 训练成功后,自动清理7天前的日志 find "$LOG_DIR" -name "sft_*.log" -mtime +7 -delete 2>/dev/null find "$LOG_DIR" -name "error.log" -mtime +7 -delete 2>/dev/null # 只保留最近3次的成功训练结果(节省磁盘) ls -t "$OUTPUT_DIR"/run_* | tail -n +4 | xargs -r rm -rf5.3 失败自动告警
当训练连续失败3次,发消息提醒你介入:
# 在重试循环结束后添加 FAILED_COUNT=$(grep -c "训练失败" "$LOG_DIR/error.log" | tail -c +1) if [ "$FAILED_COUNT" -ge 3 ]; then echo " 严重警告:夜间训练已连续失败3次!请立即检查。" | mail -s "【AI训练告警】ms-swift夜间任务异常" your_email@example.com fi6. 效果验证与日常维护
6.1 如何确认任务真的在运行?
- 查看cron日志:
sudo tail -f /var/log/syslog | grep CRON - 查看你的日志目录:
ls -lt /data/log/nightly-sft/ - 检查进程:
ps aux | grep nightly_sft.sh
6.2 日常维护清单
| 项目 | 操作 | 频率 |
|---|---|---|
| 检查磁盘空间 | df -h /data | 每周 |
| 查看最近3次日志 | tail -n 50 /data/log/nightly-sft/sft_*.log | head -n 20 | 每日晨会 |
| 更新ms-swift | pip install 'ms-swift[all]' -U | 每月一次(升级前先备份旧环境) |
| 验证GPU健康 | nvidia-smi -q -d MEMORY,UTILIZATION | 每月 |
6.3 一个真实的运行日志片段
[2024-09-01 02:30:01] 开始第 1 次训练尝试... [2024-09-01 02:30:05] GPU BUSY! No running processes found -> 继续执行 [2024-09-01 02:30:10] Loading checkpoint shards: 100%|██████████| 4/4 [00:02<00:00, 1.82it/s] [2024-09-01 03:15:22] Saving model checkpoint to /data/train/nightly-qwen25/run_20240901-023001/checkpoint-873 [2024-09-01 03:15:25] End time of running main: 2024-09-01 03:15:25.123456 [2024-09-01 03:15:25] 训练成功!结果保存在: /data/train/nightly-qwen25/run_20240901-023001看到这样的日志,你就知道——你的AI,正在你熟睡时,默默进化。
7. 总结:自动化不是目的,而是释放创造力的起点
我们花了不到100行Shell脚本,就为ms-swift赋予了“夜间自主学习”的能力。这背后体现的,是一种典型的AI工程思维:
- 拥抱工具链:不重复造轮子,用好Linux+ms-swift这两个成熟、稳定的基石;
- 关注可观测性:每一步都有日志,每一次失败都有记录,让不确定性变得可追踪;
- 设计防御性逻辑:GPU检测、重试、超时、清理,让自动化真正可靠;
- 从手动到自动,只差一个脚本的距离。
这套方案可以轻松迁移到其他任务:
swift rlhf做夜间强化学习对齐swift eval定期评测模型性能衰减swift export自动量化并导出最新模型
当你把重复性劳动交给机器,你的时间,才能真正投入到更有价值的地方——比如思考下一个创新点子,或者,安心睡个好觉。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。