《UNIX/Linux系统管理技术手册-读书笔记-第四章

1. 进程的组成与关键属性

概念 说明 能做什么
地址空间 内存页集合(代码、库、变量、栈) 进程运行的基础
内核数据结构 状态、优先级、资源占用、打开文件、信号掩码、属主等 内核管理进程的依据
线程 进程内的执行上下文(每个线程有自己的栈和CPU上下文) 多线程可利用多核并行处理(如Apache、BIND)

关键属性速查

属性 全称 作用
PID 进程ID 唯一标识,操作进程时指定
PPID 父进程ID 追踪进程来源(谁创建了它)
UID / EUID 真实用户ID / 有效用户ID UID=创建者;EUID=决定当前访问权限(setuid时不同)
GID / EGID 真实组ID / 有效组ID 类似UID/EUID,setgid程序使用
saved UID/GID 保存的ID 允许程序临时放弃并恢复特权(setuid程序安全设计)
友善度(nice) 调度优先级暗示 值越高越“友善”(优先级越低),范围 -20~+19(Linux)
控制终端 关联的终端(或伪终端) 决定stdin/stdout/stderr,接收键盘信号(Ctrl+C等)

Linux还有FSUID(文件系统UID),非标准,极少使用。

2. 进程生命周期

阶段 系统调用/操作 说明
创建 fork() 复制父进程,生成子进程(返回值:子进程得到0,父进程得到子进程PID)
加载新程序 exec() 系列 替换当前进程的内存映像,执行新程序
终止 exit() 进程结束,返回退出码(0=成功)
父进程回收 wait() 父进程获取子进程退出状态和资源统计
孤儿进程 父进程先于子进程死亡 内核将孤儿过继给 init/systemd(PID=1),由它们回收
僵尸进程 子进程已退出,父进程尚未wait() 占用进程表项,需排查父进程为何不回收

内核自建进程:引导时内核创建 init/systemd(PID=1),是所有进程的祖先。

3. 信号(进程级中断)

信号名 编号 默认行为 能否捕获/阻塞 用途
HUP 1 终止 能/能 ①守护进程重新读取配置(如nginx -s reload)②终端挂断
INT 2 终止 能/能 Ctrl+C,中断当前操作
QUIT 3 终止+core 能/能 Ctrl+\,类似TERM但生成core
KILL 9 终止 不能 强制杀死进程(终极手段)
TERM 15 终止 能/能 请求进程正常退出(默认kill信号)
STOP 17 停止 不能 挂起进程(不可捕获)
TSTP 18 停止 能/能 Ctrl+Z,请求停止(软版本)
CONT 19 继续 能(不能阻塞) 恢复被STOP/TSTP的进程
USR1/USR2 30/31 终止 能/能 用户自定义(如Apache用USR1平滑重启)
BUS/SEGV 10/11 终止+core 能/能 内存访问错误(程序崩溃常见)

信号处理方式

  • 捕获(自定义处理程序)
  • 忽略(丢弃)
  • 阻塞(排队,解除阻塞后仅调用一次处理程序)
  • 默认(由内核处理)

💡 kill -l 可列出所有信号名。

4. 进程管理命令

4.1 kill / killall / pkill:发送信号

命令 语法 功能
kill kill [-signal] pid 向指定PID发送信号(默认TERM)
kill -9 pid 强制杀死(KILL,不可捕获) 普通kill无效时使用
killall killall httpd 按名字杀死所有匹配进程
pkill pkill -u ben 按属性(用户名、进程名等)发送信号

kill -9 是最后手段,先尝试TERM(15)让进程自己清理。

4.2 ps:进程快照

常用用法 说明 典型输出字段
ps aux 显示所有进程(面向用户格式) USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, TIME, COMMAND
ps lax 显示所有进程(长格式,速度快) 增加 PPID, PRI, NI, WCHAN
ps aux | grep sshd 查找特定进程 注意grep自身也会出现,可用grep -v grep过滤

