linux问题排查

web排查方法论

nginx+php

  • 日志排查access_log、error_log、php-fpm.log、php_errors.log,日志中可能存在权限、文件不存在、超时等错误记录
  • strace查看系统调用
  • tcpdump抓包

top

P按CPU使用率排序
M按内存使用率排序

按1 可查看核心数
RES (一个任务正在使用的没有交换的物理内存)我们一般称为驻留内存空间

按swap占用排序 top->O->p->enter R切换正序/倒序

1
2
3
4
top -b -n1 -o +%CPU
-b 非交互模式
-n 输出次数
-o 排序字段

状态值

  • R Running或Runnale 表示进程在CPU的就绪队列中,正在运行或正在等待运行
  • D Disk Sleep,也就是不可中断状态睡眠。一般表示进程正在和硬件交互,并且交互过程不允许被其他过程或中断打断
  • Z 僵尸进程,表示进程实际已经结束了,但是父进程还没回收它的资源(比如进程的描述符、PID等)
  • S是 Interruptible Sleep的缩写,也就是可中断睡眠状态,表示进程因为等待某个事情而被系统挂起。当进程等待的事情发生时,他会被唤醒并进入R状态
  • I 是Idle的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致不可中断进程用D,但对某些内核线程来说,他们有可能实际上并没有任何负载,用Idle正式为了区分这种情况,要注意,D状态的进程会导致平均负载升高,而I不会
  • T Stopped或Traced的缩写,表示进程正处于暂停或跟踪状态。比如当你用调试器(比如gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态。
  • X 表示进程已经消亡,你不会再top或ps命令中看到它

另外ps中还会显示入Ss+这样的状态,S表示中断睡眠状态,s表示这个进程是一个会话的领导进程,而+表示前台进程组

  • 进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员
  • 而会话是指共享同一个控制终端的一个或多个进程组

比如我们通过SSH登录服务器,就会打开一个控制终端(tty),这个控制终端就对应一个会话。而我们在终端中运行的命令及他们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。

pidstat

1
2
3
4
5
6
7
pidstat -wut -p xxx
-w 显示任务切换信息
-u 显示cpu利用率信息
-t 显示任务相关线程信息
pidstat -d 1
-d 显示I/O信息

pidstat 中, %wait 表示进程等待运行的时间所占CPU时间百分比。此时进程是运行状态。
top 中 ,iowait% 则表示等待 I/O 的 CPU 时间百分比。此时进程处于不可中断睡眠态。

等待 CPU 的进程已经在 CPU 的就绪队列中,处于运行状态;而等待 I/O 的进程则处于不可中断状态。

strace

strace-跟踪进程中的系统调用

perf

20190408155470069541565.png

1
perf top -g -p xxx

在行上按回车可以展开调用关系

-p 指定进程号

-g 开启调用关系分析

-a 来自所有CPU的系统范围的集合

另外可以利用perf record -g -a记录信息,然后使用perf report查看

1
2
3
perf record -g -a
perf report

20190224155093840310543.png

使用perf时,看到的是16进制地址而不是函数名

方法1: 在容器内perf

方法2: 容器外perf record,把生成的data文件拷贝到容器里来分析:

1
2
3
4
5
docker cp perf.data phpfpm:/tmp
docker exec -i -t phpfpm bash
cd /tmp
apt-get update && apt-get install -y linux-tools linux-perf procps
perf_4.9 report

perf的报告中,很多符号都不显示调用栈

20190224155101187290470.png

perf record -g 等同于perf record —call-graph graph,0.5.caller,function,percent

可以看到默认threshold(阈值)为0.5,时间比例超过0.5%时,调用栈才能被显示。这种情况下,你只需要给perf report设置一个小于0.34%的阈值,就可可以显示我们想看到的调用图了

1
perf report -g graph,0.3

20190224155101185940284.png

如何理解perf的报告

首先你会发现,perf report界面中swapper高达99%的比例,直接告诉我们,应该直接观察它对么,为什么没有那么做呢?

系统初始化时创建init进程,之后,swapper就成了一个最低优先级的空闲任务。当CPU上没有其他任务运行时,就会执行swapper,你可以称它为“空闲任务”

回到我们的问题,展开swapper的调用栈,你会发现swapper时钟事件都耗费在do_idle上,也就是执行空闲任务。

20190224155101224436397.png

所以案例分析时,我们直接忽略这个99%的符号,转而分析后面只有0.3%的app

报告中字段的解释如下:

  • Self 最后一列符号(可以理解为函数)本身所占比例
  • Children是这个符号调用的其他符号(可以理解为子函数,包括直接和间接调用)占用的比例之和

参考

Linux Performance

vmstat

CPU相关-性能观测

iostat

1
2
3
4
5
6
7
8
9
10
11
12
13
$ iostat -d -x 1
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
loop0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.11 0.00 0.00 9.64 0.00 0.00 0.00
scd0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00 0.00 28.38 0.00 0.24 0.00
vda 0.38 3.93 7.86 38.44 0.00 2.49 0.00 38.82 2.12 1.02 0.00 20.89 9.79 0.09 0.04
vdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 3.41 0.00 0.00 25.11 0.00 0.40 0.00
r/s 设备每秒完成的请求读取数
rrqm/s 排队到设备的每秒合并的请求读取数
r_await 发向设备的读取请求的平均时间
aqu-sz 发向设备的请求的平均队列长度
svctm 向设备发出的 I/O 请求的平均服务时间
%util 设备的带宽利用率

查看cpu平均负载

1
2
3
4
5
$ uptime
20:45:08 up 657 days, 3:59, 9 users, load average: 1.08, 1.13, 1.09
1515分的负载分别是1.08,1.13,1.09
负载最低是0,最高是1*cpu核心数

查询历史服务器信息

sar -q 查看历史负载 (相当于历史时间的uptime)
sar -r 查看内存
sar -u 查看cpu
sar -b 查看io

sar -n DEV 查看网络报告

20190228155136921692347.png

PPS(每秒收发报文数)

BPS(每秒收发字节数)

sar N N秒一次显示统计信息

配置文件在sysstat中,记得开启

%iowait
iowait表示在一个采样周期内有百分之几的时间属于以下情况:cpu空闲且有仍未完成的I/O请求
对iowait常见误解有两个

  • iowait表示cpu不能工作
  • iowait表示有io瓶颈
    iowait升高并不能证明等待I/O的进程数多了,也不能证明等待I/O的总时间增多了
    iowait是一个非常模糊的指标,如果看到iowait升高,还要看I/O量有没有明显增加,比如iostat、sar -b
    可以用$ stress-ng -i 1 --hdd 1 --timeout 600来模拟io压力 -i 的含义还是调用 sync,而—hdd 则表示读写临时文件

查看网络情况

1
2
3
4
5
6
7
netstat -ntlp
ss -ntlp|cat
ss -ntlp默认输出格式不太美观 使用|cat会更符合正常人审美
ss比netstat快
ss -o state established|cat

查看状态为established的连接(并发数)

1
2
netstat -nal|grep ESTABLISHED|wc -l
ss -o state established|wc -l

查看httpd连接数

ps -ef|grep httpd|wc -l

查看80端口连接数

netstat -nat|grep ‘:80 ‘|wc -l

查看连接统计信息

1
2
3
4
5
6
7
8
9
10
11
$ ss -s
Total: 242 (kernel 942)
TCP: 21 (estab 5, closed 1, orphaned 0, synrecv 0, timewait 0/0), ports 0
Transport Total IP IPv6
* 942 - -
RAW 0 0 0
UDP 7 5 2
TCP 20 18 2
INET 27 23 4
FRAG 0 0 0

列出正在监听的接口

ss -l

查看内存使用情况

free -m

查看相关文件

1
2
3
4
5
6
lsof -p
lsof -Pni :port
-P 禁止将端口号转换为网络文件的端口名
-n selects the listing of NFS files.
-i 选择与网络地址相关的文件列表

抓包

1
2
#使用ASCII的方式打印各个包 通常用于查看web信息
$ tcpdump -i 1 port 8888 -A

ngrep查看网络数据包

强大的抓包工具ngrep

FAQ

1. 为什么有时候iowait比较高,但是iostat却发现io的使用率并不高

iowait只是代表CPUI/O操作的时间占用的百分比,并不代表磁盘IO存在瓶颈。假如这时候没有其他进程在运行,那么很小的I/O就会导致iowait升高

用十条命令在一分钟内查询linux服务器性能

手把手教你用Strace诊断问题