SSH 连接中断后进程是否继续运行?
问题核心:SSH 连接中断后进程是否继续运行?
结论:取决于进程启动方式!
默认情况下,当 SSH 连接中断(网络切换/窗口关闭)时,正在运行的进程会被终止。但通过特定方式启动的进程可以完全不受影响。
三种场景分析(以 php cli.php
为例)
场景 1:直接前台运行 ❌ 进程终止
# SSH 连接后直接执行
php cli.php
网络中断时:SSH 会话结束 → 发送 SIGHUP 信号 → 进程被终止
典型表现:脚本执行中断,需要重新运行
场景 2:后台运行但未隔离 ❌ 进程终止
# 后台运行但未脱离会话
php cli.php &
网络中断时:进程仍属于当前 SSH 会话 → 随会话结束被终止
风险点:看似在后台,实际仍依赖会话
场景 3:使用会话隔离 ✅ 进程持续运行
# 通过 nohup 隔离会话
nohup php cli.php > output.log 2>&1 &# 或使用 screen/tmux
screen -S task
php cli.php
# 按 Ctrl+A D 脱离会话
网络中断时:进程与 SSH 会话解耦 → 继续在系统后台执行
验证方式:重连后
ps aux | grep cli.php
仍可见进程
网络切换/窗口阻塞的真相
中断类型 | 对进程的影响 | 底层机制 |
---|---|---|
网络切换(IP变化) | ❌ 立即断开 TCP 连接 | SSH 连接基于 TCP 会话 |
窗口关闭 | ❌ 发送 SIGHUP 信号 | 终端进程树清理机制 |
电脑睡眠/锁屏 | ❌ 网络冻结导致 TCP 超时 | 操作系统暂停网络堆栈 |
终端窗口失去焦点 | ✅ 不影响运行 | 仅 GUI 事件,不涉及进程信号 |
📌 关键认知:进程是否存活取决于是否与 SSH 会话绑定,而非网络波动本身。
生产环境最佳实践
1. 基础方案:nohup
+ 日志重定向
nohup php cli.php > /var/log/cli.log 2>&1 &
优点:简单可靠,所有输出保存到日志文件
验证:
tail -f /var/log/cli.log
2. 高级方案:systemd
服务化(推荐)
# /etc/systemd/system/cli.service
[Unit]
Description=PHP CLI Service[Service]
ExecStart=/usr/bin/php /path/to/cli.php
Restart=always
User=www-data[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl start cli.service
systemctl enable cli.service # 开机自启
优势:
自动崩溃重启
统一日志管理 (
journalctl -u cli.service
)资源限制 (CPU/Memory)
3. 交互式方案:tmux
会话托管
tmux new -s cli_session
php cli.php
# 按 Ctrl+B D 脱离会话
# 重连后恢复:tmux attach -t cli_session
适用场景:需要实时查看输出的调试过程
诊断进程状态的命令
检查进程是否存活:
ps aux | grep cli.php
查看进程资源占用:
top -p $(pgrep -f cli.php)
追踪系统调用(高级调试):
strace -p $(pgrep -f cli.php)
终极解决方案架构
graph TDA[SSH客户端] -->|网络中断| B(连接断开)B --> C{进程启动方式}C -->|直接运行| D[进程终止]C -->|nohup/systemd| E[进程持续运行]E --> F[日志文件/系统日志]F --> G[重连后查看结果]
✅ 结论:
只要使用 nohup、tmux/screen 或 systemd 服务启动进程,即使:
切换 WiFi/4G/5G 网络
关闭终端窗口
电脑进入睡眠状态
进程都会持续在服务器后台执行,不受客户端网络环境影响。