Orange的运维学习日记--11.Linux进程管理详解

发布于:2025-07-26 ⋅ 阅读:(13) ⋅ 点赞:(0)

Orange的运维学习日记–Linux 进程管理

进程基础

进程的定义与作用

进程是操作系统分配资源和调度执行的最小单位。每当我们运行一个程序,比如 bashsshd 或者自写的脚本,内核就会在内存中创建一个新的进程,赋予它独立的地址空间、资源和执行上下文

进程使得多个程序能够并发执行,并隔离各自的运行环境,从而保证系统稳定性与安全性

进程组成与环境

一个典型的进程由以下几部分构成:

  • 地址空间:包含代码段、数据段、堆和栈
  • 所有权与权限:包括用户 ID、组 ID 以及 Capability
  • 执行线程:单线程或多线程,由寄存器和程序计数器决定执行位置
  • 系统资源:文件描述符、信号处理函数、网络端口等

除此之外,进程还有环境变量集合、当前调度优先级和打开的资源列表,这些都影响着它的行为与性能

生命周期与状态

进程在其一生中会经历一系列状态转换:

wakeup/事件/信号
SIGSTOP/Ctrl+Z
SIGCONT
exit
wait()/回收
New
Runnable
Running
Sleeping
Stopped
Zombie
  • New:刚创建,还未装载执行代码
  • Runnable:就绪队列中等待 CPU 调度
  • Running:正在 CPU 上执行,分用户态和内核态
  • Sleeping:阻塞等待 I/O、计时器或外部事件
  • Stopped:收到暂停信号,挂起执行
  • Zombie:已终止,但保留退出状态供父进程回收
  • Reaped:父进程调用 wait() 后彻底销毁

在这里插入图片描述

通常你在日常中只会见到 Running、Sleeping、Stopped 和 Zombie 四种状态

在这里插入图片描述

在这里插入图片描述


进程查看与属性筛选

操作系统中运行的进程数量往往非常多,要快速定位并获取感兴趣的进程信息,就需要借助 ps 工具。

ps 命令概览

ps 命令可以快照式地打印系统当前进程。它既能列出所有进程,也可以针对用户、终端、命令名称等条件进行过滤,同时支持自定义输出列和排序。

ps 常用选项

  • 限定范围
    • -eax:列出所有进程
    • -u 用户名:仅显示指定用户的进程
    • -t 终端名:显示指定终端的进程
    • -C 程序名:按命令名称匹配
  • 输出格式
    • -o 列表:自定义列,如 pid,ppid,%cpu,cmd
    • -f-j:全格式或作业型输出
    • axf:以树形结构展示父子关系
  • 排序
    • --sort 字段:默认升序
    • --sort -字段:降序

示例与说明

下面一段对比展示了几种典型场景:

场景 命令 说明
查看所有进程 ps -e / ps axu 最基本的全量列表
树形查看 ps axf 用缩进展示父子进程关系
按 CPU 占用率排序 ps axu --sort -%cpu 找出最占资源的进程
查看特定用户 ps -u laoma u 针对 laoma 用户查看
查看指定终端 ps -t pts/1 u 查看终端 pts/1 下的所有进程
自定义列查看特定 PID ps -o pid,ppid,%mem,cmd 1159 显示 PID=1159 进程的关键信息
按命令名称过滤 ps -C sshd -o pid,user,cmd 查找所有 sshd 进程并显示 PID 与用户

使用 headgrepawksort 等工具组合可以进一步挖掘特定条件下的进程


作业控制

在同一个终端里,你既可以同时运行多个程序,也能灵活地暂停、恢复甚至迁移它们的运行状态

前台与后台作业对比

  • 前台作业
    • 占用当前终端,能读写标准输入
    • 捕获 Ctrl+C(SIGINT)和 Ctrl+Z(SIGTSTP)
  • 后台作业
    • 不占用输入,即使尝试读取也会被挂起
    • 终端列(TTY)显示 ?

& 将命令放到后台执行,shell 马上返回提示符,你可以同时处理其他事情

控制命令与快捷键

操作 命令或快捷键 作用
列出作业 jobs 查看当前所有作业及状态
前台恢复 fg %n 将第 n 个作业切换到前台
后台恢复 bg %n 将暂停的第 n 个作业在后台继续运行
暂停前台作业 Ctrl+Z 发送 SIGTSTP
终止前台作业 Ctrl+C 发送 SIGINT

通过这些命令,你可以在一个 shell 会话中高效地管理多个任务

会话保持工具:nohup vs screen

