SRE运维
Linux SRE 运维常用命令详解与实战
1. 引言
在站点可靠性工程(Site Reliability Engineering, SRE)的日常运维工作中,Linux 命令行工具是不可或缺的。SRE 工程师需要利用这些工具进行系统监控、故障排查、性能分析、日志审计和安全加固。本报告旨在详细介绍 SRE 运维中常用的一系列 Linux 命令,包括 grep
、iptables
、awk
、sed
、ps
、netstat
(及其替代者 ss
) 等,并结合一个详细的实战案例,展示如何综合运用这些命令解决实际问题。掌握这些命令的精髓,对于提升运维效率和保障系统稳定性至关重要。本报告还将涵盖 top
、vmstat
、iostat
、lsof
、curl
、find
、df
、du
、systemctl
和 journalctl
等其他核心命令。
2. 核心文本处理与防火墙管理命令详解
2.1. grep (Global Regular Expression Print)
核心功能: grep
用于在文件或标准输入中搜索匹配特定模式(字符串或正则表达式)的行,并将匹配的行输出到标准输出 。它是日志分析、数据筛选和文本搜索的基石。
基本语法: grep PATTERN [FILE...]
常用选项:
-i
,--ignore-case
: 忽略大小写进行匹配 。-v
,--invert-match
: 反转匹配,显示不包含模式的行 。-r
,-R
,--recursive
: 递归搜索目录下的所有文件 。-r
默认跟踪符号链接目录,-R
不跟踪 。-n
,--line-number
: 在输出的每行前显示行号 。-c
,--count
: 只输出每个文件中匹配模式的行数,而不是匹配的行本身 。-E
,--extended-regexp
: 使用扩展正则表达式 (ERE) 。这使得例如|
(或)、+
(一个或多个)、?
(零个或一个) 等元字符可以直接使用。-F
,--fixed-strings
: 将模式视为固定字符串(字面量),而不是正则表达式 。当搜索包含特殊字符的文本时很有用。-o
,--only-matching
: 只显示行中与模式匹配的部分,每个匹配部分占一行。-A NUM
,--after-context=NUM
: 打印匹配行及其后 NUM 行。-B NUM
,--before-context=NUM
: 打印匹配行及其前 NUM 行。-C NUM
,--context=NUM
: 打印匹配行及其前后各 NUM 行。-l
,--files-with-matches
: 只打印包含匹配项的文件名。-H
,--with-filename
: 在多文件搜索时,打印每个匹配项所在的文件名。-w
,--word-regexp
: 只匹配整个单词 。
正则表达式 (Regex) 应用:
- 锚点:
^
匹配行首,$
匹配行尾 。例如,grep '^error'
查找以 “error” 开头的行。 - 字符匹配:
.
匹配任意单个字符 。 - 方括号表达式:
[abc]
匹配 a、b 或 c。[a-z]
匹配任意小写字母。[^0-9]
匹配任意非数字字符 。 - 字符类:
[[:digit:]]
匹配数字,[[:alpha:]]
匹配字母,[[:space:]]
匹配空白字符 。 - 量词:
*
(零个或多个),+
(一个或多个, ERE),?
(零个或一个, ERE),{n}
(恰好n个, ERE),{n,}
(至少n个, ERE),{n,m}
(n到m个, ERE) 。 - 替换/或:
|
(ERE) 用于匹配多个模式之一。例如grep -E 'error|warning'
。 - 分组:
()
(ERE) 用于将模式的一部分组合成一个单元 。 - 特殊反斜杠表达式:
\b
匹配单词边界,\w
匹配单词字符 。
SRE 使用场景与示例:
- 日志分析:
- 搜索错误日志:
grep -i 'error' /var/log/syslog
。 - 查找特定IP地址的访问记录:
grep '192.168.1.100' /var/log/nginx/access.log
。 - 统计特定错误出现的次数:
grep -c 'NullPointerException' application.log
。 - 显示包含 “failed login” 的行以及其后5行:
grep -A 5 'failed login' /var/log/auth.log
。
- 搜索错误日志:
- 配置文件审查:
- 查找特定配置项:
grep '^ListenPort' /etc/ssh/sshd_config
。 - 显示不以
#
开头的配置行:grep -v '^#' /etc/nginx/nginx.conf
。
- 查找特定配置项:
- 代码搜索:
- 在项目中递归搜索函数定义:
grep -r 'function process_payment' /srv/myapp/
。
- 在项目中递归搜索函数定义:
- 结合管道使用:
- 列出所有正在运行的Java进程:
ps aux | grep '[j]ava'
(使用[]
避免 grep 进程自身被匹配)。 - 查找监听80端口的进程:
netstat -tulnp | grep ':80'
。
- 列出所有正在运行的Java进程:
表: grep 常用选项
选项 | 描述 | SRE 场景示例 |
---|---|---|
-i |
忽略大小写 | grep -i 'exception' app.log |
-v |
反转匹配 (不包含) | grep -v 'DEBUG' app.log |
-r / -R |
递归搜索 | grep -r 'API_KEY' /etc/ |
-n |
显示行号 | grep -n 'FATAL' error.log |
-c |
统计匹配行数 | grep -c 'HTTP/1.1" 500' access.log |
-E |
使用扩展正则表达式 | `grep -E ‘timeout |
-o |
只显示匹配的部分 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' access.log (提取IP) |
-A NUM |
显示匹配行及其后NUM行 | grep -A 3 'transaction failed' payment.log |
-B NUM |
显示匹配行及其前NUM行 | grep -B 2 'user_login_failed' auth.log |
-C NUM |
显示匹配行及其前后各NUM行 | grep -C 5 'segmentation fault' kern.log |
-l |
只列出包含匹配模式的文件名 | grep -rl 'TODO' /opt/project/src |
-w |
匹配整个单词 | grep -w 'port' config.ini |
grep 的核心价值在于其快速、灵活的文本模式匹配能力。 |
对于 SRE 工程师而言,系统日志、配置文件、应用输出等都是海量的文本数据。
grep
及其正则表达式的强大功能,使得工程师能够迅速从这些数据中筛选出关键信息,例如错误提示、特定事件、配置参数等。这种能力在故障排查、性能分析、安全审计等多种场景下都至关重要。
例如,在服务发生故障时,通过 grep
搜索错误日志中的特定关键字(如 “Exception”, “Error”, “Timeout”),可以快速定位问题发生的时间点和大致原因 。结合 -A
, -B
, -C
选项,可以获取错误发生的上下文信息,为进一步分析提供线索。
在安全事件响应中,grep
可以用来搜索入侵痕迹,如特定的恶意IP地址、可疑的命令执行记录等。其递归搜索能力 (-r
或 -R
) 使得在整个文件系统中查找特定内容成为可能,这对于追踪配置变更或查找散落在各处的日志文件非常有用。此外,grep
经常作为管道命令链中的一环,与其他命令(如 ps
, netstat
, awk
, sort
, uniq
等)协同工作,实现更复杂的数据提取和分析任务。例如,ps aux | grep 'my_service'
可以快速查看特定服务的进程状态。熟练掌握 grep
不仅能提高日常运维效率,更是 SRE 解决复杂问题的基础技能之一。
2.2. iptables
核心功能: iptables
是 Linux 内核防火墙 Netfilter 的用户空间命令行工具,用于配置、维护和检查 IPv4 数据包过滤规则集 。SRE 使用它来控制网络流量,保护服务器免受未经授权的访问和攻击。
基本概念:
- Tables (表): 规则的集合,按功能组织。主要有
filter
,nat
,mangle
,raw
,security
表 。filter
: 默认表,用于数据包过滤(允许/拒绝)。nat
: 用于网络地址转换 (NAT),如 SNAT, DNAT, MASQUERADE。mangle
: 用于修改数据包的 IP 头部字段 (如 TTL, TOS)。
- Chains (链): 表内规则的序列。数据包按顺序通过链中的规则。内置链对应 Netfilter 钩子点 。
INPUT
: 处理发往本机的数据包。OUTPUT
: 处理由本机发出的数据包。FORWARD
: 处理流经本机的数据包(路由)。PREROUTING
(nat
,mangle
,raw
表): 在路由决策之前处理数据包。POSTROUTING
(nat
,mangle
表): 在路由决策之后,数据包即将发出时处理。
- Rules (规则): 定义了匹配数据包的条件和匹配成功后执行的动作 (Target) 。
- Targets (目标/动作): 规则匹配后对数据包执行的操作 。
ACCEPT
: 允许数据包通过。DROP
: 丢弃数据包,不发送任何响应。REJECT
: 拒绝数据包,并向发送方返回错误信息 (如 ICMP port-unreachable)。LOG
: 记录数据包信息到内核日志 (通常是/var/log/kern.log
或/var/log/syslog
),然后将数据包传递给链中的下一条规则 。MASQUERADE
(nat
表的POSTROUTING
链): 一种特殊的 SNAT,用于动态 IP 地址(如家庭宽带),自动使用出站接口的 IP 地址 。DNAT
(nat
表的PREROUTING
和OUTPUT
链): 目标网络地址转换,用于将发往特定 IP 和端口的流量重定向到内部网络的另一台主机和端口(端口转发)。SNAT
(nat
表的POSTROUTING
链): 源网络地址转换,用于修改数据包的源 IP 地址 。
规则管理:
- 查看规则:
sudo iptables -L [chain] [-t table] [-v -n --line-numbers]
。-L
: 列出规则。-v
: 显示详细信息(包括接口、包和字节计数器)。-n
: 以数字形式显示 IP 地址和端口号(不进行 DNS 解析)。--line-numbers
: 显示规则的行号,便于插入或删除。
- 添加规则:
sudo iptables -A <chain> ... -j <target>
: 追加规则到链尾 。sudo iptables -I <chain> [rule_number] ... -j <target>
: 插入规则到指定位置(默认为链首)。
- 删除规则:
sudo iptables -D <chain> <rule_number>
: 按行号删除 。sudo iptables -D <chain> ... -j <target>
: 按规则内容删除 。
- 修改/替换规则:
sudo iptables -R <chain> <rule_number> ... -j <target>
。 - 清空规则:
sudo iptables -F [chain]
: 清空指定链(或所有链)的规则 。sudo iptables -X [chain]
: 删除用户自定义的空链 。sudo iptables -Z [chain]
: 清零指定链(或所有链)的包和字节计数器 。
- 设置默认策略:
sudo iptables -P <chain> <target>
(例如,sudo iptables -P INPUT DROP
) 。 - 保存和恢复规则:
sudo iptables-save > /etc/iptables/rules.v4
(Debian/Ubuntu, 需安装iptables-persistent
) 。sudo service iptables save
(CentOS/RHEL 6) 或sudo systemctl stop firewalld; sudo yum install iptables-services; sudo systemctl enable iptables; sudo systemctl start iptables; sudo iptables-save > /etc/sysconfig/iptables
(CentOS/RHEL 7+,如果想用iptables替换firewalld) 。sudo iptables-restore < /etc/iptables/rules.v4
。
常用匹配条件:
-p, --protocol <protocol>
: 协议 (tcp
,udp
,icmp
,all
) 。-s, --source <address[/mask]>
: 源 IP 地址或网络 。-d, --destination <address[/mask]>
: 目标 IP 地址或网络 。-i, --in-interface <name>
: 数据包进入的网络接口 (用于INPUT
,FORWARD
,PREROUTING
链) 。-o, --out-interface <name>
: 数据包传出的网络接口 (用于OUTPUT
,FORWARD
,POSTROUTING
链) 。--sport <port>
: 源端口 (需指定-p tcp
或-p udp
) 。--dport <port>
: 目标端口 (需指定-p tcp
或-p udp
) 。-m <module_name> --<module_options>
: 使用扩展模块。state
: 连接状态模块 (--state NEW,ESTABLISHED,RELATED,INVALID
) 。multiport
: 多端口模块 (--dports 22,80,443
或--sports 1000:2000
) 。limit
: 限制日志速率等 (--limit 5/min
) 。iprange
: IP 地址范围模块 (--src-range 192.168.1.100-192.168.1.200
) 。time
: 时间模块 (--timestart 09:00 --timestop 18:00 --weekdays Mon,Tue,Wed,Thu,Fri
) 。
SRE 防火墙配置示例:
- 基本 Web 服务器防火墙策略 (推荐默认拒绝):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35# 清空现有规则 (生产环境慎用,除非明确知道后果)
sudo iptables -F
sudo iptables -X
sudo iptables -Z
# 设置默认拒绝策略
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT # 或者更严格的 DROP,然后明确允许出站流量
# 允许回环接口流量
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
# 允许已建立和相关的连接 (非常重要,允许服务器响应外部请求)
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许 SSH (例如,在端口 22 上,可以限制源 IP)
# sudo iptables -A INPUT -p tcp -s YOUR_TRUSTED_IP/24 --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 简化版,不限制源IP
# 允许 HTTP 和 HTTPS
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# (可选) 允许 ICMP (ping)
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# 记录并丢弃其他所有入站流量 (记录规则应在最终 DROP 规则之前)
sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTABLES-INPUT-DENIED: " --log-level 7
sudo iptables -A INPUT -j DROP
# 记录并丢弃所有转发流量 (如果服务器不作为路由器)
sudo iptables -A FORWARD -m limit --limit 5/min -j LOG --log-prefix "IPTABLES-FORWARD-DENIED: " --log-level 7
sudo iptables -A FORWARD -j DROP - 阻止恶意 IP:
sudo iptables -I INPUT -s <malicious_ip> -j DROP
。 - 端口转发 (DNAT): 将外部端口 8080 的 TCP 流量转发到内部服务器 192.168.1.100 的 80 端口。假设
eth0
是外网接口,eth_internal
是内网接口。1
2sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
sudo iptables -A FORWARD -i eth0 -o eth_internal -p tcp --dport 80 -d 192.168.1.100 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT - 源 NAT (MASQUERADE) 实现内网共享上网:
1
2
3
4
5# 假设 eth0 是外网接口 (互联网), eth1 是内网接口 (LAN)
# 开启 IP 转发: echo 1 > /proc/sys/net/ipv4/ip_forward (或修改 /etc/sysctl.conf)
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT # 允许从 LAN 到 WAN 的新连接 - 记录被丢弃的数据包:日志通常记录在
1
2
3# 在 INPUT 链中,针对特定端口(如 SSH)的 DROP 规则前插入 LOG 规则
sudo iptables -A INPUT -p tcp --dport 22 -j LOG --log-prefix "SSH_DROP: " --log-level 4 # warning level
sudo iptables -A INPUT -p tcp --dport 22 -j DROP/var/log/kern.log
或/var/log/syslog
,具体取决于系统日志守护进程 (如rsyslog
) 的配置。可以通过修改rsyslog
配置将iptables
日志重定向到特定文件,例如在rsyslog.conf
中添加类似:msg,contains,"IPTABLES-DENIED: " -/var/log/iptables.log
和& ~
(停止处理该消息,防止重复记录) 的规则 。
表: iptables 关键表和链
表 (Table) | 链 (Chain) | SRE 上下文中的用途 |
---|---|---|
filter |
INPUT |
保护服务器本身免受不必要的入站流量。 |
filter |
OUTPUT |
控制源自服务器的流量 (较少严格限制)。 |
filter |
FORWARD |
控制流经服务器的流量 (如果它充当路由器/网关)。 |
nat |
PREROUTING |
目标 NAT (例如,端口转发到内部服务)。 |
nat |
POSTROUTING |
源 NAT (例如,MASQUERADE 用于从私有网络访问互联网)。 |
nat |
OUTPUT |
对本地生成的包进行 NAT。 |
mangle |
(多种) | 高级数据包修改 (例如,QoS 标记,TTL 更改)。 |
规则顺序和默认策略的关键性iptables
规则的处理顺序至关重要。数据包一旦匹配到链中的某条终止性规则(如 ACCEPT
, DROP
, REJECT
),处理即停止,后续规则不再被检查 。这意味着,如果一条宽泛的 ACCEPT
规则出现在一条针对其子集流量的特定 DROP
规则之前,那么该 DROP
规则将永远不会被触发。因此,SRE 工程师必须精心规划规则顺序,通常将更具体的规则置于更通用的规则之前。
采用“默认拒绝” (DROP
) 的策略是安全最佳实践。为 INPUT
和 FORWARD
链设置默认 DROP
策略,可以确保任何未被明确允许的流量都会被阻止。之后,再逐条添加 ACCEPT
规则以放行必要的服务和流量。几乎总是最先添加的 ACCEPT
规则之一是针对 ESTABLISHED,RELATED
状态的流量,这允许服务器对已建立的连接或与已建立连接相关的流量(如FTP数据传输或ICMP错误消息)进行响应。
未能正确排序规则或设置不安全的默认策略是导致安全漏洞或网络连接问题的常见原因。调试 iptables
问题时,经常需要检查规则顺序和计数器(通过 sudo iptables -L -v -n --line-numbers
查看)。
iptables
与较新的前端工具 (例如 firewalld
, ufw
)
虽然 iptables
功能强大,但其配置也相对复杂。一些工具如 ufw
(Uncomplicated Firewall) 和 firewalld
(常见于基于 RHEL 的系统) 提供了更用户友好的界面,并在后台管理 iptables
规则 。firewalld
引入了区域 (zones) 和服务 (services) 的概念,可以简化常见场景下的管理。
SRE 工程师需要理解 iptables
以便进行细粒度控制和底层 Netfilter 行为的调试。然而,对于许多标准的防火墙配置,使用 ufw
或 firewalld
可能更高效且不易出错。但在高度定制或对性能敏感的场景中,直接操作 iptables
可能仍然是必要的。了解这些替代方案,并将 iptables
视为 SRE 必须掌握的基础工具,即使日常任务中可能使用前端工具,也能更全面地管理 Linux 防火墙。
2.3. awk (Aho, Weinberger, and Kernighan)
核心功能: awk
是一种功能强大的文本处理编程语言,特别适用于扫描和处理模式,对文件或数据流中的数据进行操作,并生成报告 。
基本语法: awk [options] 'pattern { action }' [file...]
。
- 如果省略
pattern
,action
将应用于所有行。 - 如果省略
action
,默认动作为print $0
(打印整行)。
关键概念与内置变量:
- 记录与字段:
awk
逐条记录 (默认为行) 处理输入。每条记录被分割成若干字段。 $0
: 当前的完整记录 (行) 。$1, $2, ... $N
: 当前记录中的各个字段 。NR
(Number of Records): 当前已处理的记录 (行) 总数 (跨所有输入文件) 。FNR
(File Number of Record): 当前文件中的记录号 。每个新文件开始时重置。NF
(Number of Fields): 当前记录中的字段数量 。$NF
指的是最后一个字段。FS
(Field Separator): 输入字段分隔符 (默认为空白字符)。可通过-F
选项或在BEGIN
块中设置 (例如,FS=","
用于CSV文件) 。OFS
(Output Field Separator):print
命令的输出字段分隔符 (默认为空格) 。ORS
(Output Record Separator): 输出记录分隔符 (默认为换行符) 。FILENAME
: 当前输入文件的名称 。ARGC
,ARGV
: 命令行参数的数量和参数数组。
模式 (Patterns):
- 正则表达式:
/regex/
。例如:awk '/error/ {print $0}' log.txt
。 - 关系表达式:
($3 > 100)
,($1 == "user")
。例如:awk '$NF > 10 {print $1, $NF}' data.txt
。 - 范围模式:
pattern1, pattern2
(匹配从第一个模式到第二个模式之间的所有行) 。 BEGIN
和END
特殊模式:BEGIN { actions }
: 在读取任何输入行之前执行一次。用于初始化 (例如设置 FS, OFS, 打印表头) 。END { actions }
: 在处理完所有输入行之后执行一次。用于汇总、计算总和等 。
动作与常用函数:
print
: 打印字段、变量、字符串。print $1, $3
。printf
: 格式化打印,类似于 C 语言的printf
。- 算术运算:
+
,-
,*
,/
,%
,**
或^
。 - 字符串函数:
length()
,substr()
,index()
,split()
,tolower()
,toupper()
,gsub()
,sub()
,match()
。 - 控制流语句 :
if (condition) statement [else statement]
while (condition) statement
do statement while (condition)
for (init; condition; increment) statement
for (var in array) statement
(用于关联数组)break
,continue
,next
,exit
- 数组:
awk
支持关联数组 。例如:counts[$1]++
。
SRE 使用场景与示例:
- 日志分析与汇总:
- 提取特定字段:
ps aux | awk '{print $1, $2, $3, $4}'
。 - 统计
access.log
中的 HTTP 状态码:awk '{print $9}' access.log | sort | uniq -c | sort -nr
。 - 计算平均响应时间:
awk '/api\/call/ {total += $10; count++} END {if (count > 0) print "Avg Resp Time:", total/count "ms"}' app.log
。 - 对某列求和:
awk 'BEGIN {sum=0} {sum+=$2} END {print sum}' data.txt
。 - 查找唯一 IP 及其请求计数:
awk '{counts[$1]++} END {for (ip in counts) print ip, counts[ip]}' access.log
。
- 提取特定字段:
- 报告生成:
- 打印带行号的行:
awk '{print NR, $0}' file.txt
。 - 使用
printf
格式化输出:df -h | awk 'NR>1 {printf "Mount: %-20s Used: %s Avail: %s\n", $6, $3, $4}'
。
- 打印带行号的行:
- 数据转换:
- 将 CSV 文件转换为以空格分隔:
awk -F, '{print $1, $2, $3}' data.csv
。 - 根据字段值过滤行:
awk '$3 > 1000 {print "High usage:", $0}' resource_usage.txt
。
- 将 CSV 文件转换为以空格分隔:
- 处理
ps
输出:ps -ef | awk '$1 == "nginx" {print $2, $8}'
(查找 nginx 进程的 PID 和 COMMAND)。
表: awk 核心内置变量
变量 | 描述 | SRE 常用场景 |
---|---|---|
$0 |
当前的完整行 | 打印或匹配整行。 |
$1..$N |
单个字段 | 提取特定数据点 (IP、状态码、指标)。 |
NR |
当前记录/行号 | 处理特定行,为输出添加行号。 |
NF |
当前记录中的字段数 | 访问最后一个字段 ($NF ),验证记录结构。 |
FS |
输入字段分隔符 | 定义如何分割行 (例如,用于 CSV、日志分隔符)。 |
OFS |
输出字段分隔符 | 格式化打印输出。 |
FILENAME |
当前输入文件名 | 区别处理多个文件或在报告中包含文件名。 |
BEGIN |
用于预处理的特殊模式 | 初始化变量,打印表头。 |
END |
用于后处理的特殊模式 | 计算总计,打印摘要。 |
awk
作为数据重构和计算引擎awk
的强大之处在于其能够将原始文本数据转化为结构化信息。对于 SRE 工程师而言,它不仅仅是一个文本过滤器,更是一个轻量级的数据处理引擎。原始的日志数据或命令输出通常是半结构化的,不能直接用于聚合或提取特定指标。awk
基于字段的处理方式 ($1
, $2
等) 使得访问列式数据变得简单 。其对算术运算和变量的支持使得动态计算(如求和、平均值、计数)成为可能。关联数组在分组和统计唯一项(如IP地址、错误类型)方面非常强大。BEGIN
和 END
块则分别方便了初始化设置(如打印表头)和最终结果报告(如输出总计)。因此,awk
在 SRE 的工具箱中扮演着将原始数据流或文件转换为有意义的指标或摘要的关键角色,通常无需借助更重量级的工具或完整的脚本语言就能完成许多常见任务。其核心在于 pattern { action }
的范式与字段操作的结合。在实际应用中,应着重展示 awk
如何从原始数据中提取有价值的度量或摘要,而不仅仅是打印列。同时,强调其在管道中处理其他命令输出的能力。
2.4. sed (Stream Editor)
核心功能: sed
主要用于对输入流 (文件或来自管道的输入) 进行基本的文本转换。它逐行读取输入,应用指定的操作,然后输出修改后的行 。
基本语法: sed 'ADDRESS/COMMAND/ARGUMENTS' [FILE...]
或 sed -f script_file [FILE...]
关键概念:
- 模式空间 (Pattern Space):
sed
用于存放当前正在处理的行的缓冲区。 - 保持空间 (Hold Space):
sed
可用于临时存储数据的辅助缓冲区。
常用命令与用法:
s
(substitute):s/regex/replacement/flags
。regex
: 要搜索的模式。replacement
: 用于替换匹配模式的字符串。&
在替换部分代表匹配到的模式。\1
,\2
用于后向引用(与\(...\)
配合使用)。flags
:g
(global): 替换模式空间中所有匹配项 。N
(数字): 只替换第 N 个匹配项。p
(print): 如果发生替换,则打印模式空间 (常与-n
选项合用) 。w file
: 如果发生替换,则将模式空间写入文件file
。I
或i
(ignore case): 不区分大小写匹配 。
d
(delete): 删除模式空间 (当前行) 。p
(print): 打印当前模式空间 。通常与-n
合用以控制输出。i\
(insert):address i\text_to_insert
- 在寻址到的行之前插入文本 。a\
(append):address a\text_to_append
- 在寻址到的行之后追加文本 。c\
(change):address c\new_text
- 用新文本替换寻址到的行。y/string1/string2/
(transform): 将string1
中的字符音译为string2
中对应的字符。-n, --quiet, --silent
: 禁止自动打印模式空间 。-e script
: 添加脚本 (命令) 到待执行的命令中 。允许多个命令。-f script-file
: 从脚本文件中读取命令并添加到待执行的命令中 。-i, --in-place
: 直接修改文件。如果提供了 SUFFIX,则创建原始文件的备份 。谨慎使用。-r
或-E
(extended regex): 使用扩展正则表达式 。
地址定界 (将命令应用于特定行):
- 行号:
sed '3d' file
(删除第3行)。 - 行范围:
sed '2,5s/old/new/' file
(在第2到第5行进行替换)。 $
: 最后一行。sed '$d' file
(删除最后一行)。- 正则表达式:
sed '/pattern/d' file
(删除匹配pattern
的行)。 - 组合:
sed '/start_pattern/,/end_pattern/s/foo/bar/' file
(在起始模式和结束模式之间的行进行替换)。
正则表达式应用: sed
默认使用基本正则表达式 (BRE)。-E
或 -r
启用扩展正则表达式 (ERE) 。
- 后向引用: BRE 中用
\(pattern\)
分组,ERE 中用(pattern)
分组,替换时用\1
,\2
。例如:sed 's/\([0-9]\+\)-\([a-z]\+\)/\2-\1/'
(将 “数字-单词” 替换为 “单词-数字”)。
SRE 使用场景与示例:
- 原地修改配置文件:
- 注释掉某行:
sudo sed -i.bak '/^some_config_param/s/^/#/' /etc/app.conf
。 - 修改配置值:
sudo sed -i 's/DEBUG=true/DEBUG=false/' /etc/app/settings.conf
。
- 注释掉某行:
- 日志文件处理/过滤:
- 删除空行:
sed '/^$/d' logfile.log
。 - 提取日志特定部分:
sed -n '/BEGIN_SECTION/,/END_SECTION/p' large_log.txt
。 - 替换敏感信息 (简单脱敏):
sed 's/CreditCardNo=[0-9]*/CreditCardNo=REDACTED/g' transaction.log
。
- 删除空行:
- 格式化命令输出:
df -h | sed 's/ Mounted on/MountPoint/'
(重命名表头)。
- 自动化脚本修改: 在 Shell 脚本中用于跨多个文件或输出自动执行文本修改。
表: sed 替换标志
标志 | 描述 | SRE 示例 |
---|---|---|
g |
全局:替换行中所有匹配项。 | sed 's/old_IP/new_IP/g' config.file |
N (数字) |
第N次出现:仅替换第N次匹配。 | sed 's/ERROR/Error/2' log.txt (修正第二个拼写错误) |
p |
打印:如果发生替换则打印该行 (与-n合用)。 | sed -n 's/DEBUG/INFO/p' app.log (仅显示被更改的行) |
w file |
写入:如果发生替换则将行写入file。 | sed 's/CRITICAL/ALERT/w critical_alerts.txt' system.log |
i 或 I |
忽略大小写:不区分大小写匹配。 | sed 's/username/USER/ig' user_list.txt |
sed
作为管道中的精确文本操纵器sed
通常用于进行有针对性的修改,例如替换文本、删除特定行,而不是像 awk
那样进行大规模的数据重构 。sed
逐行操作,并且擅长基于模式的查找和替换。其寻址能力(行号、正则表达式)允许精确地定位操作目标。虽然它可以通过保持空间实现更复杂的功能,但在 SRE 的日常使用中,它主要用于相对直接的转换。在管道中,sed
经常在 grep
之后使用(修改已过滤的行)或在 awk
之前使用(在字段处理前清理数据)。因此,sed
是 SRE 用来进行精确、通常是小范围文本流或文件更改的工具。它的强项不在于复杂的逻辑处理(那是 awk
的领域),而在于高效和准确的文本替换与删除。-i
选项用于原地编辑,功能强大但有风险,这强调了 SRE 小心谨慎和先测试的原则。在报告中,应突出 sed
在清理、规范化或轻微更改数据方面的作用,作为更大数据处理管道的一部分,并警示原地编辑的风险。
2.5. ps (Process Status)
核心功能: 显示当前运行进程的信息 。它提供系统进程的一个快照。
语法风格:
- BSD 风格:
ps aux
(选项前无连字符) 。 - System V/POSIX 风格:
ps -ef
(选项前有连字符) 。
常用选项与输出解释:
ps aux
(BSD 风格):USER
: 拥有进程的用户。PID
: 进程 ID。%CPU
: CPU 利用率。%MEM
: 内存利用率 (驻留集大小 / 总物理内存)。VSZ
: 虚拟内存大小 (KiB)。RSS
: 驻留集大小 (使用的物理内存, KiB)。TTY
: 控制终端 (?
表示无)。STAT
: 进程状态 (例如,R
运行,S
休眠,Z
僵尸,D
不可中断休眠,I
空闲,T
停止)。还可能包含修饰符,如s
(会话领导者),<
(高优先级),N
(低优先级),L
(页面锁定在内存中),+
(前台进程组) 。START
: 进程启动时间。TIME
: 累积使用的 CPU 时间。COMMAND
: 命令及其参数。
ps -ef
(System V/POSIX 风格):UID
: 用户 ID。PID
: 进程 ID。PPID
: 父进程 ID。C
(或某些系统上的%CPU
): CPU 利用率。STIME
: 启动时间。TTY
: 控制终端。TIME
: 累积使用的 CPU 时间。CMD
(或COMMAND
): 命令及其参数。
ps -l
(长格式): 提供更详细信息,包括F
(标志),S
(状态),PRI
(优先级),NI
(nice 值),ADDR
(内存地址),SZ
(可分页映像的大小,单位为块) 。axo <format_specifiers>
或-o <format_specifiers>
(自定义输出): 允许用户精确指定要显示的列及其表头 。
示例:ps axo pid,ppid,user,%cpu,%mem,stat,etime,args --sort=-%cpu
pid
: 进程 IDppid
: 父进程 IDuser
: 用户名%cpu
或pcpu
: CPU 使用率%mem
或pmem
: 内存使用率stat
或state
: 进程状态etime
: 进程启动后经过的时间 ([[dd-]hh:]mm:ss
)args
或command
: 完整命令及参数comm
: 仅命令名vsz
: 虚拟大小rss
: 驻留集大小psr
: 当前分配给进程的处理器ni
: Nice 值
- 排序:
ps aux --sort=-%cpu
(按 CPU 使用率降序排序),ps aux --sort=%mem
(按内存使用率升序排序) 。
SRE 使用场景与示例:
- 识别资源消耗大户:
ps aux --sort=-%cpu | head -n 10
(CPU 消耗最高的进程) 。ps aux --sort=-%mem | head -n 10
(内存消耗最高的进程)。
- 检查特定进程是否运行:
ps aux | grep '[s]shd'
。[]
技巧避免grep
显示自身。 - 查找父/子进程关系:
ps -ef --forest
或pstree
。 - 获取特定信息用于脚本:
ps -p <PID> -o pid,ppid,%cpu,cmd
。 - 监控线程数:
ps -p <PID> -L -o pid,lwp,nlwp,pri,cmd
(lwp
是线程 ID,nlwp
是线程数) 。 - 按用户查看进程:
ps -u username
或ps aux | grep '^username'
。
表: ps 输出列 (来自 aux
和 -ef
的常见列)
列 | 描述 | aux 表头 |
-ef 表头 |
描述及 SRE 相关性 |
---|---|---|---|---|
进程 ID | PID | PID |
PID |
唯一 ID,用于定位进程 (例如,与 kill 命令配合使用)。 |
用户 | USER | USER |
UID |
进程所有者,用于安全和资源归属。 |
CPU 使用率 | %CPU | %CPU |
C 或 %CPU |
当前 CPU 份额,性能瓶颈的关键指标。 |
内存使用率 | %MEM | %MEM |
(通常不在 -ef 中直接显示, RSS 更好) |
当前物理内存份额,内存压力的关键指标。 |
虚拟大小 | VSZ | VSZ |
SZ (不固定) |
总虚拟内存。高 VSZ 不一定坏,但值得注意。 |
驻留大小 | RSS | RSS |
(通常不在 -ef 中直接显示) | 实际使用的物理内存。高 RSS 表明内存压力。 |
控制 TTY | TTY | TTY |
TT 或 TTY |
终端关联。? 表示无终端 (守护进程)。 |
进程状态 | STAT | STAT |
S 或 STAT |
理解进程活动的关键 (R , S , D , Z , T , I )。 |
启动时间 | START | START |
STIME |
进程开始的时间。 |
CPU 时间 | TIME | TIME |
TIME |
累积 CPU 使用时间,有助于识别长期繁忙的进程。 |
命令 | COMMAND | COMMAND |
CMD 或 COMMAND |
正在运行的程序。 |
父进程 ID | (不在 aux 默认输出中) |
PPID |
父进程,用于追踪进程谱系。 |
ps
用于快照分析 vs. top
用于实时监控ps
和 top
都是SRE常用的进程监控工具,但它们的应用场景有所不同。ps
执行后收集当前进程信息,打印输出然后退出,提供的是某个特定时间点的“快照” 。相比之下,top
是一个持续运行的程序,它会周期性地刷新并显示进程信息,提供动态的实时视图。
对于需要编写脚本、记录日志或捕获特定状态以供后续分析的场景,ps
是理想的选择,因为它的输出是固定的,易于通过管道传递给其他命令或重定向到文件。例如,SRE 可能会定期执行 ps aux --sort=-%cpu | head
并将结果记录下来,以追踪一段时间内CPU使用率最高的进程。
而对于交互式的实时故障排除和观察波动的资源使用情况,top
则更为合适。SRE 可以通过 top
的交互式命令(如按 P
排序CPU,按 M
排序内存)来动态分析系统负载。ps aux
和 ps -ef
是获取全面进程列表的常用命令组合,其输出经常被传递给 grep
进行筛选或 awk
进行特定字段的提取和格式化。理解这两者的区别,有助于SRE根据具体任务选择最合适的工具。
2.6. netstat (Network Statistics) 与 ss (Socket Statistics)
netstat
核心功能: 显示网络连接 (包括入站和出站)、路由表、接口统计信息、伪装连接和多播成员关系 。
关于 ss
的说明: netstat
在很大程度上被认为是已弃用的。ss
命令是现代的替代品,通常速度更快并提供更多信息 。本报告将按要求涵盖 netstat
,但强烈建议并详细介绍 ss
。
常用 netstat
选项与用法:
-a, --all
: 显示所有套接字 (监听和非监听) 。-t, --tcp
: 显示 TCP 连接 。-u, --udp
: 显示 UDP 连接 。-n, --numeric
: 以数字形式显示地址和端口号 (不解析名称) 。速度更快。-p, --program
: 显示每个套接字所属进程的 PID 和名称 (需要root
/sudo
权限) 。-l, --listening
: 只显示监听套接字 。-r, --route
: 显示内核路由表 。-i, --interfaces
: 显示网络接口表 。-ie
用于显示扩展信息。-s, --statistics
: 显示每个协议的摘要统计信息 。-c, --continuous
: 连续列出 。-e, --extend
: 显示扩展信息 。
输出解读:
Proto
: 协议 (tcp
,udp
,tcp6
,udp6
)。Recv-Q
,Send-Q
: 接收和发送队列 (字节)。Local Address
,Foreign Address
: IP 地址和端口号。0.0.0.0:*
或[::]:*
表示在该端口上监听所有接口 。State
: 连接状态 (例如,LISTEN
,ESTABLISHED
,TIME_WAIT
,CLOSE_WAIT
,SYN_SENT
,SYN_RECV
) 。PID/Program name
: (使用-p
选项时) 拥有套接字的进程 ID 和名称。
ss
命令 (现代替代品):
- 优势: 更快,信息更多,过滤功能更好。使用 Netlink 从内核获取信息。
- 常用
ss
选项 (通常与netstat
类似,但有时字母不同):ss -a
(所有),ss -l
(监听),ss -t
(TCP),ss -u
(UDP),ss -n
(数字),ss -p
(进程),ss -r
(解析主机名),ss -e
(扩展信息),ss -o
(定时器信息),ss -s
(摘要)。
- 按状态过滤:
ss -t state established
,ss -t state listening
。 - 按地址/端口过滤:
ss -t '( dport = :ssh or sport = :ssh )'
,ss dst :80
。
SRE 使用场景与示例 (同时显示 netstat
和 ss
等效命令):
- 查看监听端口:
netstat -tulnp
ss -tulnp
- 查看已建立的连接:
netstat -antp | grep ESTABLISHED
ss -tpn state established
- 关联进程与端口:
netstat -tulnp | grep ':80'
ss -tulnp | grep ':80'
sudo lsof -i :80
- 通常更推荐此方法。
- 网络故障排除:
- 检查服务 (例如,Web 服务器在 80 端口) 是否正在监听:
netstat -tulnp | grep ':80'
或ss -tlpn | grep ':80'
。 - 识别大量处于
TIME_WAIT
状态的连接:netstat -ant | awk '{print $6}' | sort | uniq -c | sort -nr
或ss -ant | awk '{print $2}' | sort | uniq -c | sort -nr
。
- 检查服务 (例如,Web 服务器在 80 端口) 是否正在监听:
- 查看路由表:
netstat -r
或ip route show
。 - 查看接口统计信息:
netstat -i
或ip -s link
。
表: netstat
vs. ss
用于常见 SRE 任务
任务 | netstat 示例 |
ss 示例 |
SRE 相关性 |
---|---|---|---|
列出所有带 PID 的 TCP 监听端口 | sudo netstat -tlpn |
sudo ss -tlpn |
验证服务是否已启动并正在监听。 |
列出所有带 PID 的 UDP 监听端口 | sudo netstat -ulpn |
sudo ss -ulpn |
检查 DNS、NTP 或其他 UDP 服务。 |
列出已建立的 TCP 连接 (数字格式) | netstat -tpn | grep ESTABLISHED |
ss -tpn state established |
监控活动连接,排查连接问题。 |
显示路由表 | netstat -r |
ip route 或 ss -r |
诊断连接问题。 |
显示接口统计信息 | netstat -i |
ip -s link 或 ss -ien |
检查接口上的网络错误或高流量。 |
显示摘要统计信息 | netstat -s |
ss -s |
获取网络协议性能概览。 |
从 netstat
到 ss
的必然转变
多个信息来源明确指出 netstat
已被弃用或过时,而 ss
是首选的替代工具 。这主要是因为 netstat
依赖于读取 /proc
文件系统中的文件,这在存在大量连接的系统上可能效率低下。相比之下,ss
使用 Netlink 套接字接口直接与内核通信,这种方式更高效,并且能够访问更详细的套接字信息。此外,ss
通常提供更强大和灵活的过滤功能。iproute2
软件包(包含 ss
和 ip
命令)是现代 Linux 网络管理的标准套件,取代了包含 netstat
、ifconfig
、route
等命令的旧版 net-tools
软件包。
因此,SRE 工程师,特别是那些在现代 Linux 发行版上工作的工程师,必须熟练掌握 ss
。虽然在旧系统或遗留脚本中可能仍会遇到 netstat
,但 ss
是当前和未来网络诊断的主力工具。理解 ss
不仅仅是学习一个新命令,更是拥抱现代 Linux 网络工具集。报告中虽然会按要求介绍 netstat
,但会投入大量篇幅介绍 ss
,突出其优势,并提供并行示例以帮助用户过渡。这使得报告更具前瞻性和实用价值。
2.7. top
核心功能: top
命令提供对 Linux 系统中正在运行的进程的动态实时视图 。它允许 SRE 监控系统性能,识别资源密集型进程。
启动 top
: 在终端输入 top
并按 Enter。
输出解释 :
- 概要区域 (Dashboard):
- 第一行: 当前时间、系统运行时间 (
up
)、登录用户数 (users
)、过去1、5、15分钟的系统平均负载 (load average
)。负载平均值表示处于可运行或不可中断睡眠状态的平均进程数。 - 第二行 (Tasks): 进程总数 (
total
)、正在运行 (running
)、休眠 (sleeping
)、停止 (stopped
)、僵尸 (zombie
) 进程的数量。 - 第三行 (%Cpu(s)): CPU 时间在不同状态下的百分比:
us
: 用户空间 (user space)。sy
: 系统空间/内核空间 (system space)。ni
: Nice 值调整过的用户进程 (nice)。id
: 空闲 (idle)。wa
: 等待 I/O (I/O wait)。hi
: 处理硬件中断 (hardware interrupts)。si
: 处理软件中断 (software interrupts)。st
: 被虚拟化环境偷走的时间 (steal time)。
- 第四行 (Mem): 物理内存使用情况 (单位通常是 KiB):
total
,free
,used
,buff/cache
。buff/cache
是被内核用于缓冲区和页面缓存的内存,可在需要时被应用程序回收。 - 第五行 (Swap): 交换空间使用情况:
total
,free
,used
。avail Mem
是可用于启动新应用程序的预计可用内存量(无需交换)。
- 第一行: 当前时间、系统运行时间 (
- 任务区域 (进程列表):
PID
: 进程 ID。USER
: 进程所有者的用户名。PR
: 进程优先级。NI
: Nice 值。负值表示高优先级,正值表示低优先级。VIRT
: 进程使用的虚拟内存总量。RES
: 进程使用的物理内存量 (驻留内存)。SHR
: 进程使用的共享内存量。S
: 进程状态 (D
=不可中断睡眠,R
=运行,S
=休眠,T
=跟踪/停止,Z
=僵尸)。%CPU
: 自上次更新以来进程使用的 CPU 时间百分比。在多核系统上,如果进程是多线程的,此值可能超过100%。%MEM
: 进程使用的物理内存百分比。TIME+
: 进程自启动以来累计使用的 CPU 时间 (通常精确到百分之一秒)。COMMAND
: 命令名或完整的命令行。
交互式命令 :
P
: 按 CPU 使用率排序 (降序)。M
: 按内存使用率排序 (降序)。T
: 按累计 CPU 时间排序 (降序)。k
: 杀掉一个进程 (会提示输入 PID 和信号,默认为 15/SIGTERM)。r
: 重新设置进程的 Nice 值 (会提示输入 PID 和新的 Nice 值)。f
: 进入字段管理界面,自定义显示的列。1
: 切换显示单个 CPU 核心与所有 CPU 核心的平均统计信息。z
: 切换彩色/单色显示。c
: 切换COMMAND
列显示命令名还是完整命令行。u
: 按用户过滤进程 (会提示输入用户名或 UID)。h
或?
: 显示帮助。q
: 退出top
。
SRE 使用场景:
- 实时监控系统负载和资源使用情况。
- 快速识别消耗 CPU 或内存过多的进程。
- 查看哪些进程处于 I/O 等待状态 (
wa
),可能指示磁盘瓶颈。 - 终止失控或无响应的进程。
- 调整进程优先级以优化关键应用性能。
2.8. vmstat (Virtual Memory Statistics)
核心功能: vmstat
报告关于虚拟内存、进程、陷阱、磁盘活动和 CPU 活动的统计信息 。它提供系统性能的快照,可以按指定的时间间隔连续更新。
基本语法: vmstat [options] [delay [count]]
delay
: 两次更新之间的延迟时间 (秒)。count
: 更新次数。如果省略count
但指定了delay
,则无限次更新。
输出字段解释 :
procs
:r
: 等待运行的进程数 (运行队列长度)。如果该值持续大于 CPU 核心数,可能表示 CPU 瓶颈。b
: 处于不可中断睡眠状态的进程数 (通常在等待 I/O)。
memory
:swpd
: 使用的虚拟内存量 (KiB)。如果该值很大且非零,表示系统正在使用交换空间。free
: 空闲物理内存量 (KiB)。buff
: 用作缓冲区的内存量 (KiB)。cache
: 用作页面缓存的内存量 (KiB)。
swap
:si
: 每秒从磁盘换入的内存量 (KiB/s)。如果持续非零,表明内存不足。so
: 每秒换出到磁盘的内存量 (KiB/s)。如果持续非零,表明内存不足。
io
:bi
: 每秒从块设备读入的块数 (通常是 KiB/s)。bo
: 每秒写入块设备的块数 (通常是 KiB/s)。
system
:in
: 每秒中断次数,包括时钟中断。cs
: 每秒上下文切换次数。高cs
值可能表明系统过于繁忙,或者有大量小任务在竞争 CPU。
cpu
: CPU 时间百分比us
: 用户态 CPU 时间百分比。sy
: 系统态 (内核态) CPU 时间百分比。id
: CPU 空闲时间百分比。wa
: 等待 I/O 的 CPU 时间百分比。高wa
值通常意味着磁盘瓶颈。st
: 从虚拟机窃取的时间百分比 (适用于虚拟化环境)。
常用选项:
-a, --active
: 显示活动和非活动内存 。-f, --forks
: 显示自系统启动以来的 fork 次数。-m, --slabs
: 显示 slabinfo。-s, --stats
: 显示各种事件计数器和内存统计信息的表格 。-d, --disk
: 显示磁盘统计信息 (需要较新内核)。-p <partition>
: 显示指定分区的详细统计信息。-S <unit>
: 指定输出单位 (k
,K
,m
,M
)。默认为K
(1024 bytes)。
SRE 使用场景:
- 监控内存使用: 检查
free
,swpd
,si
,so
来判断系统是否存在内存压力。 - CPU 瓶颈分析: 观察
r
,us
,sy
,id
,wa
。高r
值和低id
值可能表示 CPU 不足。高wa
表示 I/O 瓶颈。 - I/O 性能评估:
bi
和bo
显示磁盘活动量。 - 上下文切换监控: 高
cs
值可能需要调查。 - 示例:
vmstat 2 5
(每2秒显示一次,共显示5次)。
2.9. iostat (Input/Output Statistics)
核心功能: iostat
用于监控系统输入/输出设备和 CPU 的使用情况 。它对于识别磁盘 I/O 瓶颈特别有用。
基本语法: iostat [options] [interval [count]]
interval
: 报告之间的秒数。count
: 报告的总数。
输出字段解释 :
- CPU 利用率报告 (
avg-cpu
):%user
: 用户级别执行所占 CPU 百分比。%nice
: nice 优先级用户级别执行所占 CPU 百分比。%system
: 系统级别 (内核) 执行所占 CPU 百分比。%iowait
: CPU 等待 I/O 操作完成的时间百分比。高iowait
表示磁盘可能是瓶颈。%steal
: 虚拟机管理程序为另一个虚拟处理器提供服务时,虚拟 CPU 非自愿等待所花费的时间百分比。%idle
: CPU 空闲时间百分比。
- 设备利用率报告 (
Device:
):Device
: 设备或分区名称。tps
: 每秒传输次数 (I/O 请求数)。一个传输是一个到设备的 I/O 请求。多个逻辑请求可以合并为一个 I/O 请求到设备。tps
越高,处理器越繁忙 。Blk_read/s
或kB_read/s
(取决于选项): 每秒从设备读取的块数 (或千字节数)。Blk_wrtn/s
或kB_wrtn/s
(取决于选项): 每秒写入设备的块数 (或千字节数)。Blk_read
或kB_read
: 读取的总块数 (或千字节数)。Blk_wrtn
或kB_wrtn
: 写入的总块数 (或千字节数)。r/s
: 每秒合并的读请求数。w/s
: 每秒合并的写请求数。await
: 每个 I/O 请求的平均等待时间 (毫秒),包括在队列中等待的时间和实际服务时间。svctm
: (已弃用,可能不准确) 每个 I/O 请求的平均服务时间 (毫秒)。%util
: 设备繁忙时间的百分比。接近 100% 表示设备饱和。
常用选项:
-c
: 只显示 CPU 利用率报告 。-d
: 只显示设备利用率报告 。-k
: 以千字节为单位显示统计信息 (默认是块) 。-m
: 以兆字节为单位显示统计信息 。-x
: 显示扩展统计信息,更详细。-p [device | ALL]
: 报告指定设备或所有设备的统计信息 。-N
: 显示注册的设备映射名称 (LVM)。-t
: 在每条报告前打印时间戳。-z
: 在采样周期内,如果设备没有任何活动,则省略该设备的输出。
SRE 使用场景:
- 识别磁盘 I/O 瓶颈: 观察
%iowait
,%util
,await
,tps
。高%util
和长await
时间表明磁盘性能问题。 - 监控特定设备的性能:
iostat -p sda 2 5
(监控/dev/sda
,每2秒一次,共5次)。 - 评估读写负载: 比较
kB_read/s
和kB_wrtn/s
来了解应用的 I/O 模式。 - 示例:
iostat -xk 2 5
(每2秒显示一次扩展统计信息,以KB为单位,共5次)。
2.10. lsof (List Open Files)
核心功能: lsof
用于列出系统中所有打开的文件以及打开这些文件的进程 。在 Linux/Unix 系统中,”一切皆文件”,包括普通文件、目录、网络套接字、管道、设备等。
基本语法: lsof [options]
输出字段解释 :
COMMAND
: 打开文件的进程关联的命令名称。PID
: 打开文件的进程的进程ID。TID
: 任务 (线程) ID。如果为空,则表示是进程而非线程。USER
: 进程所属用户的用户ID或名称。FD
(File Descriptor): 文件描述符。cwd
: 当前工作目录。rtd
: 根目录。txt
: 程序文本 (代码和数据)。mem
: 内存映射文件。- 数字后跟
r
(读权限),w
(写权限),u
(读写权限)。
TYPE
: 与文件关联的节点类型。REG
: 普通文件。DIR
: 目录。CHR
: 字符特殊文件。BLK
: 块特殊文件。FIFO
:命名管道。unix
: UNIX 域套接字。IPv4/IPv6
: IP 套接字。
DEVICE
: 设备的设备号。SIZE/OFF
: 文件的大小 (字节) 或文件偏移量。NODE
: 文件的节点号 (inode number)。NAME
: 文件的名称或套接字信息 (如*:http (LISTEN)
或host:port->remote_host:port (ESTABLISHED)
)。
常用选项:
-i [protocol][@hostname|hostaddr][:service|port]
: 列出与指定网络连接相关的文件。功能强大,可以指定协议 (tcp
,udp
)、主机名/IP、服务名/端口号 。lsof -i :80
(列出使用80端口的进程)。lsof -i TCP:22
(列出使用TCP协议22端口的进程)。lsof -i @192.168.1.100
(列出与IP 192.168.1.100 相关的所有连接)。
-u <username>
: 列出指定用户打开的文件 。可使用^username
排除用户。-p <PID>
: 列出指定 PID 的进程打开的文件 。可使用逗号分隔多个 PID,或使用^PID
排除。+D /path/to/directory
: 递归列出指定目录下所有打开的文件 。-c <command_string>
: 列出其名称包含指定字符串的命令所打开的文件 。-d <FD_list>
: 列出文件描述符在指定列表中的文件。例如-d 0,1,2
。-t
: 只输出进程ID (PID),用于脚本。例如kill $(lsof -t -i:8080)
。-n
: 不解析主机名 (加快速度)。-P
: 不解析端口号为服务名 (加快速度)。-r [seconds]
: 重复执行,直到被中断。可选参数为刷新间隔。
SRE 使用场景:
- 查找哪个进程占用了特定端口:
sudo lsof -i :443
。 - 查看某个用户打开了哪些文件:
sudo lsof -u nginx
。 - 查看某个进程打开了哪些文件和网络连接:
sudo lsof -p 1234
。 - 排查 “Too many open files” 错误: 分析哪些进程打开了大量文件描述符。
- 安全审计: 检查是否有未授权的进程监听网络端口或访问敏感文件。
- 查找被删除但仍被进程占用的文件: 这些文件仍占用磁盘空间。
sudo lsof | grep '(deleted)'
。 - 示例:
sudo lsof -i TCP -sTCP:LISTEN -n -P
(列出所有正在监听的TCP端口,不解析名称)。
2.11. curl (Client URL)
核心功能: curl
是一个用于在终端与服务器之间传输数据的命令行工具,支持多种协议,最常用的是 HTTP 和 HTTPS 。SRE 常用其进行 HTTP 测试、API 交互和健康检查。
基本语法: curl [options] <url>
常用选项 (SRE 任务相关) :
-I, --head
: 只获取 HTTP 头部信息 (发送 HEAD 请求)。-L, --location
: 跟随重定向 (HTTP 3xx 响应)。-X, --request <COMMAND>
: 指定 HTTP 请求方法 (如GET
,POST
,PUT
,DELETE
,HEAD
)。-H, --header <header_line>
: 自定义 HTTP 请求头。例如-H "Content-Type: application/json"
。-d, --data <data>
: 发送 HTTP POST 请求的数据。例如-d "param1=value1¶m2=value2"
。--data-raw <data>
: 与-d
类似,但内容按字面发送,不特殊处理@
。--data-urlencode <data>
: URL 编码后发送数据。-o, --output <file>
: 将输出写入文件而不是标准输出。-O, --remote-name
: 将输出写入与远程文件同名的本地文件。-s, --silent
: 静默模式,不显示进度条或错误信息。-S, --show-error
: 静默模式下,如果发生错误,仍然显示错误信息。-v, --verbose
: 显示详细的通信过程,包括请求和响应头以及其他调试信息。-k, --insecure
: 允许连接到没有有效 SSL/TLS 证书的 HTTPS 站点 (不进行证书校验,生产环境慎用)。--connect-timeout <seconds>
: 设置最大连接超时时间。-w, --write-out <format>
: 定义在传输完成后输出的额外信息。例如curl -s -o /dev/null -w "%{http_code} %{time_total}\n" URL
可以获取 HTTP 状态码和总时间。-u, --user <user:password>
: 指定服务器认证的用户名和密码。--cacert <file>
: 指定 CA 证书文件以验证对等方。
SRE 使用场景:
- HTTP 服务健康检查:
curl -s -o /dev/null -w "%{http_code}" http://localhost/health
(检查健康检查端点的状态码,期望 200) 。curl -I http://example.com
(快速检查服务是否响应并查看头部信息) 。
- API 测试与交互:
- 发送 GET 请求:
curl -H "Authorization: Bearer <token>" https://api.example.com/v1/users
。 - 发送 POST 请求 (JSON):
curl -X POST -H "Content-Type: application/json" -d '{"name":"test", "value":123}' https://api.example.com/v1/items
。
- 发送 GET 请求:
- 下载文件:
curl -O https://example.com/archive.tar.gz
。 - 测试网络连接和 DNS 解析:
curl -v https://internal.service.local
(查看详细连接过程,包括 IP 解析) 。 - 获取 HTTP 响应头:
curl -s -D - http://example.com -o /dev/null
(将响应头打印到 stdout)。 - 测量响应时间:
curl -s -o /dev/null -w "Connect: %{time_connect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s\n" http://example.com
。 - 示例: 测试对
example.com
的 HEAD 请求,并跟随重定向:1
curl -I -L [http://example.com](http://example.com)
2.12. find
核心功能: find
命令用于在目录层次结构中搜索文件和目录,并可以对找到的文件执行操作 。
基本语法: find [path...] [expression]
path...
: 开始搜索的目录路径。默认为当前目录。expression
: 由选项、测试条件和动作组成。
常用测试条件 (Options/Expressions) :
-name <pattern>
: 按文件名匹配 (区分大小写,支持通配符,需转义或加引号)。-iname <pattern>
: 按文件名匹配 (不区分大小写)。-type <type_char>
: 按文件类型匹配。f
: 普通文件。d
: 目录。l
: 符号链接。
-user <username>
: 按文件属主匹配。-group <groupname>
: 按文件所属组匹配。-perm <mode>
: 按权限匹配。644
: 精确匹配权限。-644
: 匹配至少拥有这些权限的文件 (例如,755
会匹配-644
)。/644
或+644
(GNU find): 匹配任何用户/组/其他位设置了对应权限的文件。
-size <n>[cwbkMG]
: 按文件大小匹配。c
: 字节,k
: KiB,M
: MiB,G
: GiB。+n
: 大于 n,-n
: 小于 n,n
: 等于 n。- 例如:
find . -size +100M
(查找大于 100MB 的文件)。
-mtime <n>
: 按修改时间匹配 (天)。+n
(n天前),-n
(n天内),n
(恰好n天前)。-atime <n>
: 按访问时间匹配 (天)。-ctime <n>
: 按状态改变时间匹配 (天)。-mmin <n>
,-amin <n>
,-cmin <n>
: 按分钟匹配。-empty
: 查找空文件或空目录。-maxdepth <levels>
: 限制搜索的最大深度。-mindepth <levels>
: 从指定深度开始搜索。-nouser
: 查找没有属主的文件 (属主 UID 不在/etc/passwd
中)。-nogroup
: 查找没有所属组的文件。
常用动作 (Actions) :
-print
: (默认动作,如果未指定其他动作) 打印找到的文件路径。-ls
: 对找到的文件执行ls -dils
。-delete
: 删除找到的文件 (谨慎使用)。-exec <command> {} \;
: 对每个找到的文件执行指定的命令。{}
被替换为文件名,\;
标记命令结束。
例如:find . -type f -name "*.tmp" -exec rm -f {} \;
(删除所有.tmp
文件)。-exec <command> {} +
: 与\;
类似,但会将多个文件名作为参数传递给一次命令调用,更高效。-ok <command> {} \;
: 与-exec
类似,但在执行前会提示用户确认。
逻辑操作符:
-and
(或-a
, 默认): 与操作。-or
(或-o
): 或操作。-not
(或!
): 非操作。()
: 分组条件 (需要转义:\( ... \)
)。
SRE 使用场景:
- 查找大型日志文件:
sudo find /var/log -type f -size +500M -print0 | xargs -0 du -h
。 - 查找最近修改的配置文件:
sudo find /etc -type f -mmin -60
(查找过去60分钟内修改过的配置文件)。 - 清理临时文件:
find /tmp -type f -mtime +7 -delete
(删除/tmp
下超过7天未修改的临时文件)。 - 查找并修改文件权限:
find /var/www/html -type f -not -perm 644 -exec chmod 644 {} \;
。 - 查找属于特定用户的文件:
find /home -user suspicious_user -ls
。 - 查找 SUID/SGID 文件:
find / -type f \( -perm -4000 -o -perm -2000 \) -ls
(潜在的安全风险)。 - 示例: 查找
/opt/app/logs
目录下所有大于 10MB 且在过去3天内修改过的.log
文件,并列出详细信息:1
find /opt/app/logs -type f -name "*.log" -size +10M -mtime -3 -ls
2.13. df (Disk Free)
核心功能: df
命令用于报告文件系统的磁盘空间使用情况 。
基本语法: df [options] [file_or_filesystem...]
常用选项 :
-h, --human-readable
: 以易读的格式显示大小 (例如1K
,234M
,2G
)。-H, --si
: 以 1000 为基数显示大小 (而不是 1024)。-k, --kilobytes
: 以 KB 为单位显示大小 (默认)。-m, --megabytes
: 以 MB 为单位显示大小。-T, --print-type
: 显示文件系统类型。-i, --inodes
: 显示 inode 信息而不是块使用情况。--total
: 显示所有列出的文件系统的总计。--output[=FIELD_LIST]
: 使用自定义输出格式。FIELD_LIST
是逗号分隔的列名列表 (如source,size,used,avail,pcent,target
)。-t, --type=<type>
: 只显示指定类型的文件系统。-x, --exclude-type=<type>
: 排除指定类型的文件系统 (例如squashfs
,tmpfs
)。
输出字段解释 :
Filesystem
: 文件系统的设备名或挂载源。Size
: 文件系统总大小。Used
: 已用空间。Avail
: 可用空间。Use%
: 已用空间百分比。Mounted on
: 文件系统的挂载点。Type
(使用-T
): 文件系统类型 (如ext4
,xfs
,nfs
)。
SRE 使用场景:
- 监控磁盘空间:
df -h
是快速检查所有挂载点磁盘使用情况的首选命令。 - 自动化告警: 脚本中解析
df
输出,当Use%
超过阈值时发送告警。 - 检查特定分区:
df -h /var
(检查/var
所在分区的空间)。 - 排除临时文件系统:
df -h -x tmpfs -x devtmpfs
(查看持久存储)。 - 示例: 以人类可读格式显示
/
和/opt
分区的磁盘使用情况,并显示文件系统类型:1
df -hT / /opt
2.14. du (Disk Usage)
核心功能: du
命令用于估算和显示文件和目录所占用的磁盘空间 。
基本语法: du [options] [file_or_directory...]
- 如果未指定路径,则默认为当前目录。
常用选项 :
-h, --human-readable
: 以易读的格式显示大小。-s, --summarize
: 只显示指定参数的总计大小,不显示子目录。-a, --all
: 显示所有文件和目录的大小 (默认只显示目录)。-c, --total
: 在最后显示总计。-k, --kilobytes
: 以 KB 为单位显示 (通常是默认)。-m, --megabytes
: 以 MB 为单位显示。--max-depth=N
: 显示目录总计,仅当其层级小于等于 N 时。du -h --max-depth=1
常用于查看当前目录下各子目录的大小。-B, --block-size=SIZE
: 指定块大小。--apparent-size
: 显示表观大小,而不是磁盘使用量。对于稀疏文件等,这可能与实际磁盘占用不同。--time
: 显示上次修改时间。
SRE 使用场景:
- 查找占用空间最大的目录:
du -sh /*
(查找根目录下哪个目录占用最多,可能需要sudo
权限),或者更常用du -sh ./*
查看当前目录下。 - 按大小排序查找大文件/目录:
du -ah /var/log | sort -rh | head -n 10
(查找/var/log
下最大的10个文件或目录)。 - 分析特定应用的数据目录:
du -sh /opt/my-app/data
。 - 定期检查日志目录大小:
du -sh /var/log
。 - 示例: 显示当前目录下每个子目录的总大小 (人类可读格式,深度为1):
1
du -h --max-depth=1 .
2.15. systemctl
核心功能: systemctl
是 systemd 系统和服务管理器的主要控制工具 。SRE 用它来管理服务的生命周期 (启动、停止、重启、重载、查看状态) 以及控制系统状态。
基本语法: sudo systemctl <COMMAND> [UNIT...]
常用命令 (服务管理) :
start <unit.service>
: 启动服务。stop <unit.service>
: 停止服务。restart <unit.service>
: 重启服务。reload <unit.service>
: 重载服务配置 (如果服务支持)。status <unit.service>
: 查看服务状态,包括是否活动、PID、最近的日志等。enable <unit.service>
: 设置服务开机自启。disable <unit.service>
: 取消服务开机自启。is-active <unit.service>
: 检查服务是否正在运行。is-enabled <unit.service>
: 检查服务是否设置为开机自启。is-failed <unit.service>
: 检查服务是否启动失败。mask <unit.service>
: 完全禁用一个服务,使其无法启动 (通过链接到/dev/null
)。unmask <unit.service>
: 解除服务的mask
状态。
常用命令 (单元文件和依赖) :
list-units [--type=service] [--all] [--state=active|inactive|failed]
: 列出加载的单元。list-unit-files [--type=service]
: 列出所有已安装的单元文件及其状态。cat <unit.service>
: 查看单元文件的内容。show <unit.service> [-p PropertyName]
: 显示单元的底层属性。list-dependencies <unit.service> [--reverse] [--all]
: 显示单元的依赖关系。daemon-reload
: 在修改单元文件后,重新加载 systemd 管理器配置。
常用命令 (系统状态) :
get-default
: 获取默认的启动目标 (类似运行级别)。set-default <target.target>
: 设置默认的启动目标。isolate <target.target>
: 切换到指定目标,停止不属于该目标的单元。reboot
,poweroff
,halt
,suspend
,hibernate
,hybrid-sleep
,rescue
,emergency
。
SRE 使用场景:
- 服务部署与管理: 启动、停止、重启应用服务 (如
nginx
,tomcat
,database
)。 - 故障排查: 使用
systemctl status myapp.service
查看服务失败原因,结合journalctl -u myapp.service
查看详细日志。 - 确保服务自启动:
sudo systemctl enable mycritical.service
。 - 系统维护: 切换到
rescue.target
或emergency.target
进行维护。 - 查看单元配置:
systemctl cat httpd.service
检查服务启动脚本和配置。 - 示例: 检查
nginx
服务状态,如果未运行则尝试启动,并设置为开机自启:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15if ! systemctl is-active --quiet nginx; then
echo "Nginx is not running, starting..."
sudo systemctl start nginx
if systemctl is-active --quiet nginx; then
echo "Nginx started successfully."
if ! systemctl is-enabled --quiet nginx; then
echo "Enabling Nginx to start on boot."
sudo systemctl enable nginx
fi
else
echo "Failed to start Nginx. Check 'systemctl status nginx' and 'journalctl -u nginx'."
fi
else
echo "Nginx is already running."
fi
2.16. journalctl
核心功能: journalctl
用于查询和显示由 systemd 日志服务 journald
收集的日志 。它提供了集中的日志管理,可以按时间、单元、优先级等多种条件过滤。
基本语法: journalctl [options] [matches...]
常用选项与过滤 :
- 无选项: 显示所有日志 (从旧到新)。
-r, --reverse
: 反向显示日志 (从新到旧)。-n <number>, --lines=<number>
: 显示最近的指定行数日志 (默认10行)。-f, --follow
: 实时跟踪新日志 (类似tail -f
)。-b [<id>|<offset>], --boot[=<id>|<offset>]
: 显示指定启动周期的日志。-b
(当前启动),-b -1
(上次启动)。--list-boots
: 列出可用的启动周期。--since <datetime>, --until <datetime>
: 按时间范围过滤。接受多种格式,如"YYYY-MM-DD HH:MM:SS"
,"yesterday"
,"2 hours ago"
。-u <unit>, --unit=<unit>
: 按 systemd 单元过滤 (例如nginx.service
,sshd.service
)。-k, --dmesg
: 只显示内核消息 (同dmesg
命令)。-p <priority>, --priority=<priority>
: 按消息优先级过滤。优先级从0
(emerg) 到7
(debug)。例如-p err
(显示err
,crit
,alert
,emerg
)。_PID=<PID>
: 按进程 ID 过滤。_UID=<UID>
: 按用户 ID 过滤。_EXE=/path/to/executable
: 按可执行文件路径过滤。--grep <pattern>
: (较新版本) 在消息字段中搜索模式 (类似grep
)。-o <format>, --output=<format>
: 指定输出格式。short
(默认): 经典 syslog 格式。short-iso
: 带 ISO 8601 时间戳。verbose
: 显示所有字段。json
: JSON 格式。json-pretty
: 格式化的 JSON。cat
: 只显示消息本身。
--no-pager
: 直接输出到 stdout,不使用分页器 (如less
)。--disk-usage
: 显示日志占用的磁盘空间。--vacuum-size=<bytes>
: 清理旧日志,使其总大小不超过指定值。--vacuum-time=<time>
: 清理早于指定时间的日志。
SRE 使用场景:
- 故障排查:
- 查看特定服务的日志:
journalctl -u myapp.service -f
。 - 查看特定时间段的错误日志:
journalctl -p err --since "1 hour ago"
。 - 查看内核崩溃或硬件错误:
journalctl -k -p crit -b -1
(查看上次启动的严重内核消息)。
- 查看特定服务的日志:
- 安全审计:
- 查看 SSH 登录尝试:
journalctl -u sshd --since yesterday | grep 'Failed password'
。 - 查看
sudo
使用记录:journalctl _EXE=/usr/bin/sudo
。
- 查看 SSH 登录尝试:
- 性能分析: 结合日志中的时间戳和事件,分析系统行为。
- 日志管理: 使用
--disk-usage
,--vacuum-size
,--vacuum-time
管理日志存储。 - 示例: 查看
nginx
服务在过去2小时内所有级别为warning
或更高的日志,并以 JSON 格式美化输出:1
journalctl -u nginx.service -p warning --since "2 hours ago" -o json-pretty
3. 实战 SRE 案例分析:Web 服务器性能下降故障排除
本案例将模拟一个典型的 SRE 场景:一个关键的 Web 应用程序(例如电子商务网站)托管在 Linux 服务器上,在高峰时段出现间歇性响应缓慢和 HTTP 5xx 错误率增加的情况。用户报告页面加载缓慢或超时。SRE 团队接到告警,需要介入排查。
初步假设: 问题可能源于应用层 bug、资源耗尽 (CPU、内存、I/O)、网络瓶颈、数据库问题或外部依赖项缓慢。
步骤 1: 初步分诊与系统概览 (服务器是否存活?总体状态如何?)
这是故障排除的第一步,快速检查系统的“生命体征”,判断是否存在明显的、全局性的资源问题。
- 命令:
uptime
- 操作: 检查平均负载 (load average)。
- 解读: 平均负载(1分钟、5分钟、15分钟)是衡量系统繁忙程度的重要指标。如果负载持续高于 CPU 核心数,表明系统可能过载,有大量进程在等待 CPU 资源 。例如,一个4核系统,如果15分钟负载持续在 8.0 以上,则表明系统压力较大。
- 命令:
df -h
- 操作: 检查关键分区的磁盘空间使用情况,如
/
,/var
(通常包含日志),/tmp
, 以及应用数据所在的挂载点。 - 解读: 磁盘空间不足(例如,使用率超过 90-95%)会导致各种应用故障和性能问题,如无法写入日志、无法创建临时文件等。
- 操作: 检查关键分区的磁盘空间使用情况,如
- 命令:
free -m
- 操作: 检查内存使用情况 (
total
,used
,free
,buff/cache
,swap
)。 - 解读:
free
列显示的空闲物理内存过低,同时swap
的used
列值较高且持续增长,通常表示系统内存压力大,正在频繁使用交换空间,这会严重影响性能。buff/cache
占用的内存通常可以被内核回收,所以不能简单地认为used
高就代表内存不足,需要结合available
(如果free
命令支持) 或free
和buff/cache
的关系来看。
- 操作: 检查内存使用情况 (
- 命令:
ping <gateway/external_resolver>
- 操作: 进行基本的网络连通性测试,例如 ping 网关或一个可靠的外部 DNS 服务器。
- 解读: 丢包或高延迟可能指示本地网络、ISP 或更广泛的网络存在问题。
这种初步分诊如同医生检查病人的生命体征,快速、基础,但能有效地过滤掉一些常见的、根本性的问题。如果磁盘满了,或者内存完全耗尽,那么进一步深入分析应用日志可能意义不大,需要先解决这些基础资源问题。这个阶段的检查结果将指导后续的排查方向。
步骤 2: 识别高资源消耗进程
如果初步检查未发现明显的磁盘或基础网络问题,接下来需要找出哪些进程消耗了过多的 CPU、内存或导致了 I/O 等待。
- 命令:
top
(或htop
)- 操作: 实时观察 CPU 和内存使用情况。在
top
界面中,可以按P
以 CPU 使用率排序,按M
以内存使用率排序。重点关注%CPU
,%MEM
列,以及 CPU 状态行中的wa
(I/O 等待) 和id
(空闲) 百分比。 - 解读: 识别哪些进程 (例如 Web 服务器进程
nginx/httpd
、应用服务器进程java/python/node
、数据库进程mysqld/postgres
) 持续占用高 CPU 或内存。如果wa
值很高,说明 CPU 大量时间在等待 I/O 操作完成,可能存在磁盘瓶颈。
- 操作: 实时观察 CPU 和内存使用情况。在
- 命令:
ps aux --sort=-%cpu,%mem | head -n 15
- 操作: 获取 CPU 和内存消耗最高的进程快照,如果
top
的动态显示不便记录或用于脚本。 - 解读: 与
top
的观察结果进行交叉验证。记录可疑进程的 PID。
- 操作: 获取 CPU 和内存消耗最高的进程快照,如果
- 命令:
vmstat 1 5
(每秒输出一次,共输出5次)- 操作: 检查
procs
列的r
(运行队列中的进程数) 和b
(阻塞的进程数),swap
列的si
(换入) 和so
(换出),以及system
列的cs
(上下文切换)。 - 解读:
r
值持续大于 CPU 核心数,表示 CPU 瓶颈。b
值较高,表示许多进程在等待资源,通常是 I/O。si
和so
持续非零,确认内存压力和频繁的磁盘交换。cs
值异常高,可能意味着系统中断过多或调度效率低下。
- 操作: 检查
- 命令:
iostat -xz 1 5
(每秒输出一次,共输出5次,显示扩展统计信息)- 操作: 检查磁盘 I/O 统计信息,关注
%util
(设备繁忙百分比),r/s
(每秒读次数),w/s
(每秒写次数),await
(平均每次I/O请求的等待时间,包括队列等待和服务时间),avgqu-sz
(平均请求队列长度)。 - 解读: 某个磁盘的
%util
持续接近 100%,同时await
时间很长,或者avgqu-sz
很大,都表明该磁盘存在 I/O 瓶颈。
- 操作: 检查磁盘 I/O 统计信息,关注
步骤 3: 分析 Web 服务器和应用日志
日志是排查问题的金矿。假设我们使用 Nginx 作为 Web 服务器,其日志位于 /var/log/nginx/access.log
和 /var/log/nginx/error.log
。应用程序日志位于 /var/log/app/application.log
。
- 命令:
tail -n 500 /var/log/nginx/error.log | grep -iE 'error|crit|alert'
- 操作: 查看 Nginx 错误日志中最近的严重错误。
-E
启用扩展正则,|
表示或。 - 解读: 关注 Nginx 配置错误、上游服务器连接失败 (例如连接应用服务器超时)、资源限制等。
- 操作: 查看 Nginx 错误日志中最近的严重错误。
- 命令:
grep 'HTTP/1\.." 50' /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -nr | head -n 10
- 操作: 从 Nginx 访问日志中统计出现频率最高的 HTTP 50x 错误状态码。
grep 'HTTP/1\.." 50'
: 筛选出包含 “HTTP/1.” 并且状态码以 “50” 开头的行 (捕获 500, 502, 503, 504 等)。awk '{print $9}'
: 提取第9个字段 (通常是状态码)。sort | uniq -c
: 对状态码进行排序并统计唯一值的出现次数。sort -nr | head -n 10
: 按出现次数降序排序并显示前10个。
- 解读: 快速了解哪种类型的服务器端错误最普遍。
- 操作: 从 Nginx 访问日志中统计出现频率最高的 HTTP 50x 错误状态码。
- 命令:
awk '($9 ~ /^5/) {ip_count[$1]++; path_count[$7]++; total_5xx++} END {print "Total 5xx:", total_5xx; for(ip in ip_count) print "IP:", ip, "Count:", ip_count[ip]; for(path in path_count) print "Path:", path, "Count:", path_count[path]}' /var/log/nginx/access.log | sort -k3nr | head -n 20
- 操作: 提取所有 5xx 错误的请求,统计来源 IP 和请求路径的分布,并按数量排序。
($9 ~ /^5/)
:awk
的模式,匹配第9个字段 (状态码) 以5开头的行。{ip_count[$1]++; path_count[$7]++; total_5xx++}
: 对匹配的行,累加总的5xx错误数,并用关联数组统计每个源IP ($1
) 和请求路径 ($7
) 出现的次数。END {...}
: 在处理完所有行后,打印总的5xx错误数,然后遍历并打印IP计数和路径计数。| sort -k3nr | head -n 20
: 对awk
的输出(假设IP和路径计数格式为 “Type: Value Count: N”)按第3列(即数量N)进行数字反向排序,并显示前20条。
- 解读: 确定是特定IP的恶意请求,还是特定API端点或页面普遍存在问题。
- 操作: 提取所有 5xx 错误的请求,统计来源 IP 和请求路径的分布,并按数量排序。
- 命令:
tail -n 1000 /var/log/app/application.log | grep -C 5 -iE 'Exception|Error|Timeout|FATAL'
- 操作: 在应用日志中查找异常、错误或超时信息,并显示匹配行的上下文 (
-C 5
显示前后各5行)。 - 解读: 寻找应用层面的具体错误堆栈,例如数据库连接失败、空指针异常、第三方服务调用超时等。
- 操作: 在应用日志中查找异常、错误或超时信息,并显示匹配行的上下文 (
- 命令:
sed -n '/START_SLOW_QUERY_LOG/,/END_SLOW_QUERY_LOG/p' /var/log/app/application.log | tail -n 100
- 操作: 如果应用程序有特定的日志格式来标记慢查询或耗时操作的开始和结束,可以使用
sed
提取这些相关的日志块。 - 解读: 帮助隔离与性能问题直接相关的事务或操作。
- 操作: 如果应用程序有特定的日志格式来标记慢查询或耗时操作的开始和结束,可以使用
日志分析是一个迭代的过程。通常不是一个命令就能解决问题,而是通过一系列 grep
, awk
, sed
等命令的组合,逐步筛选、提取、聚合信息,从而形成对问题的理解。例如,先用 grep
找到错误,再用 awk
统计错误类型和来源,用 sed
清理或格式化时间戳以便分析。这种与日志的“对话”是SRE的核心技能。
步骤 4: 网络连接分析
网络问题也可能导致服务缓慢或不可用。
- 命令:
ss -tulnp
(或netstat -tulnp
)- 操作: 检查哪些端口正在被哪些进程监听。验证 Web 服务器和应用服务器是否在预期的端口和IP地址上监听。
- 解读: 确保服务正常监听。没有意外的端口被监听(可能是恶意软件)。如果服务监听在
127.0.0.1
而不是0.0.0.0
或特定公网IP,则外部无法访问。
- 命令:
ss -tpn state established '( dport = :80 or dport = :443 )' | wc -l
- 操作: 统计到 Web 服务器端口 (80/443) 的已建立连接数。
- 解读: 连接数异常高可能表明服务器负载过大、连接未能及时释放(连接泄漏),或者是DDoS攻击的前兆。
- 命令:
ss -tpn state time-wait | wc -l
- 操作: 统计处于
TIME_WAIT
状态的连接数。 - 解读: 大量的
TIME_WAIT
连接会占用客户端端口资源,可能导致无法建立新的出站连接。这可能表明短连接过多,或者需要调整内核的tcp_tw_reuse
和tcp_tw_recycle
参数(后者需谨慎使用,可能导致NAT环境下的问题)。
- 操作: 统计处于
- 命令:
sudo lsof -i :<port_of_suspect_process_PID>
- 操作: 如果在步骤2中发现某个进程可疑 (例如,PID为1234的Java应用),使用此命令查看该进程建立了哪些网络连接。
- 解读: 确认该进程正在与哪些远程主机和端口通信,是否符合预期。例如,应用是否在尝试连接一个响应缓慢的数据库或外部API。
步骤 5: 防火墙检查 (如果怀疑网络问题)
错误的防火墙配置可能导致合法的用户请求被阻止。
- 命令:
sudo iptables -L INPUT -v -n --line-numbers
- 操作: 查看
INPUT
链的规则。检查数据包和字节计数器。 - 解读: 寻找可能阻止到 Web 服务器端口的合法流量的规则。针对 Web 端口的
DROP
或REJECT
规则上如果数据包计数很高,可能表明配置错误或正在遭受攻击。
- 操作: 查看
- 命令:
sudo iptables -L -t nat -v -n --line-numbers
- 操作: 如果涉及 NAT (例如,负载均衡器后的服务器,或 Docker 环境),检查
nat
表的规则。 - 解读: 不正确的 NAT 规则 (如
PREROUTING
中的DNAT
规则) 会破坏连接。
- 操作: 如果涉及 NAT (例如,负载均衡器后的服务器,或 Docker 环境),检查
- 命令:
grep 'IPTABLES-INPUT-DENIED' /var/log/syslog
(或/var/log/kern.log
,取决于日志配置)- 操作: 如果在
iptables
规则中为被拒绝的数据包配置了LOG
目标 (如步骤 2.2 的示例),则检查这些日志。 - 解读: 查看具体哪些流量被防火墙丢弃,包括源IP、目标端口等信息。
- 操作: 如果在
步骤 6: 使用 strace 进行深度挖掘 (如果特定进程行为异常)
当怀疑某个特定进程(如 Web 服务器的工作进程或应用服务器实例)由于系统调用层面的问题而表现异常时,strace
是一个强大的工具。
- 命令:
sudo strace -p <PID_of_web_server_worker_or_app_process> -s 1024 -ttt -f -o /tmp/strace_output.txt
- 操作: 跟踪指定 PID 进程的系统调用。
-p <PID>
: 指定要跟踪的进程ID。-s 1024
: 设置每个系统调用参数字符串的最大显示长度。-ttt
: 在每行输出前打印微秒级时间戳。-f
: 跟踪由fork
,vfork
,clone
创建的子进程。-o /tmp/strace_output.txt
: 将输出保存到文件。
- 解读: 分析
strace_output.txt
文件。寻找:- 耗时过长的系统调用: 特别是文件 I/O (
read
,write
,openat
) 或网络 I/O (sendto
,recvfrom
,connect
)。 - 频繁的错误返回: 例如
EACCES
(权限不足),ENOENT
(文件或目录不存在),ECONNREFUSED
(连接被拒绝)。 - 进程长时间阻塞在某个系统调用上: 例如
epoll_wait
,select
等待网络事件。 - 大量不必要的系统调用: 可能指示应用逻辑低效。
- 耗时过长的系统调用: 特别是文件 I/O (
- 操作: 跟踪指定 PID 进程的系统调用。
- 命令 (分析
strace
输出):1
grep -E 'open|read|write|connect|sendto|recvfrom|socket|bind|listen|accept|close|poll|select|epoll_wait' /tmp/strace_output.txt | awk '{ if ($NF ~ /^-1/) {print "Failed syscall:", $0} else {print $1, $NF} }' | sort | uniq -c | sort -nr | head -n 20
- 操作:
grep -E '...'
: 筛选出与文件或网络操作相关的常见系统调用。awk '{ if ($NF ~ /^-1/)... else... }'
:awk
判断系统调用是否失败 (通常返回-1,并在最后跟着错误码如ENOENT
)。如果失败,打印整行;否则打印时间戳和系统调用名。sort | uniq -c | sort -nr | head -n 20
: 统计各种系统调用的频率或失败情况,并显示最常见的。
- 解读: 帮助快速定位最频繁或最常失败的系统调用,从而缩小问题范围。例如,如果看到大量
openat
调用失败并返回ENOENT
,可能意味着应用在尝试访问不存在的配置文件或资源。
- 操作:
strace
是一个高级调试工具,其输出可能非常庞大和复杂,需要一定的经验来解读。通常在其他工具无法明确指出问题根源时使用。
步骤 7: 综合分析与解决
在收集了来自多个工具的数据后,SRE 需要将这些信息综合起来,形成对问题的整体判断,并制定解决方案。
示例综合分析:
top
显示多个nginx
工作进程 CPU 使用率很高。iostat
显示/var/log
所在磁盘的%iowait
和%util
很高。du -sh /var/log/nginx
显示 Nginx 日志文件异常巨大。- 通过
grep
和awk
分析 Nginxaccess.log
,发现大量针对某个不存在的大型静态文件的请求,且源 IP 集中 (可能是配置错误的爬虫或小规模 DoS 攻击)。 - Nginx 正在为每个失败的请求(404 Not Found)尝试写入大量错误日志,导致磁盘 I/O 不堪重负,进而影响了正常请求的处理,表现为 CPU 升高(忙于日志写入和处理请求队列)和响应缓慢。
基于上述示例的潜在解决方案:
- 使用
iptables -I INPUT -s <bad_ip> -j DROP
阻止恶意或行为异常的 IP 地址。 - 修改 Nginx 配置,对于静态文件的 404 错误不记录到
error.log
,或者减少日志级别,或者对特定 User-Agent 的请求进行速率限制或直接返回 403/444。 - 确保 Nginx 日志已配置
logrotate
进行定期轮转和压缩,防止单个日志文件无限增长。 - 清理
/var/log
下不必要的旧日志文件以释放磁盘空间 (如果需要,先归档)。 - 在实施更改后,持续使用
top
,iostat
,ss
和日志分析命令监控系统状态,确认问题是否得到缓解。
故障排除是一个系统性的过程,SRE 需要像侦探一样工作。来自一个工具的证据(例如,ps
显示一个繁忙的进程)提供了一条线索,然后使用其他工具(例如,对该进程使用 lsof
查看其打开的文件和网络连接,使用 strace
跟踪其系统调用,或者使用 grep
/awk
分析其相关的日志)进行深入调查。根本原因往往在多个观察结果的交汇点被发现。没有哪个单一的命令能够揭示全部真相,关键在于如何组合运用这些工具,并从它们的输出中交叉验证信息,从而构建出对问题根源的合理解释和有效的解决方案。