主页
avatar

Kared

告别训练中断:Linux 模型训练会话持久化方案

在深度学习模型训练过程中,训练任务通常需要持续数小时甚至数天。在 Linux 服务器环境下,网络中断、SSH 连接断开等问题经常导致训练进程异常终止,造成计算资源和时间的浪费。

为了解决这个问题,Linux 提供了多种会话管理解决方案,可以让训练任务在后台持续运行。本文将简单介绍四种主流的 Linux 会话管理工具的使用:ScreenTmuxNohupSystemd

1、Screen

Screen 是一个经典的终端复用工具,允许在单个终端中创建多个会话和窗口,程序可以在后台持续运行即使断开连接,特别适合长时间运行的任务如机器学习训练。

基本会话管理

# 创建命名会话
screen -S <会话名>
screen -S llm_train   # 创建名为 llm_train 的会话

# 列出所有 screen 会话
screen -ls      # 显示所有会话及其状态
screen -list    # 同上,完整形式

# 重新连接到会话
screen -r llm_train   # 连接到指定会话
screen -r 123456      # 也可以用进程 ID 连接

# 强制连接到会话(即使已被连接)
screen -d -r llm_train    # 先分离再连接
screen -D -r llm_train    # 强制分离其他连接,然后连接

# 共享会话(多人同时查看)
screen -x llm_train       # 共享连接,多个用户可同时查看

# 创建会话并立即分离(后台创建)
screen -dmS llm_train     # 创建会话但不进入

# 杀死指定会话
screen -S llm_train -X quit # 或者在会话内输入 exit

# 向会话发送命令
screen -S llm_train -X stuff "python train.py\n"

窗口和面板操作

Ctrl+a d    # 分离当前会话(detach)
Ctrl+a c    # 创建新窗口
Ctrl+a n    # 切换到下一个窗口
Ctrl+a p    # 切换到上一个窗口
Ctrl+a "    # 显示窗口列表
Ctrl+a A    # 重命名当前窗口

2、Tmux

Tmux(Terminal Multiplexer)是 Screen 的现代化替代品,功能更加强大,支持更灵活的窗格分割、会话管理和自定义配置,是目前最流行的终端多任务管理工具。

基本会话管理

# 创建新会话
tmux new -s llm_train
tmux new-session -d -s llm_train

# 查看会话列表
tmux ls
tmux list-sessions

# 连接会话
tmux a -t llm_train
tmux attach-session -t llm_train

# 重命名会话
tmux rename-session -t old_name new_name

# 创建带有预定义布局的会话
tmux new-session -d -s llm_train
tmux split-window -h
tmux split-window -v
tmux attach-session -t llm_train

# 发送命令到指定会话
tmux send-keys -t llm_train:0 'cd /project && python train.py' Enter

# 捕获面板内容到文件
tmux capture-pane -t llm_train:0 -p > llm_training_log.txt

实际应用示例

# 创建一个多面板的深度学习训练环境
tmux new-session -d -s train

# 分割窗口:左侧训练,右上监控GPU,右下查看日志
tmux split-window -h
tmux split-window -v

# 在各个面板中执行不同命令
tmux send-keys -t train:0.0 'python train.py' Enter
tmux send-keys -t train:0.1 'watch -n 1 nvidia-smi' Enter
tmux send-keys -t train:0.2 'tail -f train.log' Enter

# 连接到会话
tmux attach-session -t train

窗口和面板操作

Ctrl+b d      # 分离会话
Ctrl+b c      # 创建新窗口
Ctrl+b ,      # 重命名当前窗口
Ctrl+b n      # 下一个窗口
Ctrl+b p      # 上一个窗口
Ctrl+b %      # 垂直分割面板
Ctrl+b "      # 水平分割面板
Ctrl+b o      # 切换面板
Ctrl+b x      # 关闭当前面板

配置文件示例

可以通过创建 ~/.tmux.conf 文件来自定义 Tmux 的行为和外观。以下是一个示例配置文件:

