断线,任务别死。

亲手切断 SSH。看 nohup、Screen 与 Tmux 如何面对同一个 SIGHUP。

选择生存方案
Remote process chamberTMUX / ATTACHED
SSH
PID 4821 / ALIVE

三种方法,保护的是三种工作方式。

nohup

最直接地忽略 SIGHUP。适合无需输入、只关心日志的单一任务,但 stdin 会被重定向到 /dev/null。

nohup python main.py > my_log.txt 2>&1 &
Screen

保留完整虚拟终端,稳定但操作较旧。查看历史需要进入 Copy mode,默认鼠标滚轮体验一般。

screen -S demo · Ctrl+a d · screen -r demo

Complete article

完整原文

文字、链接、图片、表格与代码均保留 开始阅读

背景

在 Linux 服务器上执行耗时任务(如模型训练、编译大项目、爬虫抓取)时,经常遇到 SSH 连接意外断开的情况。

一旦 SSH 会话结束,系统会向该会话下的所有子进程发送 SIGHUP (Signal Hang Up) 信号。默认情况下,进程收到该信号会立即终止,导致任务中断,数据丢失。

本文记录了三种常用的解决方案,分别适用于不同的场景。

方案一:nohup

如果任务逻辑简单,不需要中途进行交互(如输入密码、确认选项等),nohup 是最直接的方案。它通过忽略 SIGHUP 信号来保证程序后台运行。

1. 使用方法

命令格式为 nohup [command] &。其中 & 表示将任务放入后台执行。

BASH
# 示例:后台运行 Python 脚本
nohup python main.py &

2. 输出重定向

默认情况下,程序的标准输出(stdout)和错误输出(stderr)会被写入当前目录下的 nohup.out 文件。

BASH
# 实时查看运行日志
tail -f nohup.out

也可以手动指定输出文件:

BASH
# 将标准输出和错误输出都重定向到 my_log.txt
nohup python main.py > my_log.txt 2>&1 &

方案二:Screen

screen 是 GNU 计划开发的一个终端多路复用器。它允许在一个 SSH 会话中创建多个虚拟终端窗口,即使 SSH 断开,窗口内的程序依然运行。

1. 基础操作

BASH
# 1. 创建一个名为 demo 的会话
screen -S demo

# 2. 在新窗口中执行命令
python main.py

# 3. 分离会话 (Detach)
# 快捷键:先按 Ctrl+a,松开后按 d
# 此时会返回原终端,程序在后台运行

# 4. 恢复会话 (Reattach)
screen -r demo

2. 使用体验问题

Screen 是较早期的工具,默认配置在现代终端下体验一般:

方案三:Tmux (推荐)

tmux 是 screen 的现代替代品,采用 C/S 架构。相比 Screen,它在会话管理、分屏和配置灵活性上更好。

1. 开启鼠标支持

默认情况下 Tmux 也不支持鼠标滚动。为了解决查看日志不便的问题,需要修改配置文件。

~/.tmux.conf 中添加以下配置(如果没有该文件则新建):

BASH
# 开启鼠标支持:允许点击切换窗口、拖动调整分屏大小、鼠标滚轮查看历史记录
echo "set -g mouse on" >> ~/.tmux.conf

# 重新加载配置使生效
tmux source-file ~/.tmux.conf

2. 常用操作指令

会话管理

BASH
# 新建会话并指定名称
tmux new -s [session_name]

# 查看当前所有会话
tmux ls

# 恢复/连接到指定会话
tmux attach -t [session_name]

# 杀死/关闭会话
tmux kill-session -t [session_name]

快捷键操作 (默认前缀键为 Ctrl+b)

总结

工具适用场景优点缺点
nohup简单的非交互式脚本系统自带,命令简单无法中途交互,日志查看不便
Screen旧系统或无需配置的环境稳定性高操作逻辑陈旧,不支持鼠标滚轮
Tmux长期开发、多任务管理功能强大,支持分屏与鼠标,配置灵活需要额外安装与简单配置

对于需要长期维护的服务器环境,建议配置好 ~/.tmux.conf 并使用 Tmux 作为默认工具。

Linux / DevOps

SSH 断开后
优雅保持程序运行

记录在 Linux 服务器上运行耗时任务时,如何解决 SSH 断开导致程序终止的问题。对比 nohup、Screen 和 Tmux 的使用场景与配置。

$ ssh server -- connection lost
问题

在 Linux 服务器上执行耗时任务(模型训练、编译大项目、爬虫抓取)时,SSH 连接意外断开。系统会向该会话下所有子进程发送 SIGHUP (Signal Hang Up) 信号。默认情况下,进程收到该信号会立即终止,导致任务中断、数据丢失。

以下是三种常用的解决方案,按复杂度递增排列。

Solution 01

nohup

最简方案。忽略 SIGHUP 信号,保证程序后台运行。适合非交互式任务。

bash
# 后台运行 Python 脚本
nohup python main.py &
log
# 实时查看运行日志
tail -f nohup.out

# 自定义输出文件
nohup python main.py > my_log.txt 2>&1 &
局限性: nohup 将 stdin 重定向到 /dev/null。如果程序运行中需要用户输入(如 input()),会抛出 EOFError 或挂起。
Solution 02

Screen

GNU 终端多路复用器。允许创建虚拟终端窗口,SSH 断开后程序继续运行。

bash
# 创建会话
screen -S demo

# 在会话中执行命令
python main.py

# 分离会话: Ctrl+a -> d
# 恢复会话
screen -r demo
无法使用鼠标滚轮查看历史输出,直接滚动会显示乱码字符
查看历史需要进入 Copy mode (Ctrl+a -> [),操作逻辑陈旧

Screen 是较早期的工具,默认配置在现代终端下体验一般。如果对分屏和鼠标操作有需求,推荐使用下方的 Tmux。

Recommended
Solution 03

Tmux

Screen 的现代替代品。C/S 架构,在会话管理、分屏和配置灵活性上全面优于 Screen。支持鼠标操作、窗口分割和自定义配置。

Step 1: 配置
~/.tmux.conf
# 开启鼠标支持
echo "set -g mouse on" >> ~/.tmux.conf

# 重新加载配置
tmux source-file ~/.tmux.conf
Step 2: 会话管理
bash
# 新建会话
tmux new -s [session_name]

# 查看所有会话
tmux ls

# 恢复会话
tmux attach -t [session_name]

# 关闭会话
tmux kill-session -t [session_name]
Step 3: 快捷键
keybindings
# 默认前缀键: Ctrl+b

Ctrl+b -> d    # 分离会话
Ctrl+b -> c    # 新建窗口
Ctrl+b -> 0-9  # 切换窗口
Ctrl+b -> %    # 左右分屏
Ctrl+b -> "    # 上下分屏
Tip: 开启 mouse on 后,选中文本即自动复制。在某些终端模拟器中需按住 Shift 键选择。
对比总结
工具适用场景优点缺点
nohup简单的非交互式脚本系统自带, 命令简单无法中途交互, 日志查看不便
screen旧系统或无需配置的环境稳定性高操作逻辑陈旧, 不支持鼠标滚轮