Linux 进程管理实战指南从基础概念到高级排查引言在 Linux 运维和开发中进程管理和系统负载监控是必修的核心技能。很多初学者容易把“程序”、“软件”和“进程”混为一谈或者在面对死循环进程、杀不掉的程序、僵尸进程以及系统负载飙升时束手无策。本文将以 CentOS 7 环境为基础结合实战案例系统性地带你掌握 Linux 进程管理的全链路知识点。一、 进程基础概念与生命周期1. 程序、软件与进程的区别在日常交流中我们经常用错概念理解它们的区别是第一步程序放在磁盘上没有运行的可执行文件。软件包含了程序、说明书手册、配置文件等一整套东西的集合。进程程序运行起来后的实例。它会占用系统的 CPU、内存、磁盘、网络等资源。线程现代操作系统将进程划分为更小的执行单元一个进程可以包含多个线程。2. 进程由什么组成一个进程不仅仅是运行的一行代码它在内核中包含已分配内存的地址空间。安全属性如 UID、权限凭据。程序代码的一个或多个执行线程。进程状态如运行、睡眠、停止等。环境变量、调度上下文、分配的系统资源如文件描述符、网络端口。3. 进程是如何诞生的Fork 机制在 Linux 中新进程是通过“复制”父进程产生的这种机制叫做fork。例如你在 终端中执行sleep 5时当前的 进程就是父进程而sleep就是它fork出来的子进程。最核心的规则杀死父进程子进程不一定消失变为孤儿进程但杀死子进程父进程通常能感知到并回收其状态。二、 进程的“喜怒哀乐”——状态详解操作系统的四大核心职责是任务管理、设备管理、文件系统、内存管理。在这个过程中进程会在不同状态间流转R (Running/Runnable)正在 CPU 上运行或正处于运行队列中等待分配 CPU。S (Sleeping)可中断睡眠。进程正在等待某个事件如等待 I/O 完成、等待键盘输入。这是后台服务最常见的状态。D (Disk Sleep)不可中断睡眠。通常是在等待磁盘读写操作。危险信号如果系统里出现大量 D 状态进程说明磁盘 I/O 可能已经卡死。T (Stopped)暂停/停止状态。通常是被CtrlZ挂起或者被调试器暂停。Z (Zombie)僵尸状态。子进程已经退出但父进程没有读取其退出状态码导致进程描述符残留。三、 查看进程ps命令的高阶玩法ps命令是查看进程的核心工具它支持三种不同风格的选项UNIX 单破折号-、GNU 双破折号--、BSD 无破折号。1. 基础信息查看# 查看所有进程的 PID、TTY、CPU 时间和命令名ps-e# 查看标准长格式含 UID、PID、PPID、STIME 启动时刻、C 等ps-ef|head-n5# 这里的 PPID 非常重要它是父进程 PID2. 精确筛选特定进程# 查看特定用户 (xianyu) 运行的进程并显示 CPU/内存占用详情ps-uxianyu u# 查看特定终端 (pts/1) 下的进程ps-tpts/1 u# 查看系统所有进程最常用的命令组合psaxu3. 查看进程树与自定义排序通过树状结构你能一目了然看清进程之间的父子关系。# 查看进程树psaxf# 查看特定进程的属性如只输出 PID、CPU%、内存%、命令ps-opid,%cpu,%mem,command1159# 对进程按 CPU 使用率降序排列psaxu--sort-%cpu|head-n5四、 作业控制前台、后台与断网保活一个终端默认只能有一个前台进程独占输入输出但你可以把耗时的任务放到后台去跑。1. 后台运行与作业管理使用符号可以让命令在后台运行。# 写一个死循环脚本用于测试catEOF/usr/local/bin/study#!/bin/ while true do echo $(date): Im studying [ $ ] study.log sleep 1 done EOFchmodx /usr/local/bin/study# 启动任务study Linux# 后台运行返回 job 编号 [1] 和 PIDstudy Python# 前台运行此时按 CtrlZ 暂停jobs# 查看后台的任务列表bg%2# 将编号为 2 的后台暂停任务放到后台继续运行fg%1# 将编号为 1 的后台任务调回前台运行特别注意像passwd这种需要交互输入密码的进程无法在后台运行。如果你尝试passwd 系统会立刻自动挂起它并进入停止状态。2. 防止断网导致任务中断如果你在远端 SSH 服务器上运行一个耗时 2 小时的任务如打补丁一旦本地网络断开或终端意外关闭这些子进程会被系统挂起甚至杀死。简单方案nohupnohup study English 即使终端退出任务也会继续在后台执行输出会默认写入nohup.out。进阶神器screen可以创建一个独立的虚拟终端即使断开连接任务也能恢复。yuminstall-yscreenscreen# 进入一个新的虚拟终端在里面执行任务# 按 CtrlA, 然后按 D 分离注销当前 screen 会话screen-ls# 查看会话列表screen-r40398.pts-7.centos7# 重新连接回对应的会话# 在 screen 内部输入 exit 即可结束该会话五、 信号与进程控制kill、pkill与pgrep1. 信号Signal入门信号是传递给进程的软中断。Linux 系统有几十种信号通过kill -l可以查看所有列表。最常用的几个信号SIGTERM(15)终止信号默认。请求进程优雅退出可以理解为“请你关机”。SIGKILL(9)强制杀死。进程无法忽略或捕获强制执行“拔电源”操作。SIGSTOP(19)暂停进程。SIGCONT(18)继续运行被暂停的进程。2.kill命令的使用# 创建测试进程sleep1231sleep1232# 暂停作业 1kill-19%1jobs# 显示为 [1] 已停止# 继续运行作业 1kill-18%1jobs# 显示为 [1] 运行中# 优雅终止作业 2不加信号默认为 -15kill%23.pkill与pgrep的批量操作pkill和pgrep用于根据进程名、用户、终端等条件批量处理进程免去一个一个找 PID 的麻烦。# 根据进程名查找 PIDpgrep-lsleep# 结果3517 sleep, 3518 sleep# 根据终端踢出用户所有进程pkill-tpts/0# 根据父进程 (PPID) 杀死所有子进程pkill-P36644. 拓展whoami,who,w,last查看系统当前登录状态whoami当前用户名。who当前登录的详细信息来源 IP、时间等。w比who更详细包含 CPU 负载和正在执行的命令。last系统历史登录记录查看有没有异常 IP 曾尝试登录。六、 疑难杂症案例为什么进程“杀不掉”现象你执行了kill进程确实被杀了但过了几秒钟它又自动“复活”了并且不断消耗 CPU。怎么彻底干掉它模拟案例bin/mm脚本mkdirbincatbin/mmEOF #!/bin/ while true do md5sum /dev/zero /dev/null sleep 1 done EOFchmodx bin/mmnohupmmmm脚本每休眠 1 秒就会派发一个md5sum进程这会导致系统里不断出现md5sum进程并且它们占满了 CPU彻底的杀除思路断其臂删除程序如果程序不需要了直接禁用或删掉命令如mv /bin/md5sum ./这样即使脚本启动也找不到工具。寻其根杀死“幕后推手”脚本是靠父进程MM不断重生子进程的。我们不仅要杀死子进程md5sum还必须杀掉父进程mm。# 找出父子进程关系psax-f|grep-emd5sum-ePPID# 同时杀掉父进程和子进程kill7355675538# PID 替换为实际父进程和子进程的 PID七、 特殊进程僵尸进程与孤儿进程1. 僵尸进程Zombie Process子进程退出了但父进程没有去“收尸”读取子进程的退出状态码子进程就会进入Z状态。它的内存等资源已释放但进程描述符PCB还在占用 PID 资源。模拟代码zombies.c#includestdio.h#includestdlib.h#includeunistd.hintmain(){pid_tidfork();if(id0){// 父进程sleep(60);}elseif(id0){// 子进程sleep(10);exit(EXIT_SUCCESS);}return0;}[rootcentos-xianyu ~19:05:06]# vim zombies.c[rootcentos-xianyu ~19:20:23]# gcc zombies.c -o zombies[rootcentos-xianyu ~19:20:36]# ./zombies[rootcentos-xianyu ~19:23:52]# ps axu | grep zombiesroot122120.00.01573402216pts/1 S19:210:00watch-n1ps-ef|grepzombies|grep-vgreproot130590.00.04212352pts/0 S19:230:00 ./zombies root130600.00.000pts/0 Z19:230:00[zombies]defunctroot132060.00.0112824984pts/2 R19:240:00grep--colorauto zombies危害如果服务器上出现大量Z状态进程并且父进程不回收系统的最大 PID 数量kernel.pid_max会被耗尽导致无法创建新进程。2. 孤儿进程Orphan Process父进程先意外退出子进程还在运行那么这些子进程就成了“孤儿”。模拟代码lonely.c#includestdio.h#includestdlib.h#includeunistd.hintmain(){pid_tidfork();if(id0){perror(fork);return1;}elseif(id0){// parent// printf(parent[%d] is sleeping ...\n,getpid());printf(I am child, pid:%d\n,getpid());sleep(60);}else{// parentprintf(I am parent,pid:%d\n,getpid());sleep(3);}return0;}# 新建终端,监控进程[rootcentos-xianyu ~18:40:44]# watch -n 1 ps -ef | grep lonely | grep -v grep# 执行下列命令后切换到监控终端[rootcentos-xianyu ~18:29:22]# yum install -y gcc[rootcentos-xianyu ~18:32:01]# vim lonely.c[rootcentos-xianyu ~18:44:37]# gcc lonely.c -o lonely[rootcentos-xianyu ~18:45:39]# ./lonelyI am parent,pid:7091 I am child, pid:7092父进程 sleep 3 秒后退出子进程 sleep 60 秒。子进程会被系统的1号进程systemd领养。危害孤儿进程本身无害但如果业务代码不严谨持续不断产生孤儿进程会导致 1 号进程的资源开销增大建议从代码层面优化或者定期清理无用的孤儿进程。