# 设置前缀键为 Ctrl+a(类似Screen)
set -g prefix C-a
unbind C-b

# 启用鼠标支持
set -g mouse on

# 设置历史缓冲区大小
set -g history-limit 10000

# 快速重载配置文件
bind r source-file ~/.tmux.conf \; display "Config reloaded!"

# 状态栏配置
set -g status-bg blue
set -g status-fg white

3、Nohup

Nohup(no hang up)是一个简单而强大的命令行工具,允许进程在用户退出终端后继续运行,通过忽略 SIGHUP 信号来实现进程的持久化运行。

基本使用方法

# 基本语法
nohup command &

# 启动训练脚本(输出默认重定向到 nohup.out)
nohup python train.py &

# 重定向输出到指定文件(推荐用法)
nohup python train.py > train.log 2>&1 &

# 同时启动多个训练任务
nohup python train_model1.py > model1.log 2>&1 &
nohup python train_model2.py > model2.log 2>&1 &
nohup python train_model3.py > model3.log 2>&1 &

# 批量启动(使用循环)
for i in {1..5}; do
    nohup python train_fold_$i.py > fold_$i.log 2>&1 &
done

# 设置进程优先级
nohup nice -n 10 python train.py > train.log 2>&1 &

# 避免产生默认的 nohup.out 文件
nohup python train.py > /dev/null 2>&1 &

进程管理和监控

# 查看当前shell的后台任务
jobs

# 查看所有python相关进程
ps aux | grep python

# 查找特定训练进程
ps aux | grep train.py
pgrep -f train.py          # 只显示进程ID
pgrep -fl train.py         # 显示进程ID和命令

# 查看进程详细信息
ps -ef | grep python

# 实时查看输出日志
tail -f train.log

# 查看日志最后几行
tail -n 50 train.log

# 搜索日志中的关键信息
grep -i "error" train.log
grep -i "epoch" train.log

# 同时监控多个日志文件
tail -f model1.log model2.log model3.log

进程终止和清理

# 根据进程名停止后台任务
kill $(pgrep -f train.py)

# 停止所有包含特定关键词的进程
pkill -f train.py

# 强制终止进程(使用PID)
kill -9 PID

# 强制终止进程(使用进程名)
pkill -9 -f train.py

# 检查进程是否还在运行
if pgrep -f train.py > /dev/null; then
    echo "训练进程正在运行"
else
    echo "训练进程已停止"
fi

# 清空过大的日志文件
> nohup.out
> train.log

实用脚本示例

# 启动训练并记录启动信息
start_training() {
    echo "开始训练: $(date)" >> train.log
    nohup python train.py >> train.log 2>&1 &
    echo "训练进程PID: $!" >> train.log
}

# 检查训练状态
check_training() {
    if pgrep -f train.py > /dev/null; then
        echo "训练正在进行中..."
        echo "最新日志:"
        tail -n 5 train.log
    else
        echo "训练已完成或停止"
    fi
}

# 优雅停止训练
stop_training() {
    PID=$(pgrep -f train.py)
    if [ -n "$PID" ]; then
        echo "正在停止训练进程 $PID..."
        kill -TERM $PID
        sleep 5
        if pgrep -f train.py > /dev/null; then
            echo "强制停止进程..."
            kill -9 $PID
        fi
        echo "训练已停止"
    else
        echo "未找到训练进程"
    fi
}

4、Systemd

Systemd 是现代 Linux 系统的系统和服务管理器,它不仅可以管理系统启动过程,还可以作为强大的进程管理工具来运行和监控长时间任务。

基本服务管理

# 查看所有服务状态
systemctl list-units --type=service
systemctl status                    # 系统整体状态

# 查看特定服务状态
systemctl status llm-training
systemctl is-active llm-training    # 检查服务是否运行
systemctl is-enabled llm-training   # 检查服务是否开机启动

# 启动、停止、重启服务
systemctl start llm-training
systemctl stop llm-training
systemctl restart llm-training
systemctl reload llm-training       # 重载配置(如果服务支持)

