用nohup、screen、tmux后台运行命令,SSH断连后进程不中断的操作记录(nohup运行sh文件) szthrk.cn

以下命令在 Debian 11/12、Ubuntu 20.04/22.04、CentOS 7/8 上验证过,操作环境包括搬瓦工加拿大温哥华CABC_1节点(1核1G内存、20GB SSD、1Gbps带宽)、LuckVM香港CN2 GIA节点(1核1G/60GB+10GB NVMe/10Mbps CN2线路,月付11)、LuckVM波兰华沙节点(1核512M/5GB SSD/1Gbps Tier1线路,月付$4.93)、DMIT洛杉矶DDoS Shield高防节点(1核1G内存、20GB SSD)、Vultr迈阿密节点(1核1G内存、25GB SSD)、AWS Lightsail东京节点(1核1G内存、30GB SSD),全程root或sudo权限执行。本文只记录命令操作本身,不做任何产品推荐或性能评价,服务器仅作为操作环境。

用nohup、screen、tmux后台运行命令

一、问题:SSH断连后正在运行的命令就没了

通过SSH连接到服务器执行长时间命令(编译、备份、同步、数据处理)时,一旦网络波动断开SSH、或不小心关闭终端窗口,正在运行的进程就会收到SIGHUP(挂断)信号被终止,任务就白跑了。比如编译一个大型程序要跑半小时,跑了10分钟断网就得重来。

后台运行命令有几种方式,按简单到复杂:& 放后台 → nohup 不挂断 → disown 分离已启动进程 → screen 虚拟终端 → tmux 终端复用 → systemd 服务管理。不同场景用不同方式。

二、最简单:& 放后台运行

在命令末尾加一个 &,命令就放到后台执行,立刻返回shell提示符可以继续输入其他命令:

# 格式:命令 &

ping 8.8.8.8 > ping.log &

[1] 25831

输出 [1] 25831 表示这是第1个后台作业(job),PID是25831。

jobs 查看当前后台作业:

jobs

[1]+ Running ping 8.8.8.8 > ping.log &

+号表示最近一个放入后台的作业,Running是正在运行。

fg 调回前台:

fg %1 # 把job 1调回前台

fg # 默认调回带+号的最近作业

bg 让暂停的作业继续在后台运行:

# Ctrl+Z 暂停前台进程,然后bg放到后台继续

^Z

[1]+ Stopped ping 8.8.8.8

bg %1

[1]+ ping 8.8.8.8 > ping.log &

注意:单独用 & 只是放到后台,并没有脱离当前shell,关闭终端或SSH断开时进程还是会收到SIGHUP被终止。要真正断开后继续运行,需要配合nohup或disown。

三、nohup:不挂断运行

nohup(no hang up)的作用就是让命令忽略SIGHUP信号,关闭终端后进程不会被终止。这是最常用的后台运行方式。

基本用法:

# 格式:nohup 命令 &

nohup ping 8.8.8.8 > ping.log &

[1] 25840

# nohup: ignoring input and appending output to 'nohup.out'

输出重定向:不指定输出重定向时,nohup会把stdout和stderr都写到当前目录的 nohup.out 文件。长时间运行会让nohup.out越来越大,建议主动指定重定向:

# 标准输出写output.log,标准错误写error.log

nohup ./build.sh > output.log 2> error.log &

# stdout和stderr都写到同一个文件

nohup ./build.sh > output.log 2>&1 &

# 丢弃所有输出(不保留日志,适合确定不需要输出的场景)

nohup ./long_task.sh > /dev/null 2>&1 &

之前在LuckVM香港节点上编译一个需要跑20多分钟的程序,直接 nohup make -j$(nproc) > build.log 2>&1 & 放到后台,退出SSH等15分钟再连上去查看build.log看编译结果即可。

查看nohup进程:

ps aux | grep long_task

# 或者直接看PID

ps -p 25840

停止nohup进程:

kill 25840

# 或者通过pkill按进程名

pkill build.sh

四、disown:把已启动的进程从shell分离

有时候命令已经跑起来了,突然想起要断开SSH但之前没加nohup,不想中断正在跑的任务,可以用disown:

# 1. 先按 Ctrl+Z 暂停当前前台进程

^Z

[2]+ Stopped rsync -avz /data/ backup:/data/

# 2. 用bg让它在后台继续运行

bg %2

[2]+ rsync -avz /data/ backup:/data/ &

# 3. disown把它从shell作业表中分离,关闭终端不会被kill

disown %2

# 如果不指定job号,disown默认对最近一个作业操作

disown

disown -h 参数:不是移除作业,而是标记该作业不接收SIGHUP,jobs还能看到它。

之前在LuckVM韩国首尔节点上rsync同步一个30GB的目录备份,跑了一会才发现忘了加nohup,Ctrl+Z暂停→bg→disown三步操作后,放心断开SSH,第二天再登录确认同步完成。

五、screen:虚拟终端会话(可随时断连重连)

screen是一个虚拟终端管理器,创建的screen会话独立于SSH连接,断开后会话继续运行,下次可以重新连接(attach)进去查看。适合需要随时回去看输出、和进程交互的场景。

安装:

# Debian/Ubuntu

apt install screen -y

# CentOS

yum install screen -y

基本操作流程:

# 1. 创建一个命名会话(-S指定名字方便辨认)

