当前位置:首页>Linux>Linux 进程实战:进程启动、查看、结束和后台运行

Linux 进程实战:进程启动、查看、结束和后台运行

  • 2026-09-08 07:48:02
Linux 进程实战:进程启动、查看、结束和后台运行
点击上方
蓝字
关注我,设置星标不迷路哈

上一篇我们讲清楚了 Linux 进程的基础概念:程序和进程的区别、内核如何管理进程、进程地址空间,以及 R、S、D、Z、T 等常见状态。

这一篇继续沿着原来的逻辑往下讲:一个新进程到底是怎么启动的?平时查看、结束、后台运行进程,又该用哪些命令?


第四个问题:进程是怎么启动的?从 0 到 1 说清楚

我们知道了进程是什么,那一个新的进程是怎么来的?总不可能凭空冒出来吧?

在 Linux 里,普通用户态进程通常是由已有进程创建出来的。最早的用户态进程一般是 PID 1,也就是 init 或现代系统里常见的 systemd。其他用户态进程大多都可以沿着父子关系追溯到 PID 1。

需要注意:严格来说,PID 1 也是内核启动用户空间时创建出来的;另外,Linux 内核线程和一些特殊进程的创建方式也不完全等同于普通用户进程。对新手理解日常命令来说,先抓住“父进程创建子进程”这个主线就够了。

Linux 创建新进程最经典的模型,就是 fork() 加 exec()。

我们用一个实际场景说:你登录到 Linux 服务器,敲了一个命令想启动程序,比如:

nginx

这个过程大致会发生什么?

  1. 你登录后的 bash shell 本身就是一个进程。你敲下命令后,shell 收到输入,知道你想启动 nginx。
  2. shell 调用 fork(),创建一个子进程。这个子进程刚创建出来时,很多信息来自父进程,但它会拥有新的 PID。
  3. 子进程再调用 exec() 系列函数,把自己原来的程序映像替换成 nginx 的程序代码和运行环境。
  4. nginx 程序开始执行,一个新的进程就运行起来了。
  5. 如果这是前台命令,shell 通常会等待这个子进程结束;如果你在命令后面加了 &,shell 就不会一直等它,命令会作为后台作业运行。

所以可以这样理解:很多 Linux 程序的启动过程,本质上是“先复制出一个子进程,再把子进程替换成要运行的新程序”。

也就是:

  • fork():创建子进程;
  • exec():加载并执行新的程序;
  • wait() / waitpid():父进程等待并回收子进程退出状态。

我们可以用 pstree 命令看一下进程之间的父子关系:

pstree

输出大概像这样:

systemd─┬─NetworkManager───2*[{NetworkManager}]        ├─nginx───nginx        ├─sshd───sshd───bash───pstree        └─systemd-journal

你会看到,很多进程最终都能追溯到 PID 1 的 systemd 或 init。例如你远程登录服务器时,sshd 会创建会话进程,然后启动 shell;你在 shell 里执行 pstree,所以 pstree 又是 shell 的子进程。


第五个问题:日常操作进程,最常用的命令有哪些?我们实操一下

说了这么多原理,我们来点干货。平时操作进程,最常用的几个命令,给大家总结一下,新手也能直接用。

1. 查看进程:ps 和 top 怎么用?

最常用的命令之一是:

ps aux

这个命令会列出系统中当前进程的一个快照。输出大概长这样:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMANDroot         1  0.0  0.1 168312 10996 ?        Ss   08:00   0:01 /usr/lib/systemd/systemdroot       123  0.0  0.3  82344 24568 ?        S    08:01   0:00 nginx: master process nginxroot       456  0.0  0.1  12345  6789 pts/0    R+   10:23   0:00 ps aux

