Skip to content

进程管理与日常命令

ps 进程查询、kill 信号机制(-9 vs -15)、nohup 后台守护与 systemctl 服务管理。

Updated View as Markdown
For humans

进程管理与日常命令

校招考察频度:★ 高频(面试高频必考·生产运维生命线) 一句话速记:ps -ef 看父子关系(PPID),ps aux 看 CPU/内存(RSS/VSZ);kill -15 是优雅停机通知,kill -9 是内核强制处决;nohup ... & 避开 SIGHUP 挂断信号保证终端断开不掉线;现代化服务用 Systemd 托管实现故障自愈。

后端应用无论采用 Java、Python 还是 Go 编写,打包发布到服务器后均以“操作系统进程(Process)”的形式运行。掌握进程的检索、状态监控、优雅停止与持久化托管,是后端开发工程师的基本能力要求。


一、进程查看与定位

1. ps -ef vs ps aux 的区别与字段解析

在 Linux 中,ps(Process Status)用于报告当前系统的进程状态快照。两者源于不同的历史 Unix 标准,面试中常被考察字段差异:

# System V 风格(习惯带减号 -)
ps -ef | grep java

# BSD 风格(习惯不带减号)
ps aux | grep java
字段名称来源模式含义与重点关注
UID / USER两者皆有运行该进程的用户身份(非 root 运行是基本安全准则)
PID两者皆有进程唯一标识号(操作 kill 时必须指定的目标)
PPIDps -ef 独有父进程 ID(排查进程由谁衍生、定位孤儿/僵尸进程时至关重要)
STATps aux 独有进程当前运行状态:R(运行)、S(可中断休眠)、D(不可中断等待 IO)、Z(僵尸进程)
%CPU / %MEMps aux 独有进程占用的 CPU 与物理内存百分比
VSZps aux 独有虚拟内存大小(Virtual Memory Size,KB)
RSSps aux 独有常驻物理内存大小(Resident Set Size,KB,反映进程真实吃掉的物理内存)
TIME两者皆有该进程累计占用 CPU 的实际计算时间
CMD / COMMAND两者皆有启动该进程所执行的原始命令行字符串及参数

2. 进程快速检索与自身过滤

# 技巧:过滤自身 grep 进程
# 当你执行 ps -ef | grep app 时,grep app 自身也会被作为一条进程显示出来。
# 经典过滤方法:追加 grep -v grep
ps -ef | grep myapp | grep -v grep

# 现代极简工具:pgrep
pgrep -l -f myapp       # 直接输出匹配关键词的 PID 与命令名

二、进程终止与信号机制(面试生死线)

Linux 进程间的通知与控制依赖信号(Signal)机制。当你在终端输入 kill 时,实质上是向目标进程发送了一个数字信号。

kill -15 (优雅停机) 与 kill -9 (内核强杀) 的本质执行路径对比

1. 常见核心信号对比表

信号编号信号名称触发方式进程能否捕获/忽略典型含义与场景
1SIGHUP控制终端挂断 / 断开 SSH可以捕获挂断信号;常用于通知 Nginx 等服务热重载配置文件(nginx -s reload)
2SIGINT键盘输入 Ctrl + C可以捕获交互式终端中断请求,程序通常优雅退出
9SIGKILLkill -9 <pid>绝对不可捕获,不可忽略内核直接处决强杀;只有在进程彻底死锁假死时作为保底使用
15SIGTERMkill <pid>(默认就是 15)可以捕获并处理优雅停机(Graceful Shutdown);通知应用正常收尾清理

2. 生产环境安全停机规范


三、后台运行与持久守护流程

进程启动方式与生命周期管理全景图

1. 为什么直接用 & 放后台,关闭 SSH 终端后进程依然会挂?

  • 当用户通过 SSH 登录 Linux 主机时,系统会为当前登录开启一个会话(Session),并启动一个 Bash 终端进程作为该会话的首进程;
  • 用户在终端输入命令(即使结尾加上了 &,如 python app.py &),该命令衍生出的子进程依然归属于当前终端会话控制;
  • 当用户关闭 SSH 客户端窗口时,终端驱动会向该会话名下的所有子进程广播发送 SIGHUP(挂断)信号;
  • 默认情况下,未做特殊信号处理的进程收到 SIGHUP 后,其默认动作就是立即自尽退出!

