Linux 系统监控

2014 年 5 月 13 日

CPU 监控

(1) /proc/cpuinfo 查看 CPU 的基本信息.

(2) uptime 查看最近的系统负载.

(3) vmstat 监控, 参数说明见表格.

标记 含义
proc - r 运行和等待cpu时间片的进程数量 如果长时间大于0, 表示cpu不足
proc - b 等待资源(IO、memory)的进程数量 如果长时间大于0, 表示cpu不足
cpu - us 用户态时间 如果us + sy 大于80, 表示cpu不足
cpu - sy 系统态时间 如果us + sy 大于80, 表示cpu不足
cpu - id 系统空闲时间
cpu - wa 等待IO时间
cpu - st 非自愿等待时间(系统调度)

(4) sar 监控(有的Linux发行版本下默认是没有安装sar的, 需要安装sysstat包)

标记 含义
%user 等同于vmstat的us
%nice 进程正常运行消耗的cpu(去除系统调度等其他开销)
%system 等同于vmstat的sy
%iowait 等同于vmstat的wa
%steal 内存紧张时, pagein强制对不同的页面做的steal
%idle 等同于vmstat的id

(5) mpstat 监控

与sar和vmstat不太一样的是, mpstat的统计项多了几条:

标记 含义
%irq 中断消耗的cpu时间
%soft 软中断消耗的cpu时间
%intr/s cpu每秒收到的中断个数

(6) top 监控, 最常用的两种观察方法:

  • 按'1'能查看到当前系统的cpu负载

  • 'b''x'进入列高亮模式之后, '<'或者'>'选择到cpu这一栏, 能看到最耗cpu的进程排行

memory 监控

(1) free 查看内存的基本信息:

标记 含义
total 物理总内存
used 已经使用的内存
free 剩余内存
shared 使用的共享内存
buffers 磁盘块的读写缓存
cached 文件读写的cache
- buffer/cache 实际使用的内存, userd - buffer - cache
+ buffer/cache 实际可用的内存, free + buffer + cache
swap 交换分区
  • buffer和cache是正常的现象, 它们大幅度的提高了磁盘IO的性能, 实际监控时, 需要将buffer/cache排除在外, +/- buffer/cache 才能反映真实的系统内存情况.
  • 如果swap经常用到了很多, 这是真的内存不够了, 需要引起注意.
  • 有一种不推荐的方式可以清空cache和buffer: echo "3" > /proc/sys/vm/drop_caches, 这会降低磁盘IO的效率.
  • 一般的经验公式是: 实际使用内存 / 系统物理内存 > 70% 时, 需要引起注意,考虑加内存了.

(2) vmstat 监控内存: 图和上一节一样, 就不单独截了, 重点关注memory和swap列.

标记 含义
swpd 交换到swap的内存, 单位为k, 等同于free中的swap used. 如果si, so长期为0, swpd偶尔变大也没关系.
free 等同于 free -m 中的 free
buff 等同于 free -m 中的 buffer
cache 等同于 free -m 中的 cache
si swap in, 内存进入 swap 交换区的数量
so swap out, swap交换区进入内存的数量

(3) top 监控内存: 'm'打开内存项. 同时, 也可以列排序到 %MEM 这一栏观察进程的内存消耗.

top 中显示的跟内存相关项说明如下:

标记 含义
VIRT 进程占用总虚存, 包括了code, data, 动态链接库以及swap\一般看进程占用内存及内存泄漏, 关注这一项就对了
RES man 上的解释是非swap内存, 早期版本的 kernel 上 man page 里会说 RES = CODE + DATA, 但是实际漏了动态链接库的部分
SHR 共享内存段, 包括mmap以及动态链接的部分

磁盘IO监控

(1) iostat 监控

标记 含义
tps 每秒处理的请求
kB_read/s 每秒的读数据量, 单位 KB
kB_wrtn/s 每秒的写数据量, 单位 KB
kB_read 监控时间内的总读数据量, 单位 KB
kB_wrtn 监控时间内的总写数据量, 单位 KB

可以通过每秒的读写数据量, 对磁盘 IO 有一个基本认识, 如果长期数值都比较大, 需要考虑做一下优化.

(2) sar 监控

  • 整体的IO监控, 只要观察%iowait这一项, 图同cpu一节, 就不在截图了.
  • sar -d 可以观察每一块磁盘设备的IO.
  • sar -b 可以监控IO速率, 类似iostat, 不过单位是block.

标记 含义
rd_sec/s 每秒读取的sectors(每sector 512字节)
wr_sec/s 每秒写的sectors(每sector 512字节)
avgrq-sz 设备请求的平均size
await 设备进行IO操作的平均等待时间(包含了IO队列的等待时间, 单位毫秒)
svctm 设备进行IO操作的服务时间(真正做IO的时间, 单位毫秒)
%util IO操作的时间百分比

