标签:linux
pstree,ps,pgrep,pkill,pidof
top,htop
glance,pmap,
vmstat,dstat
kill
job,bg,fg,nohup
sar,tsar,iosar,iftop
注释:
[string] 后台的内核线程
1、线程内共享进程内存,共享打开文件描述符(文件内容)
2、线程是进程的子单位
3、调度、跟踪困难
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
USER: 进程用户
PID: 进程PID
%CPU: 运行占据CPU时间百分比
VSZ:虚拟内存集:可交换出的数据
RSS: 常驻内存集:不可交换出的数据
TTY: 通过哪个终端启动
STAT:进程状态
R(Running),S(Interrupt Sleeping),D(uninterrupt Sleeping),T(Stopped),z(zombie)
+,l + 前台,l后台
N,< N:低优先级
s 领导进程,
START: 进程启动时间
TIME: 进程运行过程占据CPU累积时长
COMMAND: 由什么命令启动的相关进程
PR NI VIRT RES SHR S
PR 优先级
NI Nice值
VIRT 相当于VRT
RES 相当于RSS
SHR shared
S STATE
PPID PRI PSR RTPRIO
ppid: 父进程id,0代表 天造地设
PRI: priority
PSR: 运行在哪个cpu上
rtprio: realtime priority 实时优先级
C cpu编号
top - 17:45:26 up 3:12, 1 user, load average: 0.00, 0.01, 0.05
%Cpu(s): 0.4 us, 0.2 sy, 0.0 ni, 99.2 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
top - 当前系统时间 up 运行时长, 用户数, 平均负载:过去1分钟,5分钟,15分钟
平均负载:CPU队列中等待运行的进程数
%Cpu(s): 0.4 us, 0.2 sy, 0.0 ni, 99.2 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
所有CPU: user space, system space, nice , idle , wait , hardware interrupt, software interrupt, stole
us: 用户空间占据cpu时间百分比
wa: 等待IO完成的时间。时间长建议换硬盘
st:被虚拟化技术偷走的时间
1、pstree显示进程树
CentOS 7
[root@izpo45bh60h6bsz ~]# pstree systemd─┬─AliYunDun───13*[{AliYunDun}]
CentOS 6
init(upstart)
CentOS 5
init
2、ps
System V 风格
ps option
a 与终端相关的进程
x 与终端无关的进程
u 与用户相关的进程
Z 安全标签
o 自定义显示格式
常用组合:
# ps aux
# ps axZ
# ps axo ppid,psr,ni,pri,rtprio,cmd
BSD风格
ps option
-e 相当于 ax
-f/-F 显示详细信息
-H hierarchy 层级结构显示
使用示例
System V
[root@izpo45bh60h6bsz ~]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND [root@izpo45bh60h6bsz ~]# ps axZ LABEL PID TTY STAT TIME COMMAND [root@izpo45bh60h6bsz ~]# ps -ef UID PID PPID C STIME TTY TIME CMD [root@izpo45bh60h6bsz ~]# ps -eF UID PID PPID C SZ RSS PSR STIME TTY TIME CMD [root@izpo45bh60h6bsz ~]# ps -eFH | head -n 1 UID PID PPID C SZ RSS PSR STIME TTY TIME CMD [root@izpo45bh60h6bsz ~]# ps -exo pid,ppid,ni,psr,pri,rtprio,time,cmd PID PPID NI PSR PRI RTPRIO TIME CMD
3、pgrep,pkill
pgrep [option] pattern
pkill [option] pattern
-u euid 有效用户(suid的属主)
-U uid 真实用户
-t terminal 与指定终端相关的进程
-a 完整格式
-l 显示进程名
-P PPID 显示PPID的子进程列表
[root@izpo45bh60h6bsz ~]# pgrep sshd 4472 10829 [root@izpo45bh60h6bsz ~]# pgrep sshd -l 4472 sshd 10829 sshd [root@izpo45bh60h6bsz ~]# pgrep sshd -a 4472 /usr/sbin/sshd -D 10829 sshd: root@pts/0 [root@izpo45bh60h6bsz ~]# pgrep -P 4472 10829 [root@izpo45bh60h6bsz ~]# pgrep -t pts/0 10831 [root@izpo45bh60h6bsz ~]# pgrep -t pts/0 -l 10831 bash [root@izpo45bh60h6bsz ~]# pgrep -t pts/0 -a 10831 -bash
4、top命令
top option
-d 刷新时间间隔
-b 批次显示
-n # 显示多少批次 与-b连胜
[root@izpo45bh60h6bsz ~]# top -d 0.0000000000000000000000000000000001 [root@izpo45bh60h6bsz ~]# top -d 0.0000000000000000000000000000000001 -b [root@izpo45bh60h6bsz ~]# top -d 0.0000000000000000000000000000000001 -b -n 10
排序
P %CPU 占据CPU百分比(过去几秒占据CPU百分比:几秒由刷新定义)
M %MEM
T TIME
显示
uptime: l
tasks及cpu: t
每个cpu: 1
Mem/Swap: m
修改
杀死: k
退出: q
修改刷新时间间隔: s
6、htop 交互式进程查看命令
Fedora-EPEL
获取帮助
F1
选定进程
s syscall,显示进程相关的信息
t tree ,层级结构显示
l 显示进程打开的文件及共享库
a 设置进程和cpu亲源性,进程只能运行在某个cpu上,增加缓存命中率
F6 > 以指定字段排序
[root@izpo45bh60h6bsz ~]# dnf install htop
7、vmstat命令 虚拟内存工具virtual memory state
vmstat [delay[count]]
delay 延迟几秒刷新一次
count 刷新几次
-p partiton
内存信息查看
vmstat -s
/proc/memoinfo
vmstat注释
[root@izpo45bh60h6bsz ~]# vmstat procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 3 0 0 208496 37940 465952 0 0 21 8 107 256 0 0 99 0 0
procs 进程
r running
b block
memory 内存
swpd 交换内存使用的总量
free 空闲物理内存总量
buff 内存中buff大小
cache 内存中cache大小
swap 交换分区
si 从物理内存加载至swap的速率
so 从swap加载至物理内存的速率
io
bi input 从磁盘加载至内存的速率(kb/s)
bo output 从内存加载至磁盘的速率
system 系统
in/int interrupt 中断,每秒多少个中断
cs context switch 进程上下文切换次数(保存现场和恢复现场的切换次数)
cpu
us user space
sy system space/kernel space
id idle
wa wait 等待IO完成的时间比率
st stole 被虚拟化技术偷走的比率
8、pmap报告内存映射表
pmap [-x|-p|-d|-q] pid
-x extend显示扩展格式
-p 显示映射的完整路径
-d 显示设备信息
-q 不显示首尾信息
查看内存映射表
/proc/PID/maps
pmap pid
线性内存地址和物理地址映射关系
进程只知道线性地址
1、进程将打开的文件存储在进程内存地址空间中,分段存储
2、进程划分的空间为4K的整数倍(内存页的大小为4K)
3、heap堆、stack栈、anon: anonymous 匿名页,进程自己存储数据的位置,不能交换出去
Address Kbytes RSS Dirty Mode Mapping 00007ff5a8000000 164 12 12 rw--- [ anon ] 00007ff5a8029000 65372 0 0 ----- [ anon ] 00007ff5ac94d000 4 0 0 ----- [ anon ] 00007ff5ac94e000 8192 8 8 rw--- [ anon ] 00007ff5ad14e000 4 0 0 ----- [ anon ] 00007ff5ad14f000 8192 8 8 rw--- [ anon ] 00007ff5ad94f000 16 8 0 r-x-- libuuid.so.1.3.0 00007ff5ad953000 2044 0 0 ----- libuuid.so.1.3.0 00007ff5adb52000 4 4 4 r---- libuuid.so.1.3.0 00007ff5adb53000 4 4 4 rw--- libuuid.so.1.3.0 00007ff5adb54000 228 40 0 r-x-- libblkid.so.1.1.0 00007ff5adb8d000 2048 0 0 ----- libblkid.so.1.1.0 00007ff5add8d000 12 12 12 r---- libblkid.so.1.1.0 00007ff5add90000 4 4 4 rw--- libblkid.so.1.1.0
使用示例
1、默认 [root@izpo45bh60h6bsz ~]# pmap 1 | head 1: /usr/lib/systemd/systemd --switched-root --system --deserialize 21 00007ff5a8000000 164K rw--- [ anon ] 00007ff5a8029000 65372K ----- [ anon ] 00007ff5ac94d000 4K ----- [ anon ] 00007ff5ac94e000 8192K rw--- [ anon ] 00007ff5ad14e000 4K ----- [ anon ] 00007ff5ad14f000 8192K rw--- [ anon ] 00007ff5ad94f000 16K r-x-- libuuid.so.1.3.0 00007ff5ad953000 2044K ----- libuuid.so.1.3.0 00007ff5adb52000 4K r---- libuuid.so.1.3.0 2、显示详细 [root@izpo45bh60h6bsz ~]# pmap -x 1 | head 1: /usr/lib/systemd/systemd --switched-root --system --deserialize 21 Address Kbytes RSS Dirty Mode Mapping 00007ff5a8000000 164 12 12 rw--- [ anon ] 00007ff5a8029000 65372 0 0 ----- [ anon ] 00007ff5ac94d000 4 0 0 ----- [ anon ] 00007ff5ac94e000 8192 8 8 rw--- [ anon ] 00007ff5ad14e000 4 0 0 ----- [ anon ] 00007ff5ad14f000 8192 8 8 rw--- [ anon ] 00007ff5ad94f000 16 8 0 r-x-- libuuid.so.1.3.0 00007ff5ad953000 2044 0 0 ----- libuuid.so.1.3.0 3、静默 [root@izpo45bh60h6bsz ~]# pmap -xq 1 | head 1: /usr/lib/systemd/systemd --switched-root --system --deserialize 21 00007ff5a8000000 164 12 12 rw--- [ anon ] 00007ff5a8029000 65372 0 0 ----- [ anon ] 00007ff5ac94d000 4 0 0 ----- [ anon ] 00007ff5ac94e000 8192 8 8 rw--- [ anon ] 00007ff5ad14e000 4 0 0 ----- [ anon ] 00007ff5ad14f000 8192 8 8 rw--- [ anon ] 00007ff5ad94f000 16 8 0 r-x-- libuuid.so.1.3.0 00007ff5ad953000 2044 0 0 ----- libuuid.so.1.3.0 00007ff5adb52000 4 4 4 r---- libuuid.so.1.3.0 4、显示完整map [root@izpo45bh60h6bsz ~]# pmap -xqp 1 | head 1: /usr/lib/systemd/systemd --switched-root --system --deserialize 21 00007ff5a8000000 164 12 12 rw--- [ anon ] 00007ff5a8029000 65372 0 0 ----- [ anon ] 00007ff5ac94d000 4 0 0 ----- [ anon ] 00007ff5ac94e000 8192 8 8 rw--- [ anon ] 00007ff5ad14e000 4 0 0 ----- [ anon ] 00007ff5ad14f000 8192 8 8 rw--- [ anon ] 00007ff5ad94f000 16 8 0 r-x-- /usr/lib64/libuuid.so.1.3.0 00007ff5ad953000 2044 0 0 ----- /usr/lib64/libuuid.so.1.3.0 00007ff5adb52000 4 4 4 r---- /usr/lib64/libuuid.so.1.3.0
9、glances命令
galances [options...]
-s -B IPADDR 服务端模式
-c IPADDR 客户端模式
-b 以字节显示网络速率
-m/-n/-d 控制mount,network,disk模块的显示
-t # 延迟间隔
-1 每个cpu信息单独显示
-f /path/to/somefile galance显示的结果保存至文件中
-o {HTML|CSV} 文件的格式
galance内建命令
a Sort processes automatically l Show/hide logs c Sort processes by CPU% b Bytes or bits for network I/O m Sort processes by MEM% w Delete warning logs p Sort processes by name x Delete warning and critical logs i Sort processes by I/O rate 1 Global CPU or per-CPU stats d Show/hide disk I/O stats h Show/hide this help screen f Show/hide file system stats t View network I/O as combination n Show/hide network stats u View cumulative network I/O s Show/hide sensors stats q Quit (Esc and Ctrl-C also work) y Show/hide hddtemp stats
服务端
[root@localhost ~]# glances -s -B 192.168.1.103 -p 8888 -P 1234 Glances server is running on 192.168.1.103:8888
客户端
[root@localhost ~]# glances -c 192.168.1.103 -p 8888 Error: Connection to server failed. Bad password. [root@localhost ~]# glances -c 192.168.1.103 -p 8888 -P 1234 [root@localhost ~]# Connected to 192.168.1.103 | Press ‘h‘ for help
10、dstat命令
vmstat替换工具
dstat options
-c/-C #,#,..,total
-d/-D total,/dev/sda,/dev/sdb,...
-g page显示内存数据交换的速率
-i 显示中断速率
-l --load 显示平均负载
-m,--mem 显示内存信息
-n,--net 显示网络信息
-p,--proc 进程状态
-r,--io 显示io相关的统计数据
-s,--swap 显示swap 相关的统计数据
-t,--time 时间输出
--aio 异步io
--fs,--filesystem 显示文件系统
--ipc (message queue(signal),semephores,shared memory)
--lock 文件锁
--socket (total,udp,tcp,raw,ip-fragment分片)
--tcp (listen,established,syn,time_wait,close)
--udp (listen,active)
--unix (datagram, stream, listen, active)
PLUGIN:
-a,相当于 -cdngy
--battery 电池
--battery-remain 电池剩余的时间(ACPI支持)
--disk-tps 磁盘每秒钟的事务量(need ACPI)
--mysql5-conn 对mysql运行命令的统计
--top-cpu 显示最消耗CPU的进程
--top-int 显示中断数据最大的进程
--top-io 最消耗IO的进程
--top-mem 最消耗内存的进程
--top-latency 显示延迟最大的进程
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai hiq siq| read writ| recv send| in out | int csw total-cpu-usage cpu使用状态 dsk/total 磁盘读写速率 net/total 网络的收发速率 paging 页面的换进换出(内存页面,交换内存。 si,so) system 中断和上下文切换 (int: interrupt, csw: context swtich。 in,cs )
使用示例
1、cpu相关的信息
[root@localhost ~]# dstat -c ----total-cpu-usage---- usr sys idl wai hiq siq [root@localhost ~]# dstat -C total,0 Terminal width too small, trimming output. ----total-cpu-usage------------cpu0-usage------ -dsk/total- -net/total- ---paging--> usr sys idl wai hiq siq:usr sys idl wai hiq siq| read writ| recv send| in out >
2、硬盘相关
[root@localhost ~]# dstat -d -dsk/total- read writ [root@localhost ~]# dstat -D total,/dev/sda ----total-cpu-usage---- -dsk/total----dsk/sda-- -net/total- ---paging-- ---system-- usr sys idl wai hiq siq| read writ: read writ| recv send| in out | int csw
3、页面
[root@localhost ~]# dstat -g ---paging--
4、显示中断
[root@localhost ~]# dstat -i ----interrupts---
5、平均负载
[root@localhost ~]# dstat -l ---load-avg--- 1m 5m 15m
6、内存
[root@localhost ~]# dstat -m ------memory-usage----- used buff cach free
7、网络
[root@localhost ~]# dstat -n -net/total- recv send
8、进程
---procs--- run blk new run 运行进程的数据 new 创建新进程的数据
9、io
[root@localhost ~]# dstat -r --io/total- read writ
10、swap
[root@localhost ~]# dstat -s ----swap--- used free
11、时间
[root@localhost ~]# dstat -t ----system---- date/time
12、异步IO
[root@localhost ~]# dstat --aio async #aio
13、文件系统
[root@localhost ~]# dstat --fs --filesystem- files inodes
14、进程通信
[root@localhost ~]# dstat --ipc --sysv-ipc- msg sem shm
15、文件锁
[root@localhost ~]# dstat --lock ---file-locks-- pos lck rea wri
16、套接字
[root@localhost ~]# dstat --socket ------sockets------ tot tcp udp raw frg
17、tcp连接
[root@localhost ~]# dstat --tcp ----tcp-sockets---- lis act syn tim clo
18、udp连接
[root@localhost ~]# dstat --udp --udp-- lis act
19、unix连接
[root@localhost ~]# dstat --unix --unix-sockets- dgm str lis act
20、-a
[root@localhost ~]# dstat -a 1 1 ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai hiq siq| read writ| recv send| in out | int csw
[root@localhost ~]# dstat --disk-util sda- util
22、文件系统空闲
[root@localhost ~]# dstat --freespace -----/----------/shm-------/boot-------/home--------/usr--------/var--- used free: used free: used free: used free: used free: used free 3101M 44.9G: 0 121M:57.4M 419M: 260M 4534M:2091M 12.3G: 714M 9001M
23、插件注释
[root@localhost ~]# dstat --helloworld plugin-title counter Hello world! Hello world! Hello world! Hello world!
24、最消耗cpu进程
[root@izpo45bh60h6bsz ~]# dstat --top-cpu -most-expensive- cpu process AliYunDun 0.2 aliyun-servic1.0
25、中断次数最多
[root@izpo45bh60h6bsz ~]# dstat --top-in ---most-frequent---- interrupt ata_piix 1 virtio0-input.0 1
26、io次数
----most-expensive---- i/o process systemd 29k 10k sshd: root@ 146B 196B
27、内存消耗最大
[root@izpo45bh60h6bsz ~]# dstat --top-mem --most-expensive- memory process mysqld 123M
28、延迟最大的进程
[root@izpo45bh60h6bsz ~]# dstat --top-latency --highest-total-- latency process rcu_sched 882
11、kill命令
查看信号:
kill -l
man 7 signal
SIGHUP: 不关闭进程重读配置文件。服务程序
SIGINT: 终止信号(interrupt) 相当于 Ctrl + c
SIGKILL: 杀死正在运行的进程 ,直接终止,
SIGTERM: 终止指定的进程(优雅) ,处理的数据存回磁盘中,再终止
SIGCONT 让停止态的信号,continue
SIGSTOP 让运行中的进程,stop
SIGNAL:
1、全名 SIGHUP
2、简名 HUP
3、数字标识 1
发信号
kill -SIGNAL pid
killall -SIGNAL 进程名
12、作业
jobs一个任务可能包含单个进程也可能包含多个进程
前台作业:与终端相关,占据命令提示符
后台作业:与终端相关,不占据命令提示符
送到后台剥离与终端关系: # nohup COMMMAND &
作业送到后台:
运行中的程序:Ctrl + z
尚未启动的程序:COMMAND &
查看作业: # jobs
+ 没有作业号,默认管理的作业
- 下一个
[#]作业号
作业管理
送到前台: fg [[%]JOB_NUM]
送到后台: bg [[%]JOB_NUM]
终止作业: kill -SIGNAL %JOB)NUM
13、nice值
动态优先级:进程消耗过多的cpu资源时,内核自动调整,
静态优先级: 100-139 (数据越小,优先级越高)
实时优先级: 0-99 (数字越大,优先级越高)
进程默认启动优先级120,nice值为 0
nice [-n # ] command
-n # 启动后以#值作为Nice值运行,不给-n #,默认nice=10
renice -n # command
-n # 重新设置优先级
查看nice值: # ps axo pid,command,ni
14、sar,tsar,iosar,iftop
sar
-u cpu
-d disk
-B 交换页数据
-b 报告I\O传输速率
详解:-B
pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s
pgpgin/s 物理内存到磁盘swap
fault 缺页异常发生的速率
majflt/s major faults
pgfree/s page free place on
pgscank/s kswapd daemon scan pages
pgscnd/s page scan directly
pgsteal/s page reclaimed from cache(pagecache and swap-cache)
详解: -u 报告cpu使用率
CPU %user %nice %system %iowait %steal %idle
详解: -b
tps rtps wtps bread/s bwrtn/s
t 总传输
rtps 读传输
wtps 写传输
bread/s 从块读
bwrtn/s 写到块
tsar
iostat
Report Central Processing Unit (CPU) statistics and input/output statistics
for devices and partitions.
Central Processing Unit (CPU) 中央处理单元cpu
statistics 统计数据
for prep.为,为了;倾向于;关于;当作
为设备和分区报告CPU,I/O统计数据
iostat [-u | -d | -h | -k | -m]
-u cpu
-d disk
-h human readable
-k KB
-m MB
-N LVM2统计数据
CPU Utilization Report(Utilization 利用率)
%user 运行用户级别/用户空间的进程CPU利用率百分比
%nice nice priority占据CPU利用百分比
%system system level(kernel)
%iowait 系统有突出IO时,CPU空闲百分比。进程等待IO的百分比
%steal 被虚拟化技术偷走的时间
%idle CPU空闲和系统无IO所占时间百分比
Device Utilization Report
Device 显示dev目录下的设备或Partition名
tps 显示每秒IO请求传输至设备的数量,IO请求可以是单个,或多个IO请求组合成单个,大小不确定
kB_read/s 每秒从块或扇区读取数据量
kB_wrtn/s 每秒写
kB_read 总读
kB_wrtn 总写
rrqm/s queued to device read request merged 合并读请求队列的速率
wrqm/s 合并写请求速率
iftop
1)获取命令的信息 命令行模式显示网络接口带宽统计数据“为什么我的ADSL连接如此慢”
[root@izpo45bh60h6bsz ~]# dnf info iftop Using metadata from Wed Aug 23 00:36:04 2017 可安装的软件包 名称 : iftop 架构 : x86_64 时期 : 0 版本 : 1.0 发布 : 0.14.pre4.el7 大小 : 52 k 仓库 : epel 概要 : Command line tool that displays bandwidth usage on an interface URL : http://www.ex-parrot.com/~pdw/iftop/ 协议 : GPLv2+ 描述 : iftop does for network usage what top(1) does for CPU usage. It listens to : network traffic on a named interface and displays a table of current bandwidth : usage by pairs of hosts. Handy for answering the question "why is our ADSL link : so slow?".
2)安装包
[root@izpo45bh60h6bsz ~]# dnf install iftop
3)获取帮助
# man iftop 显示主机接口之上的网络带宽使用情况
iftop -h | [-nNpblBP] [-i interface] [-f filter code] [-F net/mask] [-G net6/mask6]
默认情况会反解主机名,-n选项或运行中使用r命令关闭dns反解
默认会显示通过过滤器的所有IP包,IP包的方向是通过接口的方向
-F NETWORK 显示给定网络输入或输出的数据包
忽略广播数据包: not ether host ff:ff:ff:ff:ff:ff
过滤仅显示web数据包,排除:port http and not host webcache.example.com
用户浪费了多少带宽弄清楚网络如此慢:icmp
-h 获取帮助
-n 不从IP包中反解主机名
-N 不反解端口号
-p promise模式,流量不经过此接口也会统计
-P 打开端口显示
-b bar开关
-m #[km] 仅显示由#指定的宽带比例上限对应的数据包
-i IFACE 指监听接口
-f filter code 过滤
-F net/mask 过滤仅显示什么ip的数据包,包的方向由网络边界决定
-c config_file 给出一个临时配置文件,默认 ~/.iftoprc
内建命令
S ,D , P ,p ,n ,N
Host display: General: n - toggle DNS host resolution P - pause display s - toggle show source host h - toggle this help display d - toggle show destination host b - toggle bar graph display t - (revice,sent,two line,one line) B - cycle bar graph average T - toggle cumulative line totals Port display: j/k - scroll display N - toggle service resolution f - edit filter code S - toggle show source port l - set screen filter D - toggle show destination port L - lin/log scales p - toggle port display ! - shell command q - quit Sorting: 1/2/3 - sort by 1st/2nd/3rd column < - sort by source name > - sort by dest name o - freeze current order
显示注释
每个字段10秒平均流量显示 foo.example.com => bar.example.com 1Kb 500b 100b 流量从 foo.example.com 到 bar.example.com 1Kb 前2秒数据被接收或发送的速率 500b 前10秒 100b 前40秒 过滤后的总传输流量 最近40s高峰流量 过去2s,10s,40s部传输速率
本文出自 “Reading” 博客,请务必保留此出处http://sonlich.blog.51cto.com/12825953/1958550
+++++++进程管理工具 top/htop/glances/dstat命令
标签:linux
原文地址:http://sonlich.blog.51cto.com/12825953/1958550