# 启用、禁用开机自启动
systemctl enable llm-training
systemctl disable llm-training

# 查看服务日志
journalctl -u llm-training
journalctl -u llm-training -f       # 实时跟踪日志
journalctl -u llm-training --since "1 hour ago"

创建自定义服务

创建服务文件 /etc/systemd/system/llm-training.service

[Unit]
Description=LLM Training Service
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=mluser
Group=mluser
WorkingDirectory=/home/mluser/project
Environment=CUDA_VISIBLE_DEVICES=0,1
ExecStart=/usr/bin/python3 /home/mluser/project/train.py
ExecStop=/bin/kill -SIGTERM $MAINPID
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

# 资源限制
LimitNOFILE=65536
MemoryMax=32G
CPUQuota=400%

[Install]
WantedBy=multi-user.target

高级服务配置

# 重载 systemd 配置
systemctl daemon-reload

# 创建用户级服务(运行在用户会话中)
mkdir -p ~/.config/systemd/user
# 将服务文件放在 ~/.config/systemd/user/ 目录
systemctl --user daemon-reload
systemctl --user start llm-training
systemctl --user enable llm-training

# 设置服务依赖关系
# 在服务文件中添加:
# After=gpu-driver.service
# Requires=database.service

实际应用示例

创建一个完整的深度学习训练服务:

# /etc/systemd/system/distributed-training.service
[Unit]
Description=Distributed Deep Learning Training
After=network.target docker.service
Requires=docker.service

[Service]
Type=forking
User=root
WorkingDirectory=/opt/ml-training
ExecStartPre=/usr/bin/docker pull pytorch/pytorch:latest
ExecStart=/usr/bin/docker run -d \
    --name training-container \
    --gpus all \
    -v /opt/ml-training:/workspace \
    -v /data:/data:ro \
    pytorch/pytorch:latest \
    python /workspace/distributed_train.py
ExecStop=/usr/bin/docker stop training-container
ExecStopPost=/usr/bin/docker rm training-container
Restart=on-failure
RestartSec=30
TimeoutStartSec=300

# 环境变量
Environment=NCCL_DEBUG=INFO
Environment=MASTER_ADDR=localhost
Environment=MASTER_PORT=12355

# 安全和资源限制
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/ml-training /tmp
MemoryMax=64G

[Install]
WantedBy=multi-user.target

服务监控和调试

# 查看服务运行时间和资源使用
systemctl show llm-training --property=ActiveState,SubState,ExecMainPID
systemctl show llm-training --property=MemoryCurrent,CPUUsageNSec

# 检查服务配置
systemctl cat llm-training
systemctl show llm-training

# 分析服务启动时间
systemd-analyze blame
systemd-analyze critical-chain llm-training.service

# 监控系统资源
systemctl status
systemd-cgtop    # 类似 htop,显示 cgroup 资源使用情况

定时任务和依赖管理

# 创建定时器(替代 cron)
# /etc/systemd/system/model-backup.timer
[Unit]
Description=Model Backup Timer
Requires=model-backup.service

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

# 启用定时器
systemctl enable model-backup.timer
systemctl start model-backup.timer
systemctl list-timers    # 查看所有定时器

日志管理

# 配置日志大小和保留时间
# 编辑 /etc/systemd/journald.conf
SystemMaxUse=1G
MaxRetentionSec=1month

# 查看和管理日志
journalctl --disk-usage           # 查看日志占用空间
journalctl --vacuum-time=2weeks   # 删除2周前的日志
journalctl --vacuum-size=100M     # 限制日志大小到100MB

# 导出日志
journalctl -u llm-training -o json > training.log

Systemd 相比 Screen 和 Tmux 的优势在于提供了系统级的进程管理、自动重启机制、资源控制、安全隔离和结构化日志记录,特别适合生产环境中的长时间运行任务和服务部署。

深度学习 Linux train 持久化