对于磁盘IO, 一般有如下的评判标准:

  • 正常情况下svctm小于await, 而svctm的大小和磁盘性能有关, cpu和内存的负载也会对svctm有影响.
  • await的值, 是svctm加上IO队列等待的时间, 所以如果svctm与await非常接近, 说明IO队列几乎没有等待, 性能很好. 如果svctm和await相差比较大, 则说明IO队列等待的时间比较长, 可以做点优化了, 无论是应用层, 还是直接换硬件.
  • %util也是衡量IO的一个重要指标, 这个值如果长期比较高, 表示IO存在瓶颈.

(3) 关于磁盘IO的一些建议

  • 一般IO比较重的磁盘应用来做存储居多, 绝大部分会需要raid, 根据应用的不同, 选择合适的raid方式.
  • 努力的使用cache, 尽可能的使用内存, 减少IO的次数.
  • 读写分离, 轻重分离.
  • 如果写比较重, 可以考虑直接写裸设备, 代替文件系统, 不过个人觉得不要轻易尝试.

网络监控

(1) 检查网络的联通性: ping(网络是否联通) + telnet(端口是否开启). 检查网路问题的第一方法, 简单实效.

(2) netstat 检查网络的基本情况, 配合grep和wc, 以及在心中的tcp状态图, 查问题的效率会出乎意料的高.

(3) ethtool 获取网卡设备的信息

ethtool 的参数可以man到, 一般的用法也比较简单:

标记 含义
ethtool -i 获取网卡设备的信息
ethtool -d 获取网卡设备的注册信息
ethtool -r 重置网卡设备的统计信息
ethtool -S 查询网卡设备的收发包统计信息
ethtool -s [speed 10 100 1000] 设置网卡设备速率, 单位Mb
ethtool -s [duplex half full] 设置网卡设备半双工 全双工
ethtool -s [autoneg on off] 设置网卡设备是否自协商

(4) tcpdump 监听网络

tcpdump的语法, 是从pcap一脉相承下来的谓词语法过滤表达式, 再加了一些自己的命令行参数.

谓词语法, 简单来说就是"组合起来的一些简单条件", 具体的条件包括了:

  • 类型(type)条件: host, port;
  • 方向(dir)条件: src, dst;
  • 协议(proto)条件: tcp, udp, ip, ip6等.

这些条件通过and, or和not就能组合起来, 形成一段过滤表达式.

tcpdump 自己的命令行参数常用的有:

  • -i, 指定网卡设备.
  • -A, 以ascii码显示包内容.
  • -x, -X, -xx, -XX, 以16进制显示包.

tcpdump是一个异常牛逼的工具, 结合具体的场景来分析问题, 是不可多得的利器.

(5) sar 监控网络

sar 的 -n 选项可以监控指定设备号的统计信息, 具体统计的参数含义可以在man page中看到.

  • sar -n DEV, 网卡设备统计信息
  • sar -n EDEV, 网卡设备的错误统计信息
  • sar -n NFS, 活动的客户端统计信息
  • sar -n NFSD, NFS服务器的统计信息
  • sar -n SOCK, 套接子的统计信息
  • sar -n ALL, 所有的统计信息

进程状态监控

(1) ps 查看进程状态, 这个就不多说了.

(2) top 观查进程运行状态, 在'S'这一列是进程的状态:

标记 含义
'D' 不可中断或者休眠, 通常是IO操作
'S' 休眠
'R' 运行
'T' 挂起, 比如ctrl+z后的进程
'Z' 僵尸进程, 例如执行完没有销毁被init接管的进程

(3) 监控进程是否存在:

  • crontab加任务脚本, 不过只能精确到分钟级别.
  • watch脚本, 可以实现秒级别的监控.
      nohup watch -n 1 'date >> /tmp/date.tmp' >/dev/null &
    
  • shell脚本直接写个死循环, 这个方法最暴力.
      #/bin/sh
      while [ 1 -eq 1 ]; do
          date >> /tmp/date.tmp
          sleep 1
      done;
    

其他

(1) strace查看系统调用

  • 在linux下, 可以通过 strace -i 来显示系统调用的地址, 然后 gdb attach 到进程, 在这个地址上加上断点, 就能查看堆栈.
  • 对应的在macos下, dtruss -s能直接打印出堆栈信息.
  • strace -cp pid可以统计一段时间的系统调用, 例如epoll_wait可以直接根据fd, 在proc/pid/fd下找到对应的socket信息, 有助于debug.

(2) valgrind工具

  • valgrind --tool=memcheck --leak-check=full 做内存检查, 检查的内容包括了访问越界, 内存泄漏等等.
  • valgrind --tool=callgrind --separate-threads=yes 做性能分析, 运行之后会生成callgrind.out.*日志文件, 可以通过callgrind_annotate工具查看, 甚至还可以在windows下用kcachegrind.exe查看图形分析结果.