UNIX/Linux系统管理技术手册-读书笔记-第四章
《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=会话控制进程
💡
pidof和pgrep也可快速获取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字节(动态生成),用cat或less查看。
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统计不到,可能是文件已被删除但仍被进程打开(lsof或fuser可查)。
排查步骤:
uptime查看负载(1/5/15分钟平均)top看CPU使用率(若接近100%则CPU-bound;若idle高但负载高,则I/O-bound)- 针对高CPU进程,用
strace跟踪看其行为 - 确定是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输入 |
示例:
|
|
系统级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=15min,OnUnitActiveSec=1d(每天一次) |
| 精度调整 | AccuracySec=1ns(高精度),默认60s(随机延迟防风暴) |
| 临时计时器 | systemd-run --on-calendar '*:0/10' /bin/sh -c "cmd" |
| 管理 | systemctl list-timers,systemctl 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)和系统工具(top、iotop)共同诊断。- cron作业常用于数据库备份(
mysqldump)、优化(mysqlcheck)、归档清理等,注意错峰执行,避免多个数据库同时备份引发I/O风暴;systemd timer的随机延迟特性可避免此问题。- 信号方面,数据库通常捕获TERM进行优雅关闭(等待事务完成),直接
kill -9可能导致数据损坏,优先使用服务管理命令(systemctl stop)或数据库自身关闭命令。
文章作者 会写代码的小郎中
上次更新 2011-06-14
许可协议 CC BY-NC-ND 4.0