2. nohup 彻底解决挂断退出

nohup(No Hang Up)的作用正是让后续启动的命令忽略 SIGHUP 信号,从而使得进程与当前的交互式终端会话彻底解绑。

经典生产启动命令深度拆解

nohup java -jar app.jar > app.log 2>&1 &
  • nohup:指示进程忽略所有的挂断信号(SIGHUP),即便退出终端、断开 SSH 链接,进程仍持续存活;
  • java -jar app.jar:实际运行的业务应用程序;
  • > app.log:将进程的标准输出(stdout,FD 1)重定向写入 app.log 磁盘文件;
  • 2>&1:将标准错误输出(stderr,FD 2)重定向合并到标准输出的目标(详见 文本三剑客与重定向管道);
  • &:通知 Bash 将此命令放到后台异步执行,使当前终端能够立即恢复输入提示符。

3. 作业控制基础:jobs、fg、bg

  • Ctrl + Z:将当前前台正在执行的程序挂起暂停(Stopped),并送入后台;
  • jobs -l:列出当前终端后台的所有任务编号([1]、[2])及其状态;
  • bg %1:让编号为 1 的后台被暂停作业在后台继续运行;
  • fg %1:将编号为 1 的后台作业重新调回前台控制台交互。

四、现代化服务管理:Systemd 与 systemctl

在 CentOS 7+、Ubuntu 16.04+ 及所有主流 Linux 现代发行版中,Systemd 是系统的第 1 号根进程(PID = 1),负责全系统的服务编排、依赖拉起与故障自愈守护。

1. systemctl 常用操作指令

# 1. 查看服务当前运行状态(是否正常运行、最近报错日志)
systemctl status nginx

# 2. 启动 / 停止 / 重启服务
systemctl start nginx
systemctl stop nginx
systemctl restart nginx

# 3. 热重载配置(不中断在线客户端 TCP 连接,重新加载配置)
systemctl reload nginx

# 4. 配置开机自启动 / 取消开机自启动
systemctl enable nginx
systemctl disable nginx

2. 手写一个生产微服务 Systemd Service 配置

在 /etc/systemd/system/ 目录下创建 myapp.service 配置文件:

[Unit]
Description=My SpringBoot or FastAPI Production Service
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/data/app
ExecStart=/usr/bin/java -jar /data/app/myapp.jar
# 进程异常退出后自动重启机制(实现高可用自愈)
Restart=always
RestartSec=5s
# 标准输出与错误输出直接进入系统日志中心 journald
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
# 生效新配置文件并启动服务
sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp

五、高频面试追问

  1. ps -ef 和 ps aux 中,如果看到一个进程的状态列为 Z,代表什么?为什么 kill -9 杀不掉它?

    • 状态为 Z 代表僵尸进程(Zombie);
    • 僵尸进程实际上早已经执行结束退出了,它的内存和代码段已经释放,但父进程没有调用 wait() 或 waitpid() 去读取它的退出码,导致内核的进程控制块(PCB)依然滞留在进程表中;
    • 因为它已经是一个死去的进程,根本无法接收任何信号,所以 kill -9 对它无效。正确解决办法是杀掉它的父进程(PPID),使它被 1 号进程(systemd/init)收养并由 1 号进程代为回收释放 PCB 表项。
  2. 如果一个后台服务意外挂了,nohup 能帮它自动拉起重启吗?

    • 不能。nohup 仅负责屏蔽终端断开带来的 SIGHUP 信号,它并不具备进程生命周期监控与健康守护功能。
    • 生产环境中若需进程崩溃自动拉起,应采用 Systemd(配置 Restart=always)、Supervisor,或者在容器化时代由 Kubernetes(配置重启策略 RestartPolicy: Always) 进行守护调度。
Navigation

Type to search…

↑↓ navigate↵ selectEsc close