Linux 进程管理详解
目录
进程介绍
- 进程是什么
- 进程产生 - fork
- 进程状态
查看进程 - ps 命令
- 常用选项
- 查看特定进程
- 进程排序
控制 jobs
- 前台进程和后台进程
- 前后台切换
- nohup 和 screen
给进程发信号
- 信号介绍
- kill 命令
- pkill 和 pgrep 命令
- 用户登录命令
特殊进程
- 僵尸进程
- 孤儿进程
监控系统负载
- 系统负载介绍
- 查看系统负载
1. 进程介绍
1.1 进程是什么
进程是已启动的可执行程序的运行中实例。进程由以下组成部分:
- 已分配内存的地址空间
- 安全属性,包括所有权凭据和特权
- 程序代码的一个或多个执行线程
- 进程状态
[gg@centos7 ~15:46:47]$ls-l/bin/bash -rwxr-xr-x.1root root1152440Aug312022/bin/bash# bash 是程序,执行后变成进程[gg@centos7 ~15:46:52]$psaux|grepbash|grep-vgrepgg20000.00.11156524324pts/0 Ss15:450:00-bash程序 vs 进程 vs 线程:
| 概念 | 说明 |
|---|---|
| 程序 | 没有运行的可执行文件(如/bin/bash) |
| 进程 | 程序运行后的实例,占用 CPU、内存等资源 |
| 线程 | 进程内更小的执行单元,共享进程资源 |
1.2 进程产生 - fork
Linux 中所有进程都是通过fork系统调用创建的,每个进程都有一个父进程:
# 当前 bash 进程产生 sleep 子进程[gg@centos7 ~15:47:00]$sleep5&[1]2050# 查看进程父子关系[gg@centos7 ~15:47:05]$ps-ef|grepsleep|grep-vgrepgg20502000015:47 pts/0 00:00:00sleep5# PPID=2000 是 bash 的 PID(父进程)# PID=2050 是 sleep 的 PID(子进程)1.3 进程状态
进程状态说明:
| 状态 | 说明 |
|---|---|
| R(Running) | 运行中或就绪状态 |
| S(Sleeping) | 可中断睡眠(等待事件完成) |
| D(Disk Sleep) | 不可中断睡眠(等待IO) |
| T(Stopped) | 暂停或跟踪状态 |
| Z(Zombie) | 僵尸进程(已终止但未被回收) |
| I(Idle) | 空闲状态 |
# 查看进程状态[gg@centos7 ~15:47:12]$psaux|head-5USERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root10.00.11936886728? Ss15:400:01 /usr/lib/systemd/systemd root20.00.000? S15:400:00[kthreadd]root30.00.000? I<15:400:00[rcu_gp]root40.00.000? I<15:400:00[rcu_par_gp]2. 查看进程 - ps 命令
2.1 常用选项
ps 命令支持三种选项风格:
| 风格 | 示例 |
|---|---|
| UNIX | ps -ef |
| GNU | ps --help |
| BSD | ps aux |
# 查看所有进程(UNIX风格)[gg@centos7 ~15:47:20]$ps-e|head-5PID TTY TIME CMD1? 00:00:01 systemd2? 00:00:00 kthreadd3? 00:00:00 rcu_gp4? 00:00:00 rcu_par_gp# 查看所有进程详细信息(UNIX风格)[gg@centos7 ~15:47:25]$ps-ef|head-5UIDPIDPPIDC STIME TTY TIME CMD root10015:40 ? 00:00:01 /usr/lib/systemd/systemd root20015:40 ? 00:00:00[kthreadd]root32015:40 ? 00:00:00[rcu_gp]root42015:40 ? 00:00:00[rcu_par_gp]# 查看所有进程详细信息(BSD风格)[gg@centos7 ~15:47:30]$psaux|head-5USERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root10.00.11936886728? Ss15:400:01 /usr/lib/systemd/systemd root20.00.000? S15:400:00[kthreadd]root30.00.000? I<15:400:00[rcu_gp]root40.00.000? I<15:400:00[rcu_par_gp]ps 输出字段说明:
| 字段 | 说明 |
|---|---|
| PID | 进程 ID |
| PPID | 父进程 ID |
| UID | 进程执行者 |
| %CPU | CPU 使用率 |
| %MEM | 内存使用率 |
| VSZ | 虚拟内存大小 |
| RSS | 实际内存大小 |
| TTY | 终端设备 |
| STAT | 进程状态 |
| START | 启动时间 |
| TIME | CPU 使用时间 |
2.2 查看特定进程
# 查看特定用户的进程[gg@centos7 ~15:47:37]$ps-ugg uUSERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND gg20000.00.11156524324pts/0 Ss15:450:00-bashgg20550.00.0112824988pts/0 R+15:470:00ps-ugg u# 查看特定终端的进程[gg@centos7 ~15:47:42]$ps-tpts/0 uUSERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND gg20000.00.11156524324pts/0 Ss15:450:00-bashgg20580.00.0112824984pts/0 R+15:470:00ps-tpts/0 u# 查看进程树[gg@centos7 ~15:47:47]$psaxf|grep-A2sshd1159? Ss0:00 /usr/sbin/sshd-D2000? Ss0:00\_ sshd: gg@pts/02001pts/0 Ss0:00\_-bash# 查看特定进程的特定属性[gg@centos7 ~15:47:52]$ps-opid,%cpu,%mem,command1159PID %CPU %MEM COMMAND11590.00.1/usr/sbin/sshd-D# 通过进程名查找进程[gg@centos7 ~15:47:57]$ps-Cbash-opid,ruser,euser,command PID RUSER EUSER COMMAND2001gg gg-bash2.3 进程排序
# 按 CPU 使用率降序排序[gg@centos7 ~15:48:02]$psaxu--sort-%cpu|head-5USERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root12000.20.325750813040? Ss15:400:01 /usr/bin/vmtoolsd root11590.00.11128244504? Ss15:400:00 /usr/sbin/sshd-Droot10.00.11936886728? Ss15:400:01 /usr/lib/systemd/systemd# 按内存使用率降序排序[gg@centos7 ~15:48:07]$psaxu--sort-%mem|head-5USERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root12000.20.325750813040? Ss15:400:01 /usr/bin/vmtoolsd root10.00.11936886728? Ss15:400:01 /usr/lib/systemd/systemd root11590.00.11128244504? Ss15:400:00 /usr/sbin/sshd-D3. 控制 jobs
3.1 前台进程和后台进程
作业控制允许单个 shell 实例运行和管理多个命令:
| 类型 | 说明 |
|---|---|
| 前台进程 | 可以读取输入和响应键盘信号,一个终端只有一个前台进程 |
| 后台进程 | 在后台运行,不能读取终端输入,可能暂停或运行 |
# 创建后台进程(使用 &)[gg@centos7 ~15:48:15]$sleep100&[1]2065# 查看后台作业[gg@centos7 ~15:48:20]$jobs[1]+ 运行中sleep100&# 创建前台进程(直接运行)[gg@centos7 ~15:48:25]$sleep200# 按 Ctrl+C 终止前台进程^C3.2 前后台切换
# 前台进程暂停(Ctrl+Z)[gg@centos7 ~15:48:32]$sleep300^Z[1]+ 已停止sleep300# 查看作业状态[gg@centos7 ~15:48:37]$jobs[1]+ 已停止sleep300# 将作业放到后台运行[gg@centos7 ~15:48:42]$bg%1[1]+sleep300&# 查看作业状态[gg@centos7 ~15:48:47]$jobs[1]+ 运行中sleep300&# 将后台作业调到前台[gg@centos7 ~15:48:52]$fg%1sleep300# 按 Ctrl+C 终止^C# 创建多个后台进程[gg@centos7 ~15:48:57]$sleep100&[1]2070[gg@centos7 ~15:49:00]$sleep200&[2]2071[gg@centos7 ~15:49:03]$sleep300&[3]2072# 查看所有作业[gg@centos7 ~15:49:07]$jobs[1]运行中sleep100&[2]- 运行中sleep200&[3]+ 运行中sleep300&# 终止特定作业[gg@centos7 ~15:49:12]$kill%2# 查看作业状态[gg@centos7 ~15:49:17]$jobs[1]运行中sleep100&[2]- 已终止sleep200[3]+ 运行中sleep300&3.3 nohup 和 screen
nohup - 防止断网导致进程终止:
# 使用 nohup 运行后台进程[gg@centos7 ~15:49:25]$nohupsleep3600&[1]2075nohup: 忽略输入并把输出追加到"nohup.out"# 查看输出文件[gg@centos7 ~15:49:30]$catnohup.outscreen - 终端多路复用器:
# 安装 screen[gg@centos7 ~15:49:37]$sudoyuminstall-yscreen# 创建 screen 会话[gg@centos7 ~15:49:42]$screen# 在 screen 中运行命令[gg@centos7 ~15:49:47]$sleep1234# 按 Ctrl+A+D 分离会话[detached from2080.pts-0.centos7]# 查看 screen 会话[gg@centos7 ~15:49:55]$screen-lsThere is ascreenon:2080.pts-0.centos7(Detached)1Socketin/run/screen/S-gg.# 重新连接会话[gg@centos7 ~15:50:00]$screen-r2080# 关闭 screen 会话(在会话中执行)[gg@centos7 ~15:50:05]$exit[screen is terminating]4. 给进程发信号
4.1 信号介绍
信号是传递给进程的软中断,可以由错误、外部事件或命令产生:
# 查看所有信号[gg@centos7 ~15:50:12]$kill-l1)SIGHUP2)SIGINT3)SIGQUIT4)SIGILL5)SIGTRAP6)SIGABRT7)SIGBUS8)SIGFPE9)SIGKILL10)SIGUSR111)SIGSEGV12)SIGUSR213)SIGPIPE14)SIGALRM15)SIGTERM16)SIGSTKFLT17)SIGCHLD18)SIGCONT19)SIGSTOP20)SIGTSTP21)SIGTTIN22)SIGTTOU23)SIGURG24)SIGXCPU25)SIGXFSZ26)SIGVTALRM27)SIGPROF28)SIGWINCH29)SIGIO30)SIGPWR31)SIGSYS34)SIGRTMIN35)SIGRTMIN+136)SIGRTMIN+237)SIGRTMIN+3常用信号:
| 信号 | 名称 | 说明 |
|---|---|---|
| 1 | SIGHUP | 终端断开,进程收到该信号后重启 |
| 2 | SIGINT | 中断信号(Ctrl+C) |
| 9 | SIGKILL | 强制终止(不可忽略) |
| 15 | SIGTERM | 默认终止信号(可忽略) |
| 18 | SIGCONT | 继续运行(恢复暂停进程) |
| 19 | SIGSTOP | 暂停进程(不可忽略) |
4.2 kill 命令
# 创建测试进程[gg@centos7 ~15:50:20]$sleep100&[1]2085# 发送 SIGSTOP 信号(暂停进程)[gg@centos7 ~15:50:25]$kill-19%1# 查看作业状态[gg@centos7 ~15:50:30]$jobs[1]+ 已停止sleep100# 发送 SIGCONT 信号(继续运行)[gg@centos7 ~15:50:35]$kill-18%1# 查看作业状态[gg@centos7 ~15:50:40]$jobs[1]+ 运行中sleep100&# 发送 SIGTERM 信号(默认终止)[gg@centos7 ~15:50:45]$kill-15%1# 查看作业状态[gg@centos7 ~15:50:50]$jobs[1]+ 已终止sleep100# 使用 PID 发送信号[gg@centos7 ~15:50:55]$sleep200&[1]2090# 发送默认信号(SIGTERM)[gg@centos7 ~15:51:00]$kill2090# 查看作业状态[gg@centos7 ~15:51:05]$jobs[1]+ 已终止sleep200# 使用 SIGKILL 强制终止[gg@centos7 ~15:51:10]$sleep300&[1]2095# 强制终止(不可忽略)[gg@centos7 ~15:51:15]$kill-92095[1]+ 已杀死sleep3004.3 pkill 和 pgrep 命令
# 创建多个进程[gg@centos7 ~15:51:22]$sleep1231&sleep1232&sleep1233&[1]2098[2]2099[3]2100# 使用 pgrep 查找进程(仅显示 PID)[gg@centos7 ~15:51:27]$ pgrepsleep209820992100# 使用 pgrep -l 显示 PID 和进程名[gg@centos7 ~15:51:32]$ pgrep-lsleep2098sleep2099sleep2100sleep# 使用 pkill 终止所有 sleep 进程[gg@centos7 ~15:51:37]$pkillsleep[1]已终止sleep1231[2]- 已终止sleep1232[3]+ 已终止sleep1233# 根据用户名查找进程[gg@centos7 ~15:51:42]$ pgrep-ugg2001# 根据终端查找进程[gg@centos7 ~15:51:47]$ pgrep-tpts/0-l2001bash# 根据父进程 ID 查找子进程[gg@centos7 ~15:51:52]$psjf|head-5PPIDPID PGID SID TTY TPGID STATUIDTIME COMMAND1159200020002000?-1Ss10000:00 sshd: gg@pts/02000200120012001pts/02106Ss10000:00\_-bash2001210621062001pts/02106R+10000:00\_psjf# 根据 PPID 终止子进程[gg@centos7 ~15:52:00]$pkill-P2001# 使用 ps 和 kill 配合终止进程[gg@centos7 ~15:52:05]$sleep100&[1]2108# 使用管道终止进程[gg@centos7 ~15:52:10]$kill-9$(pgrepsleep)[1]+ 已杀死sleep1004.4 用户登录命令
# 当前登录用户[gg@centos7 ~15:52:17]$whoamigg# 当前系统登录用户详细信息[gg@centos7 ~15:52:22]$whogg pts/02026-07-2115:45(10.1.8.1)# 当前系统登录用户详细信息(含负载)[gg@centos7 ~15:52:27]$ w15:52:27 up12min,1user, load average:0.00,0.01,0.05USERTTY FROM LOGIN@ IDLE JCPU PCPU WHAT gg pts/010.1.8.115:451.00s0.12s0.00s w# 用户登录历史记录[gg@centos7 ~15:52:32]$ last|head-5gg pts/010.1.8.1 Mon Jul2115:45 still loggedingg pts/010.1.8.1 Mon Jul2115:30 -15:40(00:10)rebootsystem boot3.10.0-1160.el7.x86_64 Mon Jul2115:40 -15:52(00:12)5. 特殊进程
5.1 僵尸进程
僵尸进程:进程已终止,但父进程未回收其资源(PID 仍占用)。
# 创建僵尸进程(父进程不调用 wait())[gg@centos7 ~15:52:40]$cat<<'EOF'>zombie.sh#!/bin/bash for i in {1..3}; do sleep 1 & done # 不等待子进程结束,直接退出 EOF# 查看僵尸进程(状态为 Z)[gg@centos7 ~15:52:45]$psaux|grep'Z'僵尸进程的危害:
- 占用 PID 资源(系统 PID 数量有限)
- 无法被 kill 命令终止
解决方法:
- 重启父进程(让 init/systemd 回收僵尸进程)
- 杀死父进程(僵尸进程变为孤儿进程,由 init/systemd 回收)
5.2 孤儿进程
孤儿进程:父进程先于子进程终止,子进程被 init/systemd 接管。
# 创建孤儿进程(父进程先退出)[gg@centos7 ~15:52:52]$cat<<'EOF'>orphan.sh#!/bin/bash sleep 100 & echo "子进程 PID: $!" # 父进程直接退出 EOF# 运行脚本[gg@centos7 ~15:52:57]$bashorphan.sh 子进程 PID:2115# 查看子进程(PPID 变为 1,被 systemd 接管)[gg@centos7 ~15:53:02]$ps-ef|grep2115|grep-vgrepgg21151015:52 ? 00:00:00sleep100孤儿进程的特点:
- PPID 变为 1(init/systemd)
- 不会造成资源泄漏
- 子进程结束后会被 init/systemd 正常回收
6. 监控系统负载
6.1 系统负载介绍
系统负载表示系统中正在运行和等待运行的进程数量:
| 数值 | 说明 |
|---|---|
| load average: 0.00, 0.01, 0.05 | 分别表示 1 分钟、5 分钟、15 分钟内的平均负载 |
判断标准:
- 负载 < CPU 核心数:系统正常
- 负载 ≈ CPU 核心数:系统繁忙
- 负载 > CPU 核心数:系统过载
6.2 查看系统负载
# 查看系统负载(uptime)[gg@centos7 ~15:53:10]$uptime15:53:10 up13min,1user, load average:0.00,0.01,0.05# 查看系统负载(w)[gg@centos7 ~15:53:15]$ w15:53:15 up13min,1user, load average:0.00,0.01,0.05# 查看 CPU 核心数[gg@centos7 ~15:53:20]$ nproc1# 查看详细系统信息[gg@centos7 ~15:53:25]$cat/proc/cpuinfo|grepprocessor|wc-l1# 使用 top 实时监控系统负载[gg@centos7 ~15:53:30]$toptop-15:53:30 up13min,1user, load average:0.00,0.01,0.05Tasks:97total,1running,96sleeping,0stopped,0zombie %Cpu(s):0.0us,0.0sy,0.0ni,100.0 id,0.0wa,0.0hi,0.0si,0.0st KiB Mem:1863268total,1200000free,200000used,463268buff/cache KiB Swap:2097148total,2097148free,0used. PIDUSERPR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND2001gg20011565243243260S0.00.20:00.05bash# 按 q 退出