当你远程登录执行长时间任务时,若突然断网或关闭终端,后台作业可能会被 SIGHUP 信号终止。为此,我们有两种主流方案:

  • nohup
    • 忽略挂断信号(SIGHUP)
    • 输出自动重定向到 nohup.out
    • 用法:nohup 命令 &
  • screen
    • 创建可分离的虚拟终端会话
    • 即使断开连接,任务仍在会话中运行
    • 安装:yum install -y screen
    • 启动:screen
    • 列表:screen -ls
    • 恢复:screen -r 会话ID

两者各有优缺点:nohup 简单直接,但无法恢复交互;screen 功能更强,但需要额外学习会话管理命令


信号机制与进程控制

信号是一种轻量级的进程间通信机制,既能由内核在异常或事件发生时产生,也能由用户通过命令或快捷键发送。

信号的概念与用例

当你按下 Ctrl+C,内核就会向前台进程发送 SIGINT,通知它“停止执行”。如果程序捕获该信号,并在处理函数里做好清理,就能优雅退场;如果未处理,进程就会被默认终止。

可以用 kill/pkill 命令给任意进程发送信号,常见用例有:

  • 优雅重启kill -HUP PID 通知进程重新加载配置
  • 调试看守kill -USR1 PID 根据约定触发进程打印状态
  • 强制终止kill -9 PID 无条件杀掉进程

常见信号列表

编号 名称 默认动作 触发方式
1 SIGHUP 终止 终端关闭/配置重载
2 SIGINT 终止 Ctrl+C
3 SIGQUIT 核心转储 Ctrl+\
9 SIGKILL 强制终止 kill -9
15 SIGTERM 终止 kill(默认)
17 SIGCHLD 忽略 子进程状态变化
18 SIGCONT 继续 kill -CONT
19 SIGSTOP 暂停 kill -STOP(无法捕获)
20 SIGTSTP 暂停 Ctrl+Z

在这里插入图片描述

kill、pgrep、pkill 使用方法

  • kill
    • 发送信号到指定 PID:kill -SIGTERM 1234kill 1234
    • 作用于作业号:kill -9 %1 将第 1 个作业强制终止
  • pgrep
    • 查找符合条件的 PID:pgrep sshd
    • 显示名称:pgrep -l httpd
    • 按用户/终端/PPID 筛选:pgrep -u laomapgrep -t pts/0pgrep -P 1000
  • pkill
    • pgrep 类似,但直接发送 SIGTERM:pkill sleep
    • 可指定信号:pkill -SIGUSR1 myapp
    • 按用户/终端/父进程:pkill -u rootpkill -t pts/2pkill -P 1350

当内置过滤无法满足需求时,经典组合为:

kill -9 $(ps axu | grep '[d]nf install' | awk '{print $2}')

登录与会话查询命令

  • whoami:显示当前执行用户
  • who:列出所有登录会话及来源
  • w:在 who 的基础上增加登录时间、空闲时长和当前执行命令
  • last:读取 /var/log/wtmp,显示历史登录和重启记录

特殊进程

有两类“看不见的隐患”进程需要特别关注:僵尸进程和孤儿进程

僵尸进程的形成与危害

当子进程退出后,内核并不立即销毁它的 PCB,而是将其标记为 Z(Zombie),等待父进程调用 wait()waitpid() 获取退出状态若父进程迟迟不回收,这些 PCB 会一直占用内存和 PID;进程过多时,可能导致系统无法再创建新进程

预防措施

  • 在父进程中捕获 SIGCHLD,在信号处理函数里调用非阻塞版 waitpid(-1, …, WNOHANG) 回收所有死子进程
  • 对于短命任务,使用进程池或线程池替代频繁 fork()

孤儿进程的救助与注意

当父进程提前退出,子进程就会被 init(或 systemd)收养,其 PPID 自动变成 1。这样即使原父进程崩溃,子进程依然能被最终回收,不会成为僵尸

虽然孤儿进程本身不会造成死锁,但频繁生成并遗忘管理会给 init 带来额外负担。

良好实践

  • 父进程对重要子进程设置合适的退出策略,避免父子脱节
  • 对于短命任务,使用进程池或线程池替代频繁 fork()

孤儿进程的救助与注意

当父进程提前退出,子进程就会被 init(或 systemd)收养,其 PPID 自动变成 1。这样即使原父进程崩溃,子进程依然能被最终回收,不会成为僵尸

虽然孤儿进程本身不会造成死锁,但频繁生成并遗忘管理会给 init 带来额外负担。

良好实践

  • 父进程对重要子进程设置合适的退出策略,避免父子脱节
  • 必要时在代码里检测 getppid() == 1,若不希望被收养则自行退出

网站公告

今日签到

点亮在社区的每一天
去签到