每一列大概是什么意思?

  • USER:哪个用户启动的进程。
  • PID:进程 ID,排查进程时非常关键。
  • %CPU:CPU 使用率。注意,ps 里的 %CPU 更像一个统计快照,不一定等同于实时瞬时 CPU;如果要看实时变化,建议用 top。
  • %MEM:内存占用比例。
  • VSZ:进程使用的虚拟内存大小。
  • RSS:进程实际驻留在物理内存中的大小。
  • TTY:进程关联的终端。
  • STAT:进程状态,比如 R、S、D、Z、T。
  • START:进程启动时间。
  • TIME:进程累计使用的 CPU 时间。
  • COMMAND:启动这个进程的命令。

这里顺便提醒一下:

ps aux

和

ps -aux

最好不要混用。Linux 上很多时候 ps -aux 也能输出类似结果,但从标准和兼容性角度看,推荐使用 ps aux 或者更明确的 ps -ef。

如果想动态查看进程状态,可以用:

top

top 会周期性刷新系统负载、CPU、内存和进程列表。不同系统默认刷新间隔可能不同,常见默认值是几秒一次,也可以在 top 内调整。

常用操作:

  • 按 q:退出;
  • 按 P:按 CPU 使用率排序;
  • 按 M:按内存使用率排序;
  • 按 k:输入 PID 后给进程发送信号;
  • 按 1:展开查看每个 CPU 核心的使用情况。

排查系统卡慢时,通常第一步就是用 top 或类似工具看:到底是 CPU 打满、内存不足、I/O 等待高,还是某个进程异常。

2. 结束进程:kill、killall 怎么用?

找到你要处理的进程 PID 之后,可以用 kill 给它发送信号。注意,kill 的本质不是“直接杀死”,而是“向进程发送信号”。

常用写法如下:

kill PID

默认发送的是 SIGTERM,也就是 15 号信号。它的意思是告诉进程:“请你正常退出。”这是一种相对温和的方式,进程可以在退出前保存数据、关闭连接、清理临时文件。日常操作建议优先使用这种方式。

如果普通 kill 没效果,再考虑:

kill -9 PID

kill -9 发送的是 SIGKILL,也就是 9 号信号。这个信号不能被进程捕获、阻塞或忽略,内核会强制结束目标进程。

但不建议一上来就用 kill -9,因为它不给进程做清理工作的机会,可能造成临时文件残留、事务中断、数据未刷盘等问题。

还可以按进程名处理:

killall nginx

这会向所有匹配名称的 nginx 进程发送信号。它很方便,但也要小心,因为名字匹配可能影响多个进程。生产环境执行前,建议先用下面的命令确认:

pgrep -a nginx

举个例子:我要结束 PID 为 123 的进程,先温和地尝试:

kill 123

如果确认它无法正常退出,再强制处理:

kill -9 123

3. 把进程放后台运行:& 和 nohup 怎么用?

很多新手会遇到一个问题:

我在 SSH 里启动了一个程序,SSH 一断开,程序也跟着退出了,这是为什么?

原因通常是:这个程序仍然挂在当前 shell 会话或终端上。终端关闭、会话结束时,相关进程可能收到 SIGHUP 信号,或者因为标准输入输出断开而退出。

如果只是想让命令在后台运行,可以在命令后加 &:

./你的程序 &

& 的作用是把程序作为后台作业启动,这样当前终端还能继续输入命令。

但仅仅加 & 不一定能保证你退出 SSH 后程序还继续运行。因为它仍然可能受到会话结束、终端关闭、输出断开等影响。

更常见的写法是:

nohup ./你的程序 > app.log 2>&1 &

这里分开看:

  • nohup:让程序忽略挂断信号 SIGHUP;
  • &:把程序放到后台运行;
  • > app.log:把标准输出写到 app.log;
  • 2>&1:把标准错误也重定向到标准输出,也就是同一个日志文件。

如果你不手动指定日志文件,nohup 通常会把输出写到 nohup.out,但生产环境更建议明确指定日志路径,方便排查问题。

需要注意:nohup 适合临时任务。如果是长期运行的服务,更推荐用 systemd、Supervisor、容器编排、进程守护工具等方式管理,而不是长期依赖一个手工执行的 nohup 命令。


常见问题解答,你可能也遇到过