STAT状态标志

  • R = 可运行
  • D = 不可中断睡眠(常与NFS hard挂载相关,无法杀死)
  • S = 睡眠(<20秒)
  • T = 停止/跟踪
  • Z = 僵尸
  • 附加:<=高优先级,N=低优先级,s=会话控制进程

💡 pidofpgrep 也可快速获取PID。

4.3 top / htop:动态实时监控

命令 功能 重点观察
top 实时刷新进程列表(默认CPU占优排序) 前三行:负载平均值、任务数、CPU使用率、内存/交换
top -q 最高优先级运行(root) 系统濒死时追踪问题进程
htop 增强版top(更美观,交互更强) 需额外安装

多核CPU:top运行时按1切换显示各核心使用率(Linux)。

内存列VIRT(虚拟内存)、RES(驻留物理内存)、DATA(数据段+栈,更准确反映进程独占内存)。

4.4 nice / renice:调整调度优先级

命令 功能 注意事项
nice -n 5 ./longtask 以较低优先级启动进程(增加5个nice值) 普通用户只能增加nice(降低优先级)
sudo renice -5 8829 将PID 8829的nice设为-5(提高优先级) root可任意设置
sudo renice 5 -u bogs 将用户bogs的所有进程nice设为5

范围:Linux -20~+19,FreeBSD -20~+20。
如今手动调整已较少,但批量任务可降低优先级以免影响交互响应。

5. /proc 文件系统(Linux)

路径 内容 用途
/proc/<PID>/ 每个进程的子目录 查看进程详细信息
/proc/<PID>/cmdline 完整命令行(null分隔) tr '\0' '\n'可读
/proc/<PID>/environ 环境变量(null分隔) 同上
/proc/<PID>/fd/ 打开的文件描述符链接 查看进程打开了哪些文件
/proc/<PID>/maps 内存映射(共享库等) 调试依赖
/proc/<PID>/cwd 当前工作目录符号链接
/proc/<PID>/root chroot后的根目录链接

/proc下文件大小显示0字节(动态生成),用catless查看。
FreeBSD的/proc已废弃,需手动挂载mount -t procfs proc /proc,但布局略有不同。

6. strace / truss:系统调用跟踪

命令 平台 功能
strace -p PID Linux 附着到运行进程,实时输出系统调用和信号
strace -f -e trace=file cp ... Linux 跟踪子进程,只显示文件操作
truss cp /etc/passwd /tmp/pw FreeBSD 类似strace

典型用途

  • 排查进程为何无法打开配置文件(权限/路径错误)
  • 找出进程卡住的原因(等待什么资源)
  • 分析进程行为是否异常(如恶意软件)

💡 输出量大,但关注返回错误(非0)的系统调用即可快速定位问题。

7. 失控进程排查

现象 排查命令 解决方法
CPU占用过高 top/ps查看%CPU 确认是否正常(如计算密集型任务),异常则kill
内存占用过高 top的VIRT/RES/DATA列 查看是否内存泄漏,必要时重启服务
文件系统被写满 df -h找满的文件系统;du -h逐级定位大目录 找到大文件(可能是core文件或日志),删除或截断
进程无法杀死(D状态) ps看到STAT=D(不可中断睡眠) 通常因NFS hard挂载或I/O故障,只能重启系统

df vs du不一致:若df显示已满但du统计不到,可能是文件已被删除但仍被进程打开(lsoffuser可查)。

排查步骤

  1. uptime查看负载(1/5/15分钟平均)
  2. top看CPU使用率(若接近100%则CPU-bound;若idle高但负载高,则I/O-bound)
  3. 针对高CPU进程,用strace跟踪看其行为
  4. 确定是bug则kill,并考虑升级或修复

8. 周期性任务调度

8.1 cron(传统)

