Linux命令之iostat

iostat来自sysstat工具包,可以查看CPU和系统磁盘IO的统计信息。本文主要介绍iostat的主要命令参数和输出的部分解释。意在帮助不熟悉的用户入境,高级用户可以直接查看man page。

用法

iostat [ options ] [ <interval> [ <count> ] ]
  • opions 选项
  • interval 每隔多少秒统计一次
  • count 连续统计多少次

注意:如果没有提供intervalcount选项,则系统只统计一次。统计结果是上次统计(如果没有统计过,则是系统启动时间)到本次统计的数据。

输出

执行iostat的输出如下:

Linux 3.16.0-4-586 (oogway)     06/02/2016     _i686_    (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.19    0.00    0.39    0.18    0.00   97.24

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               1.74        24.40         3.32     222286      30252

第一行:系统信息

系统信息的输出和uname -a的输出类似。

  • Linux 内核名称
  • 3.16.0-4-586 内核发行版本
  • oogway 主机名
  • 06/02/2016 当天日期
  • _i686_ 机器硬件名
  • 1 CPU CPU个数

第二行:CPU利用率

CPU利用率的信息和top里的CPUT信息类似。

  • %user 没有修改nice的任务的用户态时间占比
  • %nice 修改过nice的任务的用户态时间占比
  • %system 系统态时间占比
  • %iowait 等待IO的时间占比
  • %steal 虚拟cpu等待supervisor的时间占比
  • %idle 空闲时间占比

第四行:设备的读写信息

  • tps 每秒读写请求次数
  • kB_read/s 读取速度
  • kB_wrtn/s 写入速度
  • kB_read 读取量
  • kB_wrtn 写入量

常用参数

统计次数及频率

如果我们希望每一秒统计一次数据,连续统计10次,可以iostat 1 10

查看扩展统计信息

可以使用-x参数查看扩展的统计信息。

iostat -x输出如下:

Linux 3.16.0-4-586 (oogway)     06/02/2016     _i686_    (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.65    0.00    0.39    0.18    0.00   96.79

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.56     0.37    1.21    0.30    20.00     3.66    31.28     0.01    3.79    2.85    7.63   1.74   0.26

统计信息多了的这几项分别是:

  • rrqm/s 每秒读请求合并数
  • wrqm/s 每秒写请求合并数
  • r/s 每秒完成的读请求数
  • w/s 每秒完成的写请求数
  • rkB/s 读取速率,同kB_read/s
  • wkB/s 写入速率,同kB_write/s
  • avgrq-sz 请求的平均扇区数
  • avgqu-sz 请求的平均队列长度
  • await IO请求的平均耗时
  • r_await 读请求的平均耗时(ms)
  • w_await 写请求的平均耗时(ms)
  • svctm IO请求的平均服务耗时(该指标在未来将被移除)
  • %util 单位时间内IO请求占比。当达到100%时,说明系统IO已饱和(RAID和SSD除外)。公式(r/s+w/s) * (svctm/1000)。如果做了RAID或使用了SSD,这个值就不可靠了。

Linux命令之top

top命令可以动态实时地显示系统的运行状态,它的输出包括系统信息、进程信息和线程信息等。这篇文章主要讲解top输出的各项信息,以帮助用户更好的理解和使用top。

top的输出信息

top命令在我本地的输出如下:

top - 10:06:56 up  2:38,  1 user,  load average: 0.00, 0.03, 0.05
Tasks:  74 total,   1 running,  73 sleeping,   0 stopped,   0 zombie
%Cpu(s):  5.0 us,  0.7 sy,  0.0 ni, 94.0 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:    772276 total,   281820 used,   490456 free,    30140 buffers
KiB Swap:   976892 total,        0 used,   976892 free.   126516 cached Mem

 PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
1359 root      20   0   69700  30232  13524 S  4.6  3.9   4:17.45 emacs
1780 root      20   0    5080   2796   2448 R  1.0  0.4   0:15.30 top
 456 redis     20   0   29660   3084   2472 S  0.7  0.4   0:34.57 redis-server
   1 root      20   0    5576   4208   2964 S  0.0  0.5   0:02.46 systemd

第一行:系统运行信息

该输出和uptime的输出类似。

  • 10:06:56 系统启动时间
  • 2:38 系统运行时间
  • 1 user 当前系统用户数,这里只有pysnow530一个用户
  • load average: 0.00, 0.03, 0.05 三个数据分别是1分钟、5分钟、15分钟内的负载平均值

注意:这里的负载是指某段时间内待运行任务队列长度的平均值,也就是当前等待运行的任务数。如果当前任务队列数为8,说明有8个任务已处于就绪状态,就等着CPU的时间片了。该值越大,说明系统负载越高。假设系统有一个单核CPU,此值持续大于0.7则说明系统存在问题;为1时即为满负载工作,系统已不能正常处理多余的任务;若CPU大于1,好吧,它已经忙不过来了。此时可查看系统进程,有可能是某进程出问题了。以上是一个单核CPU的情况,如果系统有两个双核CPU,则满负载时值为2x2=4,其它情况可类推。

第二行:各状态任务个数

  • total 全部任务
  • running 运行中任务
  • sleeping 睡眠中任务
  • stopped 已停止任务
  • zombie 僵死任务

第三行:cpu执行各状态时间占比

  • us 没有修改nice的进程用户态耗时占比
  • sy 执行内核态耗时占比
  • ni 修改过nice的进程用户态占比
  • id 空闲时间占比
  • wa 等待IO操作耗时占比,我们的CPU已将任务队列的任务运行完了,就等着IO了
  • hi 提供硬件中断耗时占比
  • si 提供软件中断耗时占比
  • st hypervisor从当前虚拟机偷走的时间占比

注意:如果wa过高(超过30%),一方面可能是我们的CPU太强悍了,另一方面也有可能是磁盘IO存在瓶颈。此时可通过iostat -x确认具体情况。

第四行和第五行:内存和交换区的使用信息

该输出和free命令的输出类似。

  • total 总容量大小
  • used 已使用容量大小
  • free 剩余容量大小
  • buffers 缓冲区
  • cached Mem 缓存内存,当读写文件时,系统为了提高读写性能,会将文件缓存到缓存内存。

剩余行:每个进程的信息

  • PID 进程id
  • USER 所属用户
  • PR 优先级
  • NI nice值
  • VIRT 虚拟内存
  • RES 资源内存
  • SHR 共享内存
  • S 进程状态,D表示不可中断的睡眠,R表示正在运行,S表示正在睡眠,T表示被跟踪或已停止,Z表示僵死进程,跟各状态任务个数对应
  • %CPU CPU使用率
  • %MEM 内存使用率
  • TIME+ 运行时间
  • COMMAND 进程对应命令

Python中的装饰器

本文主要讲解python中decorator的历史,然后说明decorator在python中的实现,以帮助初识decorator的pythoner能够灵活运用decorator。

装饰器模式

装饰器模式来自GoF的23种设计模式。

在设计模式中,装饰器模式的意图描述如下:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

即将附加的职责动态添加到一个对象。在扩展功能时,它比子类继承的方式要来得灵活。它是面向切面编程的一种手段。

python中的装饰器

提出

在python中,decorator最早是在PEP 318 – Decorators for Functions and Methods被提出的。

具体实现

decorator在python中形如@decorator,如:

@log
def foo():
    ...

我们将通过观察字节码,看一看添加decorator在字节码层带来了哪些变化。

首先来看函数定义产生的字节码:

def foo():
    pass

0 LOAD_CONST               0 (<code object foo at 0xb72508d8, file "<stdin>", line 1>)
3 MAKE_FUNCTION            0
6 STORE_NAME               0 (foo)

foo函数的定义对应三条字节码。

LOAD_CONST指令将pass对应的代码对象压入堆栈。

MAKE_FUNCTION将代码对象弹出堆栈,并创建一个PyFunctionObject对象,然后将函数压入堆栈。

STORE_NAME将函数弹出栈,并将它绑定到foo变量。

此时,foo变量即是一个函数。

然后我们看一下加了装饰器的函数定义对应的字节码:

@log
def foo():
    pass

 0 LOAD_NAME                0 (log) <---------- 1
 3 LOAD_CONST               0 (<code object foo at 0xb720e8d8, file "<stdin>", line 1>)
 6 MAKE_FUNCTION            0
 9 CALL_FUNCTION            1       < --------- 2
12 STORE_NAME               1 (foo)

foo函数添加一个装饰器时,对应的字节码多个两条。上面使用1、2标出。

LOAD_NAME命令是新增命令,将log函数(装饰器函数)压入堆栈。

LOAD_CONST命令将foo下的代码对象压入栈项。

MAKE_FUNCTION命令将代码对象弹出栈,并创建一个PyFunctionObject对象,并压入堆栈。

CALL_FUNCTION命令是新增命令,调用最开始压入堆栈的装饰器函数,然后将函数的返回值压入堆栈。

STORE_NAME将栈项装饰器函数的返回值绑定到foo变量。

也就是说,装饰器是一个函数,它将被装饰的函数作为输入,并将输出绑定到被装饰的函数名上。而装饰器的使用本质上就是一个语法糖。

煮个粟子

知道了它的内部实现,我们就可以动手了。

例如,实现一个打印函数耗时的装饰器:

import time

def log(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        waste_time = end - start
        print 'waste time:', waste_time
    return wrapper

@log
def hello():
    print 'hello, world'

hello()
hello, world
waste time: 4.29153442383e-05