最后我们整理几个后台常问的问题,统一解答一下。

Q:为什么我的某个进程占了 100% CPU?怎么回事?

A:原因不一定只有死循环,也可能是程序正在做大量计算、被压测、线程池繁忙、日志过多、GC 异常、加解密任务过重,或者确实遇到了 bug。

排查思路可以这样来:

  1. 用 top 找到 CPU 占用最高的 PID;
  2. 用 ps -fp PID 看清楚它是什么程序;
  3. 查看程序日志;
  4. 如果是 Java、Go、Python 等服务,再结合对应语言的诊断工具进一步分析;
  5. 如果确认异常,再考虑重启或发布修复版本。

不要看到 100% CPU 就马上 kill -9。先判断它是在正常忙,还是异常忙。

Q:僵尸进程太多会有什么问题?怎么解决?

A:每个僵尸进程会占用一个 PID 和少量进程表信息。系统 PID 是有限的,如果僵尸进程太多,可能导致新的进程无法创建。

解决方法不是直接杀僵尸进程,因为它已经退出了,普通 kill 对它没用。

正确思路是:

  1. 用 ps -ef | grep defunct 或 ps aux | grep Z 找到僵尸进程;
  2. 查看它的父进程 PID;
  3. 判断父进程是什么服务;
  4. 优先修复或重启父进程,让它正确回收子进程;
  5. 必要时在维护窗口重启相关服务,最后才考虑重启系统。

Q:D 状态的进程为什么杀不掉?怎么处理?

A:D 状态是不可中断睡眠。进程通常卡在内核态 I/O 等待里,信号不会立即生效,所以 kill -9 也可能看起来“杀不掉”。

如果 D 状态进程一直不消失,优先排查:

  • 磁盘是否故障;
  • 文件系统是否卡住;
  • NFS、iSCSI、Ceph 等存储是否异常;
  • 内核日志里是否有 I/O error;
  • 是否有大量进程同时等待同一个存储资源。

常用排查命令包括:

dmesg -T | tail -100
iostat -x 1
df -h
mount

如果底层 I/O 恢复,很多 D 状态进程会继续执行或退出。如果存储长时间无法恢复,可能需要重启相关服务,严重时需要重启系统。

Q:前台进程怎么切回后台?

A:如果一个进程正在前台运行,你可以按:

Ctrl + Z

这会把进程暂停,而不是继续在后台跑。

然后输入:

bg

让它在后台继续运行。

如果你想再切回前台,输入:

fg

这个操作常用于临时处理命令行任务。但如果是重要的长期任务,还是建议一开始就规划好运行方式,比如 systemd、tmux、screen 或守护进程管理工具。


写在最后

其实 Linux 进程说来说去,核心逻辑就是:

程序是静态的,进程是程序运行起来后的执行实例;内核通过进程描述符管理每个进程;每个进程有独立的虚拟地址空间;不同进程状态对应不同的运行阶段。

把这些基础概念搞懂了,再去看进程调度、进程通信、查看进程、结束进程、后台运行这些操作,就不会一头雾水了。它们本质上都是建立在同一套进程模型之上的。

日常排查时,你可以先记住这条主线:

  1. 先用 ps、top 找到进程;
  2. 再看它的状态、PID、父进程和资源占用;
  3. 能温和退出就不要直接 kill -9;
  4. 遇到僵尸进程查父进程;
  5. 遇到 D 状态优先查 I/O;
  6. 长期任务尽量交给专业的进程管理工具。

把这几条用熟,你就已经能处理大部分 Linux 进程相关的入门问题了。

END

往期推荐

Linux 进程基础:程序、进程、PCB、地址空间和进程状态

yum 安装包为什么总和镜像源有关?换源、离线安装和生产环境避坑(下)

yum 安装包为什么总和镜像源有关?先搞懂 Linux 软件仓库这套逻辑(上)

为什么 Linux 的目录这么奇怪?终于有人讲明白了

为什么 Linux 要用“挂载”?而不是直接显示 C 盘、D 盘?

最新文章

随机文章