概念 说明
crontab文件 每个用户的调度配置文件,位于/var/spool/cron/(Linux)或/var/cron/tabs/(FreeBSD)
crontab命令 crontab -e编辑,-l列出,-r删除;root可用-u user管理他人
格式 minute hour day month weekday command(6字段)
特殊语法 *任意,1-5范围,*/10步进,1,3,5列表
% 在command中表示换行,第一个%前为命令,之后作为stdin输入

示例

1
2
3
4
# 每个月 25 号,早上 04:30 执行发送邮件
30 4 25 * * /usr/bin/mail -s "TPS report" [email protected]%TPS due!%
# 每周一、三、五,全天每 10 分钟执行一次
*/10 * * * 1,3,5 echo ruok | nc localhost 2181 | mail -s "status" admin

系统级crontab

  • /etc/crontab:多出username字段,指定运行身份
  • /etc/cron.d/:类似,软件包可安装自己的调度
  • /etc/cron.hourly//etc/cron.daily/等:由系统crontab调用的脚本目录

环境问题:cron执行的shell不是登录shell,环境变量(PATH等)可能缺失,建议使用绝对路径或在crontab顶部设置PATH=/bin:/usr/bin

访问控制

  • /etc/cron.allow(白名单)存在则仅列表内用户可用
  • 否则检查/etc/cron.deny(黑名单)
  • 两者均不存在时行为不定(通常允许所有)

不要直接编辑/var/spool/cron/下的文件,用crontab -e,否则cron可能未感知修改。若修改后无反应,可kill -HUP <cron-pid>强制重载。

8.2 systemd计时器(Timer)

特性 说明
组成 计时器单元(.timer)+ 服务单元(.service)
时间类型 OnBootSec(引导后)、OnActiveSec(计时器激活后)、OnCalendar(绝对日期/时间)
示例 OnBootSec=15minOnUnitActiveSec=1d(每天一次)
精度调整 AccuracySec=1ns(高精度),默认60s(随机延迟防风暴)
临时计时器 systemd-run --on-calendar '*:0/10' /bin/sh -c "cmd"
管理 systemctl list-timerssystemctl start/stop timer

时间表达式(OnCalendar)

2017/7/4                # 2017-07-04 00:00:00
*-*-* 12:00:00          # 每天中午
Mon 17:00:00            # 每周一下午5点
monthly                 # 每月1日午夜
*:0/10                  # 每10分钟(从整点开始)

优势:支持相对时间、可随机延迟(防风暴)、可直接systemctl start service调试。

现状:本书示例系统仍保留cron,但有些发行版(如CoreOS)已完全转向systemd timer。两者可共存。

9. 本章核心命令速查表

命令 用途
ps aux / ps lax 查看进程快照
top / htop 实时监控进程
kill [-signal] PID 发送信号(默认TERM)
kill -9 PID 强制杀死(终极)
killall name / pkill -u user 按名或属性杀进程
nice -n incr command 以指定优先级启动
renice prio PID 调整运行中进程优先级
strace -p PID(Linux) 跟踪系统调用和信号
truss cmd(FreeBSD) 同strace
lsof / fuser 查看文件被哪些进程占用
df -h / du -h 检查磁盘使用
uptime 查看系统负载平均值
crontab -e/-l/-r 管理cron任务
systemctl list-timers 查看systemd计时器
systemd-run --on-calendar ... 创建临时计时器

DBA视角补充

  • 数据库进程(如mysqld、postmaster)通常有多个线程/进程,ps时注意区分主进程和worker。
  • 数据库进程的失控常表现为高CPU或高I/O,需结合数据库自身监控(如SHOW PROCESSLIST)和系统工具(topiotop)共同诊断。
  • cron作业常用于数据库备份(mysqldump)、优化(mysqlcheck)、归档清理等,注意错峰执行,避免多个数据库同时备份引发I/O风暴;systemd timer的随机延迟特性可避免此问题。
  • 信号方面,数据库通常捕获TERM进行优雅关闭(等待事务完成),直接kill -9可能导致数据损坏,优先使用服务管理命令(systemctl stop)或数据库自身关闭命令。