第 6 章 · 05 后台作业: 、 、 、 本节摘要:有时候你要跑一个耗时任务(大文件下载、长时间训练),又不想让终端一直被占着。本节讲怎么把任务放后台、怎么管理后台作业。核心工具是 (放后台)、 (暂停到后台)、 (列后台作业)、 / (切回前台/后台继续)。但本节真正的重点是 ——它解决的不是一个简单问题,而是「为什么我关掉终端,后台进程就死了」的根因(SIGHUP 信号)。理解了 SIGHUP 与 nohup,你才懂得为什么生产环境应该用 而非 来管理长期服务。 内容来源:原项目「Linux 命令大全」 、 等,精选并套用体系化模板。 学习目标 阅读完本节,你应当能够: 用 把命令放后台执行,用 查看后台作业。 用 暂停前台进程,用 / 在后台继续或切回前台。
jobs、bg、fg、nohup本节摘要:有时候你要跑一个耗时任务(大文件下载、长时间训练),又不想让终端一直被占着。本节讲怎么把任务放后台、怎么管理后台作业。核心工具是
&(放后台)、Ctrl+Z(暂停到后台)、jobs(列后台作业)、fg/bg(切回前台/后台继续)。但本节真正的重点是nohup——它解决的不是一个简单问题,而是「为什么我关掉终端,后台进程就死了」的根因(SIGHUP 信号)。理解了 SIGHUP 与 nohup,你才懂得为什么生产环境应该用systemd而非nohup来管理长期服务。
内容来源:原项目「Linux 命令大全」
command/nohup.md、command/jobs.md等,精选并套用体系化模板。
阅读完本节,你应当能够:
& 把命令放后台执行,用 jobs 查看后台作业。Ctrl+Z 暂停前台进程,用 bg/fg 在后台继续或切回前台。nohup 让进程忽略 SIGHUP,从而在终端关闭后存活。systemd 而非 nohup 管理长期服务。默认情况下,你在终端敲一个命令,它在前台跑,占着终端,你敲不了别的。有两种情况你想让它「不占终端」:
gimp &,图形程序启动了,终端还能继续用。第一种用 & 就够。但第二种会撞上一个隐蔽的坑:你关掉终端,后台进程跟着死了。要理解为什么,得先理解 Shell 与子进程、以及 SIGHUP 信号。
ls | grep 是一个作业,含两个进程)。jobs 命令看到的是作业,ps 看到的是进程。Shell 给每个作业编号([1]、[2]),这个编号是 fg/bg 用的;而 PID 是 kill 用的。两者不同。
&long_task & # 放后台, 立刻回到提示符 [1] 12345 # [1] 是作业号, 12345 是 PID
Ctrl+Z、bg、fg、jobsvim file.txt # 前台跑 vim # 按 Ctrl+Z # 暂停 vim, 回到 Shell [1]+ Stopped vim file.txt jobs # 列出后台作业 [1]+ Stopped vim file.txt fg %1 # 把作业 1 切回前台(继续 vim) bg %1 # 让作业 1 在后台继续(从 Stopped 变 Running)
💡 技巧:
Ctrl+Z暂停的进程状态是T(停止,见第 03 节)。忘了它而退出 Shell,这个暂停的进程也会被清理。用jobs定期检查有没有被你遗忘的暂停作业。
现在讲本节的核心问题:为什么关终端后台进程会死,以及 nohup 怎么解决。
根因:当你关闭终端窗口或断开 SSH,Shell 进程要退出。退出前,它给它的每个子进程/作业发 SIGHUP 信号(SIGHUP = "signal hangup",挂断)。大多数进程收到 SIGHUP 的默认行为是「退出」——所以你的后台任务跟着终端一起死了。
nohup 的解法:它启动进程时让进程忽略 SIGHUP,这样终端关闭、Shell 发 SIGHUP 时,进程不受影响。
nohup long_task & # 后台跑, 且忽略 SIGHUP, 关终端也不会死 # nohup 会把输出重定向到 nohup.out(因为终端没了, stdout 无处可去)
nohup ./train.py > train.log 2>&1 & # 更好的写法: 自己指定日志, 不用默认的 nohup.out
⚠️ 注意:
nohup只解决 SIGHUP 一个问题。它不保证「进程永远不死」——如果系统重启,进程还是会消失。真正可靠的长期服务管理用systemd(第 8 章),它提供开机自启、崩溃重启、统一日志,这些 nohup 都没有。
nohup ./script.sh & # 没指定输出, 默认写 nohup.out
多次跑会不断追加 nohup.out,且与脚本目录混在一起。始终显式重定向:nohup ... > app.log 2>&1 &。
Ctrl+Z 暂停的进程忘了恢复vim big.txt # Ctrl+Z 暂停 # ... 干别的事, 忘了 vim 还暂停着 exit # 退出 Shell, 暂停的 vim 被清理, 没保存的内容丢了!
退出 Shell 前先 jobs 检查,把重要作业 fg 回来处理完。
nohup ./job.sh > job.log 2>&1 & echo $! # $! 是上一个后台进程的 PID, 务必记下来 # 后续: kill <那个PID> 才能停掉它
不记 PID,以后想停就只能 ps aux | grep job.sh 慢慢找。
nohup 让进程忽略 SIGHUP,但它仍是 Shell 的子进程,没有 setsid(脱离会话)、没有崩溃重启。要「真正的守护进程」,用 systemd 写个 service 单元(第 8 章)。
& 放后台、Ctrl+Z 暂停、jobs 列作业、fg/bg 切换——这是 Shell 的作业管理。[1]/[2] 编号)与进程(process,系统概念,PID)不同;fg 用作业号,kill 用 PID。nohup 让进程忽略 SIGHUP,从而在终端关闭后存活;但务必重定向输出(> log 2>&1)、记下 PID($!)。systemd(第 8 章)。下一节抬到系统级资源观测——free(内存)、uptime(负载)、vmstat(虚拟内存与上下文切换)。