后台任务与进程挂起:jobs、fg、bg 与 disown
发布时间:2026-05-12 13:29       
更新时间:2026-05-12 17:24
跑了三小时的脚本被手滑按了 Ctrl+Z 卡住,关掉终端它会不会丢?这个问题背后是 shell 任务控制的一整套机制,值得一次讲清。
Ctrl+Z 按下去发生了什么
任务没有被杀死,只是收到 SIGTSTP 信号进入挂起状态,进程还原封不动待在内存里。立刻输入 `bg %1` 让它转后台继续跑,或 `fg %1` 调回前台;`jobs -l` 列出当前会话所有任务和状态,百分号加编号就是任务标识。误按之后手别乱,两条命令能原样救回来。另一个更隐蔽的误操作是 Ctrl+S——终端画面像卡死一样冻结,其实只是输出被暂停,Ctrl+Q 即刻恢复,知道这一条能少重启好几次终端。
为什么退出终端任务会消失
后台任务本身还在,但退出终端时 shell 会给它们发 SIGHUP(挂断信号),多数程序收到就退出了。想让任务熬过登出,有三条路:启动时用 `nohup 命令 &`,输出自动进 nohup.out;对已经在跑的任务用 `disown -h %1` 把它从 SIGHUP 名单里摘出去;长任务干脆放进 tmux 或 screen 这类终端复用器,会话和连接分离,断线重连接着看。bash 的 huponexit 选项决定登出时是否发挂断信号,多数发行版默认关闭,这也是有人退出后任务还在、有人就被带走的差异来源。
恢复挂起任务的完整路径
先 `jobs -l` 确认任务还在,再选 bg 或 fg。如果这是新开的终端、jobs 列表是空的,那任务要么已被 SIGHUP 带走,要么还挂在旧会话上——用 `ps -ef | grep 脚本名` 查进程,状态列是 T 说明仍处于挂起,`kill -CONT 进程号` 可以就地唤醒;状态是 Z 则成了僵尸进程,得找它的父进程处理。查完状态再动手,T 唤醒、R 等待、Z 找父进程,对症下药比一通乱 kill 高明得多,也安全得多;状态看错就动手,是排障大忌。
预防永远比抢救便宜:重要长任务启动前就放进 tmux,或明确用 nohup 加输出重定向。等想起来的时候任务已经没了,任何参数都救不回来。