想象你是一家高档餐厅的店长。后厨里,有厨师在灶台前颠勺,有帮厨在案板上切菜,有服务员端着菜来回穿梭,角落里还有个临时工在刷盘子。你手上握着三件管理法宝:喊一声“所有人举手报到”,就能让全员停下动作报出自己的工号——这是 ps;站在大厅中央盯着每桌的上菜速度和每个人的忙碌程度,实时掌握谁在偷懒、谁在超负荷——这是 top;发现某个员工操作不当,你可以温和地请他放下手头工作,也可以直接让保安把他架走——这就是 kill。餐厅每天都在营业,员工来来去去,有人干到一半被调岗,有人下班了还在加班完成订单。在 Linux 的服务器上,“正在干活的员工”就是进程(Process)。本文用这套餐厅管理学的故事,带你吃透 Linux 最经典的 ps/top/kill 三件套,以及作业控制、优先级和后台常驻等进阶技能。
学会 Linux 进程管理,你就握住了服务器运维的方向盘:排查故障、监控负载、精准处置异常进程,是每个 AI 工程师部署模型、运行训练任务、保障推理服务稳定的基本功。
目录
可视化演示
动态展示Kruskal算法按边权排序后使用并查集逐步选择不构成环的最小权边构建最小生成树的过程,直观呈现贪心策略与连通性检测原理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Kruskal算法 - 初始状态 按边权升序排序所有边 并查集检测不构成环则选入MST O(E log E) 贪心策略构建MST
进程基础概念:菜谱与厨师
走进一家餐厅的后厨,你会看到灶台上翻飞的火苗和忙碌的身影。但真正支撑这一切的,是墙上那本厚厚的菜谱——它只是静静躺在那里,什么都不做。只有当一位厨师拿起菜谱、点火、备料、起锅,“红烧肉”这道菜才真正开始走向餐桌。在 Linux 世界里,菜谱就是程序(Program),是磁盘上的一堆静态指令;而拿着菜谱干活的厨师,就是进程(Process)。程序不会消耗 CPU,只有进程才会。
每位厨师胸前都别着一块工牌号(PID),后厨总管那里还记录了 TA 是由哪位领班招进来的(PPID)。进程之间“谁招进来、谁负责管”的链条构成了进程树。用 ps -ef 能看到完整的家族谱系,树根是 PID 为 1 的 init 进程——相当于餐厅的老板,所有无人认领的员工最后都归他管。
进程一生会经历不同状态,像厨师在不同时段的工作状态:R(Running) 正在颠勺,占用 CPU;S(Sleeping) 在等食材下锅(等 IO 或事件),CPU 空着也暂时不用;D(Uninterruptible) 正握着水管冲地,拽都拽不开,此时不能被打断;T(Stopped) 被店长喊了暂停;Z(Zombie) 员工已经离职,但人事档案还没销——这在排查实战一节会再遇到。这五种状态统一用下面的集合表示:
理解了这五种状态,再看 ps 输出的 STAT 列就不会懵:一个 java 进程显示 S 说明它在等请求,显示 R 说明它正忙于计算。像店长看一眼考勤备注就能知道员工在干嘛一样,STAT 列就是进程的“此刻状态栏”。
- 状态变量$S_{\text{proc}}$ 是内核为每个进程登记的状态标签,相当于考勤表上的备注栏
- 属于关系$\in$ 表示状态取值被限定在后面的集合内,不会超出范围
- 运行与睡眠$R$ 说明进程正占着 CPU 颠勺,$S$ 说明它在等食材下锅(等待事件或 IO)
- 不可中断与暂停$D$ 表示正握着水管不能撒手(不可被信号打断),$T$ 表示被店长喊了暂停
- 僵尸状态$Z$ 表示进程已退出但退出信息无人接收,像离职员工的档案还挂在人事部
ps进程快照:拍一张全员点名照
身为店长,你最常做的动作是站在门口扫一眼:现在店里有多少人?都在什么岗位上?状态如何?ps 干的就是这件事——它不是摄像头,而是照相机:拍到哪一秒就是哪一秒,绝不追着人跑。这个“定格”特性,决定了它最适合快速排查和脚本解析。
最常用的组合是 ps aux。注意这里没有连字符,a 表示显示所有用户的进程,u 表示带上用户和资源占用信息,x 表示包含不占用终端的后台进程。与之并列的还有 System V 风格的 ps -ef(显示完整命令),但运维场景里 ps aux 的出场率最高,它的每一列都值得记住:USER 是哪个员工启动的;PID 是工牌号;%CPU 与 %MEM 是进程占用的 CPU 和内存百分比;VSZ 是虚拟内存大小(申请了多少地盘),RSS 是实际驻留内存(真正坐了多少桌);TTY 是关联的终端(在哪个楼面干活);STAT 是状态;START 是上岗时间;TIME 是累计吃掉的 CPU 时间;COMMAND 是正在执行的完整命令。
想从一堆进程里挑出目标,最朴素的方式是管道加 grep:ps aux | grep python。%MEM 这个字段并非凭空而来,它的计算方式很直观:
拍快照最大的好处是稳定、可脚本化:把 ps aux 的输出存成文件,就是一张可回查的点名表。但照片终归是照片——如果你想盯着某个人连续观察,就得换 top 这个“直播镜头”了。
- RSSResident Set Size,进程实际占用的物理内存大小,即真实坐下的桌数
- 物理内存总量整台服务器所有内存条容量的总和,可用
free -h查看 - 比值RSS 除以总内存,得到进程占用的比例
- 百分化乘以 100% 得到易读的百分比数字
top实时监控:厨房直播大屏
照片只能回答“现在怎么样”,回答不了“刚才那几分钟谁一直在偷懒”。top 就是架在厨房中央的直播摄像头,默认每隔几秒刷新一帧,让你持续盯住每个人的动作。当你怀疑某个进程在“摸鱼”或“爆肝”时,top 是第一个该打开的窗口。
top 的第一屏是“全局看板”,分上下两区。上半区:第一行显示当前时间、开机时长、登录人数,以及最重要的负载平均值 load average(分别对应 1 分钟、5 分钟、15 分钟);第二行是进程总数及状态分布;再往下是 CPU 各状态百分比,其中 us 是用户态占用、sy 是系统态占用、id 是空闲比例;接着是内存与交换分区。下半区则是按 CPU 降序排列的进程实时榜单——谁在烧 CPU 一目了然。
top 不只是看,还能互动:按下 k 键会提示输入 PID 并发送终止信号;r 键可以调整优先级(对应后文 nice/renice);P / M / T 分别按 CPU、内存、累计时间排序;q 退出。真正的高手会先看 load,再看 us/id 比例,最后才定位到具体进程。负载的物理含义可以用这个比值理解:
所以监控一台繁忙的模型训练服务器,别只盯着某个进程的 CPU 飙到 100%,先看 load 是否超过核数——先判断“是厨房整体超载,还是个别厨师燃起来了”,再决定要不要动用 kill 的手段。
- 可运行进程数已就绪、正在排队等待 CPU 的进程数量,相当于在灶台前等位的厨师
- 不可中断进程数正在执行磁盘读写等不可打断 IO 的进程数量,相当于握着水管冲地的员工
- CPU 核数服务器实际可并行干活的物理核总数,可以用
nproc命令查看 - 判读标准Load 大于 1 说明等待队列开始拥堵,相当于灶位不够用了
kill信号控制:传达室送信的艺术
kill 这个词很唬人,仿佛一敲下去就是“拖出去斩了”。实际上 kill 的真实身份是“传达室的小哥”——它的本职工作只是送信(发信号),至于收到信的人怎么反应,取决于信的内容和收信人当时的状态。理解了这一点,很多“杀不死”的怪现象就豁然开朗了。
最常用的三封信:SIGTERM(编号 15)——“请把手头工作收尾、释放资源后下班”,这是默认信,kill PID 就等于 kill -15 PID;SIGKILL(编号 9)——“不用收拾了,保安直接架走”,进程无法拦截,只能当场消失;SIGHUP(编号 1)——“老板挂电话了”,终端断开时 shell 会给旗下所有进程群发这封信,多数进程默认选择随老板一起下班。用 kill -l 可以列出系统支持的全部六十多种信号。
实战中,终止一个失控的 python 训练进程,标准动作是:先 ps aux | grep python 拿到 PID,再 kill -15 PID 温柔劝退;等 5 秒看进程还在,才升级 kill -9 PID 强杀。为什么先 15 后 9?因为直接 -9 相当于不给进程保存检查点的机会,可能损坏模型权重或数据库文件。另外 kill -0 PID 不发送任何真实信号,只探测进程是否存在——像先戳一下看看人还醒着没。kill 的命令结构可以概括为:
把 kill 理解为送信而不是处决,很多怪现象就通了:为什么杀不死僵尸进程?因为人已经走了,信送给谁呢?为什么 D 状态的进程 kill -9 也没反应?因为它正握着水管(内核 IO)腾不出手接信。搞懂信号,就是搞懂“如何用恰当的方式让人停下”。
- kill命令名的真实含义是“发送信号”,而不是“杀死”,它是传达室的小哥
- -信号编号可选参数,-15 对应温和退出的 SIGTERM,-9 对应强制击杀的 SIGKILL
- PID目标进程的工牌号,信要送到具体的人手上,没有工牌号就无从投递
- 缺省行为省略信号编号时不写,默认发送 SIGKILL 吗?不,默认是 SIGTERM
作业控制:前台接待与后厨备菜
餐厅有两种干活模式:一种是服务员站在你桌前,等你一道菜一道菜地点——前台;一种是后厨在后台默默备料,不见人但活没停——后台。Linux 的终端作业控制,就是在这两种模式之间的切换艺术。
前台运行:直接敲 python test.py,终端被这个进程独占,你按 Ctrl+C 会发送 SIGINT 让其中断。想让它滚到后台继续跑,按 Ctrl+Z 会发送 SIGTSTP 把它挂起(暂停),然后输入 bg 让它转为后台运行——相当于把刚点的菜转交给后厨,后厨继续闷头做。加 & 启动更干脆:python test.py &,命令直接从后台开工,终端立刻还给你。
jobs -l 像店长的派工单,列出当前 shell 管理的所有作业及 PID,每个作业带编号 [1]、[2]。fg %1 把 1 号作业拉回前台继续跑;bg %1 让挂起的 1 号作业在后台继续跑。需要记住的是,这些操作只影响同一个终端会话内的作业——换一个终端窗口,jobs 列表是完全独立的。作业的状态只有三种:
作业控制最适合临时性调度:正在前台跑一个耗时脚本,突然想起来还要编译另一个模块,Ctrl+Z 挂起、bg 转后台、重新敲新命令,一气呵成。但要记住,作业控制只是 shell 这一层的事,一旦终端断开,挂起的、后台的作业都会收到 SIGHUP——这时候就需要后台常驻三件套出场了。
- 作业状态一个作业在终端眼中的“派工状态”,同一时刻只能是三者之一
- 前台运行独占终端的输入,终端的 Ctrl+C / Ctrl+Z 直接作用于它
- 后台运行进程照常执行但不再接收终端输入,输出仍可能打印到屏幕
- 挂起暂停进程被 Ctrl+Z 冻结,不占 CPU,等待 fg 或 bg 唤醒
优先级管理:加急单与普通单
餐厅里订单堆成山时,店长怎么决定先做哪桌?自然是加急单优先、老顾客优先。Linux 用 nice 值来表达这种“排队的礼貌程度”:nice 值越低,进程越“凶”,越优先获得 CPU;nice 值越高,进程越“谦让”,越是把资源让给别人。
nice 的取值范围是 -20 到 19,共 40 个档位。启动时指定:nice -n 10 python train.py 表示以低优先级启动训练任务,把 CPU 让给线上服务。对已经运行的进程,用 renice 调整:renice -n -5 -p 1234。这里有个权限红线:普通用户只能把 nice 往大了调(让自己更谦让),只有 root 才能把 nice 调成负数(抢占优先)。
top 里看到的 PR 列,数值接近 20 + nice。为什么要做这层映射?因为内核不直接存 nice,而是存 PR 优先级,数值越小越优先调度。一个 nice 为 19 的进程谦让至极,在 CPU 富余时也能跑,一旦有高优先级任务进来就立刻让位——就像普通顾客永远给 VIP 让座。
给模型训练任务降级时用 nice + 10 让它“文明排队”,给重要推理服务提权时用 renice -5 让它“加急处理”。掌握 nice/renice,你就学会了在有限 CPU 资源上做“餐厅排班”的艺术。
- NICE用户可调的“礼貌程度”,取值范围从 -20 到 19,数字越小越不客气
- PR内核实际使用的调度优先级,数值越小越优先被 CPU 选中
- 恒定偏移PR 与 NICE 之间相差固定的 20,nice=-20 时 PR=0
- 取值范围nice 为负数是“加急单”,只有 root 能开;nice 为正数是“普通单”,人人可开
后台常驻:店长下班也不停火
假设你下班前让一位厨师通宵备料,结果你离开餐厅时忘了交代其他人——正常剧本是,保安锁门前看到厨师还在,心想“老板都走了你还干?”一个 SIGHUP 挂断信号砸过去,任务当场中断。这就是 ssh 断开后后台任务全部消失的真相:终端关闭时,shell 会给它的“小弟们”群发 SIGHUP。
nohup 就是给这位厨师发一副“降噪耳机”:忽略 SIGHUP 信号。典型用法是:
拆解一下:nohup 让它不响应挂断信号;> train.log 把标准输出写入日志;2>&1 把错误输出也并进同一个日志;最后的 & 让它直接进后台。这样即使 ssh 断开、终端关闭,任务依然在服务器上稳如泰山地跑。第二天回来,用 ps aux | grep train.py 确认进程还活着,再 tail -f train.log 看进度,一套标准的“无人值守后厨”就搭好了。
另一招是 disown:先用 & 把任务丢后台,然后 disown %1 把它从 shell 的作业表里划掉——相当于把厨师从店长的名册上除名,之后店长哪怕离职(shell 退出),也不会专门给它发信号。nohup 和 disown 的差别很微妙:nohup 是“屏蔽信号”,disown 是“脱离管制”。如果任务已经用 & 启动了,来不及加 nohup,disown 就是补救方案。另外,如果父进程比子进程先退出,子进程就成了孤儿进程,会被老板 init(PID 1)收养。
生产环境跑数据管道、模型训练长任务,几乎都是 nohup + 重定向 + & 的固定配方。配合之前学的 top,第二天回来先看进程还在不在,再看日志有没有报错——一套完整的“无人值守后厨”就搭建完成。
- 进程被保活的后台任务,相当于通宵备料的厨师
- nohup 作用启动阶段就把 SIGHUP 加入信号屏蔽清单,挂断信号来了也听不见
- disown 作用将进程从当前 shell 的作业表中移除,shell 退出时不再向它发放任何信号
- 二者关系nohup 是事前防护,disown 是事后补救,也可以组合使用双保险
nohup python train.py > train.log 2>&1 &排查实战:店长巡检的一天
店长每天早晚各巡一次店:先拍张照(ps)看全员在岗情况,再盯一会儿直播(top)看有没有异常,发现问题就送信(kill)。这套流程就是进程排查的完整闭环,也是本章的核心心法。
进阶工具有两个。htop 是 top 的彩色加强版:支持鼠标操作、F 键排序、树状进程视图,F9 可以直接选择信号发送,非常适合人眼排查。pgrep 则像“按名字查工号”:pgrep -l python 会输出所有名字含 python 的进程 PID 和名称,配合 kill $(pgrep python) 可以批量处置——不过要小心核对,别误杀了别的项目进程。
重点讲僵尸进程:子进程退出后,父进程没有调用 wait 回收它的退出信息,进程就变成 Z 状态。僵尸不占 CPU 和内存,只占一个 PID 槽位;大量堆积会耗尽系统可用的 PID 总数。处置口诀:先 ps -o pid,ppid,stat -l 确认它的 PPID,若是 init(PID 1)收养,稍等即会回收;若是普通父进程,就 kill 掉父进程,让 init 接管善后——相当于领班离职了,员工档案自动归到老板名下,由老板统一销账。这个过程可以表示为一条事件链:
遇到“服务器卡死”的第一反应不该是重启机器,而是按店长巡检法走一遍:ps 快照找可疑进程 → top 确认它是否真的吃满资源 → 判断该 kill 还是 renice → 处置后再次确认。这套流程就是 Linux 运维的基本功,也是你从“小白”走向“值班高手”的分水岭。
- 子进程退出进程完成了任务,准备离场
- 状态 Z退出信息无人接收,档案悬置,显示为僵尸状态
- 父进程 wait 或退出父进程调用 wait 收尸,或父进程自身也退出,交给 init 处理
- PID 槽位回收系统回收该 PID,供新进程复用,档案正式销掉
AI 应用场景
模型训练进程监控
阶段:模型训练阶段
解决的问题:训练脚本一跑就是几小时,传统方式只能黑盒等待,跑完才知道成功还是失败,中途卡死或死循环都无从下手。用 ps/top 可以让训练过程全程透明:实时观察训练进程的 CPU 占用、状态和内存增长,发现异常用 kill 精准处置,把失败成本从“几小时”压缩到“几分钟”。
具体案例:一位 MLOps 工程师同时在 GPU 服务器上跑 3 个消融实验,用 top 看到实验 B 的 CPU 持续 100% 但 loss 迟迟不降,判定为死循环。他用 ps aux | grep train.py 拿到实验 B 的 PID,先 kill -15 优雅终止,5 秒后确认仍在,升级 kill -9 回收,重写脚本重新启动。整个诊断过程不到 3 分钟。
数据处理管道后台常驻
阶段:数据预处理阶段
解决的问题:白天要跑线上服务,清洗两亿条日志只能放在凌晨执行;如果直接 ssh 挂着跑,一旦网络抖动断开终端,任务就会收到 SIGHUP 当场中断,第二天发现白跑一夜。用 nohup + disown 可以让数据管道在后台常驻,彻底摆脱对终端的依赖。
具体案例:一位数据工程师在凌晨用 nohup python clean_logs.py > logs/clean.log 2>&1 & 启动清洗任务,随后 disown 让它脱离 ssh 会话。第二天上班先 ps aux | grep clean_logs 确认进程仍在运行,再 tail -100 logs/clean.log 查看进度,管道如期完成。
推理服务进程急救
阶段:模型部署与推理阶段
解决的问题:在线推荐服务突发内存泄漏,多个 worker 进程的 RSS 疯狂上涨,用户请求大面积超时。传统做法是重启整个服务,但会导致所有用户闪断。用 top 精准定位异常 worker,再用 kill -9 逐个回收,配合进程守护工具自动拉起新 worker,可以把影响面控制在最小。
具体案例:SRE 值班时接到告警,先用 top 按内存排序,锁定 3 个 RSS 异常增长的 worker PID;确认是内存泄漏后 kill -9 逐个回收,supervisor 在秒级自动拉起新 worker,服务恢复,其余正常 worker 全程无感。全程没有重启整个服务集群。
Python 演示
import systry: import psutilexcept ImportError: print("请先安装 psutil: pip install psutil") sys.exit(1) def show_snapshot(limit=12): """模拟 ps aux: 列出 CPU 占用最高的前 limit 个进程""" rows = [] for p in psutil.process_iter(['pid', 'ppid', 'name', 'cpu_percent', 'memory_percent', 'status']): try: rows.append(p.info) except (psutil.NoSuchProcess, psutil.AccessDenied): continue for r in rows: if r['cpu_percent'] is None: r['cpu_percent'] = 0.0 if r['memory_percent'] is None: r['memory_percent'] = 0.0 rows.sort(key=lambda x: -x['cpu_percent']) print('{:>6} {:>6} {:>6} {:>6} {:>8} {}'.format( 'PID', 'PPID', 'CPU%', 'MEM%', 'STAT', 'NAME')) for r in rows[:limit]: print('{:>6} {:>6} {:>6.1f} {:>6.1f} {:>8} {}'.format( r['pid'], r['ppid'], r['cpu_percent'], r['memory_percent'], r['status'], r['name'])) def send_signal(pid, sig=15): """发送信号: 15=SIGTERM 温和退出, 9=SIGKILL 强杀""" try: proc = psutil.Process(pid) proc.send_signal(sig) print('[OK] 信号 {} 已发送给进程 {} ({})'.format(sig, pid, proc.name())) except psutil.NoSuchProcess: print('[!!] 进程 {} 不存在, 工牌号已回收'.format(pid)) except psutil.AccessDenied: print('[!!] 权限不足, 无法操作进程 {}'.format(pid)) if __name__ == '__main__': print('=== Linux 进程管理演示 ===') show_snapshot() if len(sys.argv) >= 2: target_pid = int(sys.argv[1]) target_sig = int(sys.argv[2]) if len(sys.argv) >= 3 else 15 send_signal(target_pid, target_sig)
for p in psutil.process_iter(['pid', 'ppid', ...])遍历系统中所有进程,相当于ps在全员点名rows.append(p.info)用字典形式收集每个进程的六项关键信息rows.sort(key=lambda x: -x['cpu_percent'])按 CPU 占用从高到低排序,模拟top的默认榜单r['cpu_percent'] is None处理进程刚启动、CPU 采样尚未返回的边界情况proc.send_signal(sig)向进程发送信号,等价于 shell 里的kill -s命令except psutil.NoSuchProcess捕获“进程已消失”的异常,相当于送信时发现收信人已经离职target_sig = int(sys.argv[2]) if len(sys.argv) >= 3 else 15默认用 SIGTERM 温和劝退,符合“先礼后兵”的原则
常见误区
误区我碰到跑不动的进程就习惯 `kill -9` 一把梭:反正都是要它死,早死早超生,直接强杀最省事,什么 SIGTERM、SIGKILL 的区别根本不重要。
正解kill -9 是最后手段而非首选。SIGTERM(默认信号)给进程预留了整理现场的机会:释放内存、关闭文件、保存日志,就像让人把工作交接完再走。直接用 -9 相当于不给人任何反应时间就断电拔网线,可能导致数据文件损坏、数据库不同步。正确姿势是先 kill -15,观察几秒,确认还活着再升级 -9。
为何常见:-9 见效快,网上大量教程和论坛示例张口就是 kill -9,新手自然形成了“强杀万能”的印象。
误区看到 STAT 是 Z 的进程,第一反应是它还在偷偷吃 CPU、占内存,赶紧 `kill -9` 补刀,但每次都显示杀不掉,是不是权限不够?
正解僵尸进程已经死亡,完全不占用 CPU 和内存,只是退出信息没人接收,占着一个小小的 PID 槽位。它根本无法被任何信号杀死——因为人已经不在了,信送给谁呢?正确处置是让“收尸人”出现:kill 掉它的父进程,让 init(PID 1)接管并清理,或者等父进程调用 wait 后自然回收。
为何常见:“僵尸”这个名字太有迷惑性,让人联想到还魂、还在作怪,其实它只是系统里的一具“档案尸体”。
误区ps 和 top 都是看进程列表,随便用哪个都一样,反正输出的都是那几列信息,没必要两个都学。
正解ps 是“快照”,拍下执行那一刻的静态数据,适合脚本解析和事后排查;top 是“直播”,默认每隔几秒刷新一次,还能直接交互(k 终止、r 调优先级、P/M/T 排序),适合实时监控。两者就像照片和监控画面,一个定格式、一个动态式,使用场景完全不同,排查问题时常需要两者配合。
为何常见:两者确实都展示进程列表,第一眼高度相似,新手容易把命令的“长相”当成功能的全部。
误区只要命令前面加了 nohup,这个进程就永远安全了,就算服务器重启也没事,再也不用管它。
正解nohup 只屏蔽 SIGHUP 一个信号,解决的是“终端断开导致任务退出”的问题。它防不住系统重启、防不住 kill -9、也防不住程序自身崩溃。另外它并没有让进程脱离 shell 的作业表,只是让 shell 退出时不再通知它。要彻底脱离管制还要结合 disown;要开机自启则是 systemd 的职责。
为何常见:nohup 与 & 组合使用后表现确实很“稳”,给人一种全能的错觉,忽略了它实际只处理了一个信号的事实。
误区nice 嘛,数值越大越 nice,对系统越友好,所以我启动任务时把 nice 调得很大,这样系统会更舒坦。
正解在 Linux 里 nice 值越大,进程越“谦让”,优先级越低——19 是最低优先级,人人都能插它的队;反而 -20 才是最高优先级。把训练任务设成 nice=19,它会在 CPU 空闲时慢慢跑,一旦有高优先级进程进来就立刻让位。想让任务跑得快,要设负数(需要 root 权限);想让位给别人,才设正数。简单说:nice 值低 = 加急单,nice 值高 = 普通排队。
为何常见:英文 nice 的日常含义是“好、友好”,“越 nice 越好”的直觉恰好和 Linux 里的调度语义相反,属于典型的文化反差陷阱。
面试题
Q1. ps 输出中代表“进程唯一身份”的字段是?
- A.PID 是进程的身份编号← 正确答案
- B.PPID 是父进程的身份编号
- C.TTY 是终端的身份编号
- D.STAT 是运行的状态编号
答案:A。PID(Process ID)是内核分配给每个进程的唯一工牌号,就像餐厅里每位员工的工牌编号。PPID 是父进程的编号,TTY 是终端编号,STAT 是状态,它们都不是“唯一身份”。
Q2. 直接执行 kill PID 时,默认发送的信号是?
- A.SIGTERM 温和的退出信号← 正确答案
- B.SIGKILL 强制的杀死信号
- C.SIGHUP 终端的挂断信号
- D.SIGSTOP 暂停的运行信号
答案:A。kill 命令不写信号编号时,默认发送 SIGTERM(编号 15),相当于“请收尾后下班”。SIGKILL(9)是要显式指定的强杀信号,SIGHUP(1)是挂断信号,SIGSTOP 是暂停信号。
Q3. 在终端执行命令时末尾加上 & 表示?
- A.让命令在后台默默运行← 正确答案
- B.让命令在前台重点运行
- C.让命令立即终止运行
- D.让命令提升优先度运行
答案:A。& 的作用是把命令放到后台运行,就像把备菜单递给后厨,后厨默默干、前台继续接客。前台运行是默认方式;& 与终止、提优先级无关。
Q4. 进程 A 的 nice=-10,进程 B 的 nice=10,谁更优先获得 CPU?
- A.进程 A,因为 nice 值越低越优先← 正确答案
- B.进程 B,因为 nice 值越高越优先
- C.两者优先级完全一样没有差别
- D.谁先启动谁就更加优先
答案:A。nice 值越低,“礼貌程度”越低,越凶、越优先;nice=-10 相当于加急单,nice=10 相当于普通排队。这是 Linux 调度里最容易反直觉的规则,记住“低者优先”。
Q5. 僵尸进程(STAT=Z)的正确处置方式是?
- A.用 kill -9 信号强杀僵尸
- B.终止其父进程,让系统回收← 正确答案
- C.用 renice 改变它的优先级
- D.僵尸无任何影响,可永久放置
答案:B。僵尸进程已经死亡,任何信号都杀不死它(无人收信)。正确做法是终止它的父进程,让 init(PID 1)收养并清理;僵尸虽不占 CPU 和内存,但会占 PID 槽位,不能“永久放置”。
Q6. 下列哪些操作能让任务在断开 SSH 后继续运行?
- A.用 nohup 加 & 启动任务← 正确答案
- B.启动后再用 disown 脱管← 正确答案
- C.直接关闭终端不通知
- D.用 Ctrl+C 中断重放
答案:AB。nohup 让进程忽略 SIGHUP,disown 让进程脱离 shell 的作业表,两者都能让任务在终端断开后存活。直接关闭终端会给进程发 SIGHUP 导致中断;Ctrl+C 是发送 SIGINT 终止进程,不是保活手段。
Q7. top 交互界面中按 k 键的主要作用是?
- A.提示输入 PID 并发送信号← 正确答案
- B.立即退出 top 的监控界面
- C.调整个别进程的 nice 值
- D.按 CPU 占用率重新排序
答案:A。top 的 k 键是“送信”入口,会提示输入 PID 和信号编号,默认 SIGTERM。退出是 q 键,调整优先级是 r 键,按 CPU 排序是 P 键(大写),四者功能不同,别记混。
Q8. 关于 SIGHUP 信号,下列说法正确的是?
- A.终端断开时 shell 会发送它← 正确答案
- B.nohup 能让进程忽略它← 正确答案
- C.它的编号是 9 表示强杀
- D.disown 后进程不再接收它← 正确答案
答案:ABD。终端断开时,shell 会给旗下进程群发 SIGHUP(编号 1),nohup 是屏蔽它,disown 是从作业表移除所以收不到它。编号 9 是 SIGKILL,不是 SIGHUP。
Q9. 一个进程处于 D 状态(不可中断睡眠)且无法被 kill 终止,最可能的原因是?
- A.它在等待磁盘 IO 完成← 正确答案
- B.它根本没有加载内存地址
- C.它被 nohup 的配置拦截
- D.它的优先级低于阈值限制
答案:A。D 状态是内核级的不可中断等待,通常发生在磁盘 IO 等场景,像员工握着水管冲地,任何人喊话都没用。此时进程不响应信号,只能等 IO 完成。这与内存、nohup、优先级无关。
Q10. 关于用 pgrep 与管道 grep 定位进程,正确的说法是?
- A.pgrep 按名字匹配并输出 PID← 正确答案
- B.管道 grep 可能匹配到自身← 正确答案
- C.pgrep 完全等价于 ps -ef
- D.管道拼接结果包含命令行← 正确答案
答案:ABD。pgrep 按名字匹配并直接输出 PID,适合脚本使用;ps aux | grep python 的输出会包含 grep 自身那一行,因为 grep 的进程名也含"grep"关键字,所以还需要 grep -v grep 排除;pgrep 默认只输出 PID 列表,并不等价于 ps -ef。