screen -S build

# 2. 进入screen后,正常执行命令

./long_build.sh

# 3. 临时退出(detach)但不关闭会话:按 Ctrl+A,然后按 D

[detached from 12345.build]

# 回到原shell,可以安全退出SSH

# 4. 下次登录后,查看所有screen会话

screen -ls

There is a screen on:

12345.build (03/15/2026 02:30:00 PM) (Detached)

# 5. 重新连接(attach)回去

screen -r build

# 会话还在,之前的命令输出都能看到

# 6. 会话用完了,在screen内部exit退出,会话就关闭了

exit

[screen is terminating]

常用快捷键(都要先按Ctrl+A):

强制接管别人的会话(会话attached状态但连接断开了):

screen -d -r build

# -d 先detach再attach

六、tmux:更现代的终端复用器

tmux和screen功能类似,但更现代、功能更强(支持分屏、状态栏、脚本化配置),是很多运维人员的首选。

安装:

apt install tmux -y

# 或 yum install tmux -y

基本操作:

# 创建命名会话

tmux new -s work

# 执行命令后临时退出(detach):Ctrl+B 然后按 D

# 查看会话列表

tmux ls

# 重新连接

tmux attach -t work

# 或简写

tmux a -t work

常用快捷键(先按Ctrl+B,再按其他键):

之前在LuckVM波兰节点上同时跑多个监控脚本,用tmux分成三个窗格分别跑日志监控、ping测试、磁盘IO监控,一个界面同时看三个任务,detach后脚本继续运行。

七、需要开机自启动:写systemd服务

前面的nohup/screen/tmux都是会话级别,服务器重启后任务不会自动启动。需要真正长期后台运行、开机自启的进程,应该写systemd服务:

创建服务文件 /etc/systemd/system/myapp.service:

[Unit]

Description=My Long Running App

After=network.target

[Service]

Type=simple

User=www-data

WorkingDirectory=/opt/myapp

ExecStart=/opt/myapp/myapp.sh

Restart=on-failure

RestartSec=5

StandardOutput=append:/var/log/myapp.log

StandardError=append:/var/log/myapp.log

[Install]

WantedBy=multi-user.target

启用并启动:

systemctl daemon-reload

systemctl enable myapp

systemctl start myapp

systemctl status myapp

这种方式是最规范的后台服务管理方式,适合常驻服务(Web服务、采集脚本、定时任务等)。

八、其他方式简要

setsid:开一个新会话运行命令,效果和nohup类似:

setsid ./long_task.sh

at 定时执行:指定时间运行一次命令:

echo "./backup.sh" | at 02:00

cron定时任务:周期性重复执行,前面crontab那篇已经写过。

九、实战场景

场景1:rsync大文件同步不中断

大文件同步耗时久,配合nohup后台执行,日志写文件:

nohup rsync -avz --progress /data/ user@remote:/data/ > rsync.log 2>&1 &

tail -f rsync.log

场景2:编译大型软件

编译可能跑几十分钟,用screen:

screen -S compile

cd /usr/src/xxx

./configure && make && make install

# Ctrl+A d 退出

# screen -r compile 随时回来看

场景3:Python脚本常驻运行

临时脚本用nohup,正式服务写systemd:

# 临时跑

nohup python3 monitor.py > monitor.log 2>&1 &

场景4:同时监控多个日志

tmux分屏多窗格:

tmux new -s logwatch

# Ctrl+B % 左右分屏

# 左边 tail -f /var/log/nginx/access.log

# 右边 tail -f /var/log/nginx/error.log

十、易错点和注意

  1. nohup.out会越写越大:不加重定向所有输出都写nohup.out,运行几个月能撑满磁盘,建议主动用 >log 2>&1 或 >/dev/null 重定向。
  2. & 不等于后台稳定运行:单独用&,断开SSH进程还是会被kill,必须配nohup/disown。
  3. screen/tmux 要记得exit关闭:开了不用的会话会一直占着系统资源,screen -ls 和 tmux ls 定期清理。
  4. nohup执行相对路径问题:nohup启动脚本时,脚本内的相对路径是相对于执行nohup时的工作目录,不是脚本所在目录,建议脚本内先cd或用绝对路径。
  5. 环境变量可能不同:nohup启动的进程环境变量和交互式shell不完全一样(比如PATH),脚本里最好写绝对路径。
  6. systemd服务的Restart=always要谨慎:程序正常退出也会被自动重启,按需选on-failure或on-abnormal。
  7. 不要在screen/tmux里跑太多高负载任务:开太多会话占资源,定期清理不用的。

十一、实用经验

  1. 临时跑几分钟但不想因为断连中断:nohup 命令 >log 2>&1 &,简单够用。
  2. 命令已经跑了才想起要后台:Ctrl+Z → bg → disown 三步救场。
  3. 需要和进程交互(随时回来输入命令看输出):用tmux(更推荐)或screen。
  4. 长期常驻服务,开机自启:写systemd service文件,最规范最可靠。
  5. 跑完的后台进程记得看日志确认结果(tail -f log看输出,echo $?看退出码)。
  6. nohup加完后可以用 ps aux | grep 命令名 确认进程在跑,disown后jobs可能看不到但ps能看到。
  7. tmux配置~/.tmux.conf可以把快捷键改成自己习惯的,比如开启鼠标支持、改状态栏。