Linux 进程管理实战从概念到 /proc 透视的完整指南上一期我们讲了软件包的交付解决了软件怎么装上来的问题。软件装好了接下来自然是怎么让它跑起来、看清它跑得怎么样、出问题怎么收拾它——这就是进程管理。本文以 Ubuntu 24.04同样适用于 Rocky 9为演示环境覆盖程序/进程/线程的概念辨析、PID 与进程树、ps/top 两大查看神器、信号与作业控制、CPU 负载与内存的判读最后深入到 /proc 文件系统这个进程透视窗。文章目录Linux 进程管理实战从概念到 /proc 透视的完整指南一、程序、进程、线程三个必须分清的概念二、PID、PPID 与进程树2.1 PID 是什么2.2 用 pstree 看进程树2.3 两个衍生命题孤儿与僵尸2.4 PID 的数量上限三、静态查询三剑客ps / pgrep / pidof3.1 ps进程查询的瑞士军刀3.2 pgrep按名字找人3.3 pidof只要 PID别的不要四、top动态监控的驾驶舱4.1 顶部五行信息区逐行读4.2 交互按键top 启动后按4.3 脚本里用 top五、信号和进程说话的方式5.1 信号是什么5.2 正确用法演示5.3 批量发信号六、前台、后台与暂停作业控制6.1 四个基本操作6.2 关终端不掉线nohup 与 disown七、CPU 负载nproc 与 uptime7.1 先知道有几个核7.2 load average 到底怎么看八、内存与 Swapfree 和 vmstat8.1 free -h先看对列8.2 Swap最后的缓冲垫8.3 vmstat一个命令看全局九、/proc进程的透视窗9.1 /proc 是什么9.2 进程级目录里最常用的几个9.3 系统级的三个常用文件9.4 删了文件空间没释放/proc 破案十、总结一、程序、进程、线程三个必须分清的概念面试常考干活常用但很多人工作几年还是糊的。程序Program躺在磁盘上的一个静态文件。比如/usr/sbin/nginx你不运行它它就是一堆字节不占 CPU、不占内存只占磁盘。进程Process程序的一次执行实例。当你启动 nginx内核把程序加载进内存、分配资源、开始执行——这个活起来的实例就是进程。同一个程序可以同时起多个进程比如你可以开三个 vim 编辑三个文件它们互相独立。线程Thread进程内部的执行流。一个进程至少有一个线程主线程也可以有多个线程并发干活。同一进程内的线程共享内存空间这是线程和进程最本质的区别。打个生活化的比方程序 菜谱纸上的静态文字 进程 按菜谱做菜的整个过程开火、备料、占用厨房 线程 厨房里同时干活的多个人一个切菜、一个看火共用同一个厨房两个硬核知识点记住就够用了进程是资源分配的最小单位内存、文件句柄按进程分配线程是 CPU 调度的最小单位CPU 核心上真正跑来跑去的是线程二、PID、PPID 与进程树2.1 PID 是什么每个进程一出生内核就给它发一个身份证号——PIDProcess ID。所有进程操作查看、发信号、调优先级都靠 PID 定位。PPIDParent PID是这个进程的爹的编号。Linux 的进程不是一盘散沙而是一棵树每个进程都有父亲树的根是PID 1现代发行版上是systemd。# 一眼看清PID 1 是谁ps-p1-opid,ppid,comm# PID PPID COMMAND# 1 0 systemd2.2 用 pstree 看进程树# 带 PID 显示整棵进程树pstree-p# 只看某个进程的子树比如 nginx 的 master 和 workerspstree-p$(pidof nginx|awk{print $1})nginx 的典型结构就是一个 master 进程带几个 worker 子进程在 pstree 里一目了然nginx(1000)───┬──nginx(1001) └──nginx(1002)2.3 两个衍生命题孤儿与僵尸孤儿进程爹先死了孩子还在跑。不用担心——内核会让PID 1systemd收养它负责善后。僵尸进程Zombie孩子死了爹却不去收尸不调用 wait 读退出状态子进程的尸体 task_struct 残留就留在进程表里状态显示为Z。僵尸不占 CPU 和内存但占 PID 名额大量僵尸说明父进程代码有 bug——解法不是 kill 僵尸它已经死了杀不动而是处理它的父进程。2.4 PID 的数量上限cat/proc/sys/kernel/pid_max# 默认通常是 4194304PID 是有限资源。这也是为什么僵尸进程多了会出事——PID 耗尽新进程就 fork 不出来了。三、静态查询三剑客ps / pgrep / pidof3.1 ps进程查询的瑞士军刀两种经典风格输出各有拥趸建议都认识psaux# BSD 风格无短横线最常用ps-ef# SysV 风格能直接看到 PPID 列ps aux的输出逐列拆解USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1000 0.1 0.5 71256 10520 ? Ss 10:00 0:01 nginx: master%CPU / %MEMCPU、内存占用百分比VSZ虚拟内存总量申请的虚的RSS实际常驻物理内存真实的看它STAT进程状态码重点记这几个R运行中/排队运行S可中断睡眠大多数进程的正常状态在等事件D不可中断睡眠通常在等磁盘 IOload 飙升的常客T停止被 CtrlZ 或 SIGSTOP 暂停Z僵尸附加字符s会话首领、高优先级、前台进程实战组合拳# 按 CPU 占用排序取前 10psaux--sort-%cpu|head# 按内存占用排序psaux--sort-%mem|head# 只看指定用户的进程ps-uwww-data3.2 pgrep按名字找人ps aux | grep nginx再用 awk 取 PID 是老写法pgrep 一步到位# 找出 nginx 的所有 PIDpgrep nginx# 连进程名一起显示推荐养成加 -a 的习惯pgrep-anginx# 1000 nginx: master process# 1001 nginx: worker process# 只看某个用户的进程pgrep-uwww-data-a3.3 pidof只要 PID别的不要pidof nginx# 1001 1000输出最干净适合写脚本# 脚本里判断进程是否在跑ifpidof nginx/dev/null;thenechonginx is runningfi三者怎么选要看详细资源占用用ps要按名字拿 PID 并带点信息用pgrep -a脚本里纯取 PID 用pidof。四、top动态监控的驾驶舱静态查询是照片top 是直播top4.1 顶部五行信息区逐行读top - 21:00:01 up 2 days, 3:15, 2 users, load average: 0.52, 0.38, 0.29 Tasks: 218 total, 1 running, 217 sleeping, 0 stopped, 0 zombie %Cpu(s): 3.1 us, 1.2 sy, 0.0 ni, 95.2 id, 0.4 wa, 0.0 hi, 0.1 si, 0.0 st MiB Mem : 7973.2 total, 4210.5 free, 1865.4 used, 1897.3 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 5800.1 avail Memload average1/5/15 分钟平均负载下一章专门讲怎么判读Tasks重点盯zombie不为 0%Cpu(s)各缩写us用户态应用程序干活sy内核态系统调用id空闲wa等 IOwa 持续高 磁盘瓶颈信号st被虚拟化宿主机偷走的时间虚拟机里才有st 高说明宿主机超卖严重Mem重点看最后的avail Mem可用内存不是 free原因应用程序读写磁盘时并不会每次都直接操作磁盘——磁盘比内存慢几个数量级。为了加速内核会在内存中划出两块区域做中转站Cache页缓存缓存读操作。程序读过的文件内容会留在内存里下次再读同一个文件直接从内存返回不再访问磁盘。Buffer缓冲区缓冲写操作。程序要写磁盘的数据先暂存在内存里由内核攒批后统一刷盘减少磁盘 IO 次数。通俗一点的来讲就是应用程序读写磁盘时为了加快读写会在内存中输入缓存或者输出缓存我们称为cache和buff 缓存也会占用内存这也是free -h里要看available而不是free的原因——available已经把可回收的 buff/cache 算进去了它才是应用程序真正还能用多少内存的答案。4.2 交互按键top 启动后按按键作用P按 CPU 排序默认M按内存排序1展开/收起每个 CPU 核心的详情H切换线程视图k给某进程发信号输入 PID默认发 15r调整进程优先级renicec显示完整命令行q退出4.3 脚本里用 toptop 默认是交互式全屏写脚本采集数据要加批处理模式# 只采样一次后退出输出到文本top-b-n1/tmp/top_snapshot.txt如果机器上装了htopsudo apt install htop体验更好彩色、鼠标可点、树形视图。但服务器最小化安装环境往往只有 top所以 top 必须会。五、信号和进程说话的方式5.1 信号是什么信号是内核/进程之间传递的异步通知“请你退出”、“请你重读配置”、“终端断了”……kill命令的中文名误导了无数人——kill 的本职是发信号默认发的是请你退出强杀只是其中一种用法。# 列出全部 64 种信号kill-l64 种里日常只需要记三个信号编号含义类比STERM15礼貌地请进程退出默认“收拾东西正常下班”KILL9内核直接杀死进程无法拦截“保安架出去”HUP1终端挂断对守护进程约定俗成 重读配置“电话断了” / “重新看一遍规则”5.2 正确用法演示# 第一步永远是礼貌请求不带 -9kill1000# 等价于kill-TERM1000# 等几秒进程还在再升级手段kill-91000# 让 nginx 平滑重读配置文件不中断服务kill-HUP$(pgrep-onginx)# 等价于 nginx -s reload为什么 -9 要放到最后TERM 会给进程机会执行清理动作落盘数据、关闭连接、删除锁文件、通知子进程KILL 是内核直接回收进程一句话都来不及说——数据没写完、临时文件残留、锁没释放都是这么来的。kill -9是最后手段不是第一选择。5.3 批量发信号# 按名字杀killall 按精确进程名killallnginx# pkill 更灵活可按用户、终端等条件pkill-utestuser# 踢掉某用户的所有进程pkill-fpython app.py# 按完整命令行匹配pkill -f匹配整个命令行方便但危险——模式写宽了可能误杀动手前先pgrep -af 模式看看会命中谁。六、前台、后台与暂停作业控制在终端里跑的命令默认是前台任务霸占终端你得等它跑完。作业控制Job Control让你在同一终端里调度多个任务。6.1 四个基本操作# 1. 启动时就放后台命令后加 sleep300# 2. 前台任务暂停并扔回后台先 CtrlZ再 bgsleep300# 按 CtrlZ → [1] Stopped sleep 300bg%1# 3. 查看当前终端的所有作业jobs# [1]- Running sleep 300 # [2] Stopped vim notes.txt# 4. 拉回前台继续操作fg%2记一组对照键位按键发送的信号效果CtrlCSIGINT中断请求退出CtrlZSIGTSTP暂停扔到后台停着Ctrl\SIGQUIT退出并产生 core dump6.2 关终端不掉线nohup 与 disown后台任务有个坑终端一关HUP 会发给这个终端的所有作业后台任务跟着死。两种解法# 方法一nohup 免疫 HUP输出重定向到 nohup.outnohup./long_task.shtask.log21# 方法二已在跑的任务用 disown 把它从作业表移除sleep300disown %1生产环境更推荐用 systemd 服务或 tmux/screen 会话来托管长任务tmux 里 CtrlB 再按 D 脱离会话任务照跑tmux attach随时回来——终端作业控制适合临时场景不适合长期驻留。七、CPU 负载nproc 与 uptime7.1 先知道有几个核nproc# 4# 详细版lscpu|grep^CPU(s):7.2 load average 到底怎么看uptime# 21:05:12 up 2 days, 3:20, 2 users, load average: 0.52, 0.38, 0.29三个数分别是1 分钟、5 分钟、15 分钟的平均负载。负载的准确含义是处于运行中R 不可中断睡眠D状态的进程平均数。判读规则一句话负载 ÷ 核数。4 核机器load 4.0 → 每个核刚好满负荷没有排队4 核机器load 8.0 → 平均有 4 个进程在排队等 CPU开始拥堵长期负载/核数 1 → 该扩容或优化了三个数结合看趋势load: 8.0, 4.0, 2.0 ← 负载在飙升1分钟远高于15分钟赶紧查 load: 2.0, 4.0, 8.0 ← 高峰已过正在回落高频误区负载高 ≠ CPU 忙。load 把 **D 状态等磁盘 IO**也算进去了。遇到load 很高但 ussy 很低别盯 CPU 了去看 waIO 等待和磁盘——这就是 vmstat 要干的事。八、内存与 Swapfree 和 vmstat8.1 free -h先看对列free-h# total used free shared buff/cache available# Mem: 7.8Gi 1.8Gi 4.1Gi 12Mi 1.9Gi 5.7Gi# Swap: 2.0Gi 0Bi 2.0Gi新手最常犯的错看到free只剩很少就惊呼内存爆了。错Linux 会把空闲内存拿去做文件缓存buff/cache加速读写需要时立刻释放。判断内存够不够看的是available可回收后真正可用的量不是 free。8.2 Swap最后的缓冲垫内存真不够时内核把不活跃的内存页换到磁盘上的 Swap 区——机器不会立刻 OOMout of memory但会明显变慢磁盘比内存慢几个数量级。# 查看 swap 使用情况swapon--show8.3 vmstat一个命令看全局# 每 1 秒采样一次共 5 次vmstat15procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 4313084 180520 1764580 0 0 12 28 210 380 3 1 95 0 0按列分组记procsr排队等 CPU 的进程数持续 核数 CPU 不够b等 IO 的进程数持续 0 磁盘瓶颈swapsiswap in/soswap out持续大于 0 内存真的不够了在频繁换页这是内存不足的实锤iobi读磁盘 /bo写磁盘块/秒cpuus用户、sy内核、id空闲、wa等 IO、st虚拟化被偷——和 top 里的含义一致一个vmstat 1就能把CPU 忙不忙、内存缺不缺、磁盘卡不卡三件事同时盯起来是性能排查的第一站。九、/proc进程的透视窗9.1 /proc 是什么/proc是一个伪文件系统procfs不占磁盘里面的文件是内核实时生成的数据视图。ps、top、free 这些命令的数据全部来自读 /proc。学会直接读 /proc你就在用和这些工具相同的一手数据。# 每个运行中的进程都有一个以 PID 命名的目录ls/proc/1000/# cmdline environ fd limits status ...9.2 进程级目录里最常用的几个PID1000# 进程的完整启动命令参数用 \0 分隔tr 转换一下cat/proc/$PID/cmdline|tr\0 ;echo# nginx: master process /usr/sbin/nginx# 状态汇总状态、PPID、内存、线程数比 ps 更细cat/proc/$PID/status|head-20# 进程打开的所有文件/网络连接fd 文件描述符ls-l/proc/$PID/fd# 资源限制能看到打开文件数上限这类关键限制cat/proc/$PID/limits# 进程的工作目录ls-l/proc/$PID/cwdfd目录实战价值最高进程报Too many open files、文件删了但磁盘空间没释放文件还被进程占着都是靠它定位的。9.3 系统级的三个常用文件cat/proc/cpuinfo# CPU 型号、核数、主频cat/proc/meminfo# 内存全量数据free 的数据源cat/proc/loadavg# 负载uptime 的数据源9.4 删了文件空间没释放/proc 破案经典故障rm删了一个大日志文件df -h一看空间没回来。原因是文件还被某进程打开着磁盘块要等最后一个引用关闭才释放# 找出所有已删除但仍被占用的文件ls-l/proc/*/fd2/dev/null|grepdeleted# 找到占用进程后重启它空间才会真正释放十、总结这一期从概念到实操走完了进程管理的核心链路三概念程序是静态文件进程是执行实例资源分配单位线程是进程内的执行流CPU 调度单位。进程树PID 定位进程PPID 指认父亲根是 systemdPID 1孤儿被收养僵尸要找父进程算账。查询静态用ps aux看资源/pgrep -a按名找人/pidof脚本取号动态用topP/M 排序、1看核、k发信号。信号kill 是发信号不是只杀人——先 TERM15礼貌请退HUP1重读配置KILL9永远是最后手段。作业控制后台、CtrlZ 暂停、bg/fg/jobs调度长期任务用 nohup、tmux 或 systemd 托管。负载判读uptime三个数除以nproc的核数1 开始排队load 高 CPU 低去查 IO。内存看available不看freevmstat 1的 si/so 持续非零才是内存真不够的实锤。/proc所有监控工具的数据源fd目录专治文件删了空间没释放。到这里我们已经能看清单个进程的一切。但服务器上跑着几十上百个服务怎么让 nginx 开机自启、挂了自动拉起、统一管理日志这就不能只靠手动 kill 和 nohup 了——下一期我们正式进入systemd 服务管理unit 文件编写、systemctl 全家桶、开机自启与崩溃自愈。敬请期待。练习环境Ubuntu 24.04 LTS 虚拟机命令在 Rocky Linux 9 上同样适用