-
Linux 系统监控实战
linux系统监控常用命令(一)
系统监控的重要性:
一旦我们的系统上线并开始运行,我们自然希望它能保持稳定可靠,避免宕机、无响应或运行缓慢的情况。但这不是简单开启电源后就能实现的。因此,我们需要不断监视系统的运行状况,及时发现并解决问题。对于系统和网络管理员来说,每天监控和调试 Linux 系统的性能问题是一项繁重的任务。确保系统正常启动并持续稳定运行绝非易事。以下是一些 Linux 系统监控命令的简要介绍。
Linux 下的 top 命令是一个性能监控程序,许多系统管理员常常用它来监控 Linux 性能,在许多 Linux 或者类 Unix 操作系统里都有这个命令。top 命令用于按一定的顺序显示所有正在运行而且处于活动状态的实时进程,而且会定期更新显示结果。这条命令显示了 CPU 的使用率、内存使用率、交换内存使用大小、高速缓存使用大小、缓冲区使用大小,进程 PID、所使用命令以及其他。它还可以显示正在运行进程的内存和 CPU 占用多的情况。
top
在图中依次可以看到进程 PID,进程用户,CPU 使用率,内存使用率、交换内存使用大小等等信息。top 命令提供了实时的对系统处理器的状态监视,它将显示系统中 CPU 最“敏感”的任务列表。
通过man top
可以查看到详细的 top 命令使用方式。
Linux 的 vmstat 命令用于显示虚拟内存、内核线程、磁盘、系统进程、I/O 块、中断、CPU 活动等的统计信息。
一般 vmstat 工具的使用是通过两个数字参数来完成的,第一个参数是采样的时间间隔数,单位是秒,第二个参数是采样的次数。
vmstat 2 1
vmstat 2 2
测试参数讲解:
参数 | 描述 |
---|---|
r | 表示运行队列,如果运行队列过大,表示你的 CPU 很繁忙,一般会造成 CPU 使用率很高 |
b | 表示阻塞的进程数 |
swpd | 虚拟内存已使用的大小,如果大于 0,表示机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器 |
free | 空闲的物理内存的大小 |
buff | 系统占用的缓存大小 |
cache | 直接用来记忆我们打开的文件,给文件做缓冲 |
si | 每秒从磁盘读入虚拟内存的大小,如果这个值大于 0,表示物理内存不够用或者内存泄露了 |
cs | 每秒上下文切换数 |
us | 用户 CPU 时间 |
so | 每秒虚拟内存写入磁盘的大小,如果这个值大于 0,同上 |
sy | 系统 CPU 时间,如果太高,表示系统调用时间长,例如是 IO 操作频繁 |
id | 空闲 CPU 时间,一般来说,id + us + sy = 100 |
wa | IO 等待时间百分比 wa 的值高时,说明 IO 等待比较严重,这可能由于磁盘大量作随机访问造成,也有可能磁盘出现瓶颈(块操作) |
st | 来自于一个虚拟机偷取的 CPU 时间的百分比 |
它常用于以列表的形式显示所有打开的文件和进程。打开的文件包括磁盘文件、网络套接字、管道、设备和进程。使用这条命令的主要情形之一就是在无法挂载磁盘和显示正在使用或者打开某个文件的错误信息的时候,使用这条命令,你可以很容易地看到正在使用哪个文件。
实验环境中没有安装这个命令,需要手动安装 sudo apt-get install lsof
然后在终端输入:
lsof
tcpdump 是最广泛使用的网络包分析器或者包监控程序之一,它用于捕捉或者过滤网络上指定接口上接收或者传输的 TCP/IP 包。它还有一个选项用于把捕捉到的包保存到文件里,以便以后进行分析。
参数 | 描述 |
---|---|
-h | 查看命令帮助 |
-i | 网络接口 |
-c | 需要输出包数量 |
sudo apt-get update
sudo apt-get install tcpdump
tcpdump -h
sudo tcpdump -i eth0 -c 3
netstat 是一个用于监控进出网络的包和网络接口统计的命令行工具。它是一个非常有用的工具,系统管理员可以用来监控网络性能,定位并解决网络相关问题。
参数 | 描述 |
---|---|
-h | 查看帮助 |
-r | 查看 IP 路由表 |
-i | 查看网络接口 |
htop 是一个非常高级的交互式的实时 Linux 进程监控工具。它和 top 命令十分相似,但是它具有更丰富的特性,例如用户可以友好地管理进程,快捷键,垂直和水平方式显示进程等等。htop 是一个第三方工具,它不包含在 Linux 系统中,你需要使用管理工具去安装它。
sudo apt-get install htop
htop
iostat 是一个计算机系统监视工具,用于收集和显示操作系统存储的输入和输出统计数据。这个工具常常用来追踪存储设备的性能问题,其中存储设备包括本地磁盘以及诸如用 NFS 等的远端磁盘。
sudo apt-get install sysstat
iostat
avg-cpu 段:
参数 | 含义 |
---|---|
%user | 在用户级别运行所使用的 CPU 的百分比 |
%nice | 优先进程消耗的 CPU 时间,占所有 CPU 的百分比 |
%system | 在系统级别(kernel)运行所使用 CPU 的百分比 |
%iowait | CPU 等待硬件 I/O 时,所占用 CPU 百分比 |
%steal | 管理程序维护另一个虚拟处理器时,虚拟 CPU 的无意识等待时间百分比 |
%idle | CPU 空闲时间的百分比 |
Device 段:
参数 | 含义 |
---|---|
tps | 每秒钟发送到的 I/O 请求数 |
KB_read/s | 每秒读取的 block 数 |
KB_wrtn/s | 每秒写入的 block 数 |
KB_read | 启动到现在 读入的 block 总数 |
KB_wrtn | 启动到现在写入的 block 总数 |
IPTraf 是一个在 Linux 控制台运行的、开放源代码的实时网络(局域网)监控应用。它采集了大量信息,比如通过网络的 IP 流量监控,包括 TCP 标记、ICMP 详细信息、TCP/UDP 流量分离、TCP 连接包和字节数。同时还采集有关接口状态的常见信息和详细信息:TCP、UDP、IP、ICMP、非 IP,IP 校验和错误,接口活动等。
sudo apt-get install iptraf
sudo iptraf
linux系统监控常用命令(二)
Linux 系统任何时候都运行在一个指定的运行级上,并且不同的运行级的程序和服务都不同,所要完成的工作和要达到的目的都不同,系统可以在这些运行级之间进行切换,以完成不同的工作。sysv-rc-conf 是一个强大的服务管理程序,用于查看程序和服务的运行级别。
Ubuntu 的系统运行级别:
参数 | 描述 |
---|---|
0 | 系统停机状态 |
1 | 单用户或系统维护状态 |
2~5 | 多用户状态 |
6 | 重新启动 |
NetHogs 是一个开放源源代码的很小程序(与 Linux 下的 top 命令很相似),它密切监视着系统上每个进程的网络活动。同时还追踪着每个程序或者应用所使用的实时网络带宽。
# 安装 nethogs
$ sudo apt-get install nethogs
# 因为 0.8.0 的一个 bug,需要先切换到 root 再执行,使用 sudo 会报错,安装 0.8.1 以上的版本就没问题了
# 实验环境中的 0.8.0 版本
$ sudo su
$ nethogs
若还是报错没有 root 权限,可以手动编译最新版的运行,步骤如下:
#安装编译需要的工具
$ sudo apt-get update
$ sudo apt-get install build-essential libncurses5-dev libpcap-dev checkinstall
#从 nethogs 项目页面拉取源码
$ wget https://github.com/raboof/nethogs/archive/v0.8.5.tar.gz
#解压并进入文件夹
$ tar -zxvf v0.8.5.tar.gz
$ cd nethogs-0.8.5
#开始编译,接下来一直回车确定就行了
$ sudo checkinstall -D make install
#安装生成的 deb 包
$ sudo dpkg -i nethogs_0.8.5-1_amd64.deb
#然后就可以运行了
$ sudo nethogs
用 Q 退出 nethogs 的界面。
运行 nethogs 命令:
$ nethogs --help
$ sudo nethogs > nethogs.txt
iftop 是另一个在控制台运行的开放源代码系统监控应用,它显示了系统上通过网络接口的应用网络带宽使用(源主机或者目的主机)的列表,这个列表定期更新。iftop 用于监视网络的使用情况,而 top 用于监视 CPU 的使用情况。iftop 也是 top 工具系列中的一员,它用于监视所选接口,并显示两个主机间当前网络带宽的使用情况。
$ sudo apt-get install iftop
$ sudo iftop
参数 | 描述 |
---|---|
<= => | 表示流量的方向 |
TX | 发送流量 |
RX | 接收流量 |
TOTAL | 总流量 |
cum | 运行 iftop 到目前时间的总流量 |
peak | 流量峰值 |
rates | 分别表示过去 2s 10s 40s 的平均流量 |
参数 | 描述 |
---|---|
按 H 键 | 是否显示帮助 |
按 N 键 | 显示本机的 IP 或主机名 |
按 S 键 | 是否显示本机的 host 信息 |
按 D 键 | 是否显示远端目标主机的 host 信息 |
按 T 键 | 切换显示格式为 2 行/ 1 行/只显示发送流量/只显示接收流量 |
gnome-system-monitor 是 GNOME 系统监视器,能够监听 CPU,内存,进程,硬盘的信息。分为进程监控,资源监控,文件监控:
$ sudo apt-get install gnome-system-monitor
$ gnome-system-monitor
进程监控:包括进程名,用户,CPU 占用率,进程 PID,内存占用,优先级:
资源监控是对历史资源使用的统计,将其绘制成图展现,从图中可以看出 CPU 使用率的变化,存储占用率变化,带宽占用率变化。由于实验环境的原因,文件监控包括 hosts,hostname 等。
Linux系统监控工具——Nagios
Nagios 是一个监视系统运行状态和网络信息的监视系统。Nagios 能监视所指定的本地或远程主机以及服务,同时提供异常通知功能等。
Nagios 可运行在 Linux/Unix 平台之上,同时提供一个可选的基于浏览器的 WEB 界面以方便系统管理人员查看网络状态,各种系统问题,以及日志等等。
Nagios 可以监控的功能有:
1、监控网络服务(SMTP、POP3、HTTP、NNTP、PING 等);
2、监控主机资源(处理器负荷、磁盘利用率等);
3、简单地插件设计使得用户可以方便地扩展自己服务的检测方法;
4、并行服务检查机制;
5、具备定义网络分层结构的能力,用"parent"主机定义来表达网络主机间的关系,这种关系可被用来发现和明晰主机宕机或不可达状态;
6、当服务或主机问题产生与解决时将告警发送给联系人(通过 email、短信、用户定义方式);
7、可以定义一些处理程序,使之能够在服务或者主机发生故障时起到预防作用;
8、自动的日志滚动功能;
9、可以支持并实现对主机的冗余监控;
10、可选的 WEB 界面用于查看当前的网络状态、通知和故障历史、日志文件等。
Linux 监控的 Python 脚本
目前 Linux 下有一些使用 Python 语言编写的 Linux 系统监控工具,比如 inotify-sync(文件系统安全监控软件)、glances(资源监控工具)。在实际工作中,Linux 系统管理员可以根据自己使用的服务器的具体情况编写一下简单实用的脚本实现对 Linux 服务器的监控。本文介绍一下使用 Python 脚本实现对 Linux 服务器 CPU、内存和网络的监控脚本的编写。
Linux 系统为管理员提供了非常好的方法,使其可以在系统运行时更改内核,而不需要重新引导内核系统,这是通过/proc
虚拟文件系统实现的。/proc
文件虚拟系统是一种内核和内核模块用来向进程(process)发送信息的机制,这个伪文件系统允许与内核内部数据结构交互,获取有关进程的有用信息,在运行中改变设置(通过改变内核参数)。与其他文件系统不同,/proc
存在于内存而不是硬盘中。
proc 文件系统提供的信息如下:
-
进程信息:系统中的任何一个进程,在 proc 的子目录中都有一个同名的进程 ID,可以找到 cmdline、mem、root、stat、statm 以及 status。某些信息只有超级用户可见,例如进程根目录。每一个单独含有现有进程信息的进程有一些可用的专门链接,系统中的任何一个进程都有一个单独的自链接指向进程信息,其用处就是从进程中获取命令行信息。
-
CPU 信息:/proc/CPUinfo 文件可以获得中央处理器的当前准确信息。
-
负载信息:/proc/loadavg 文件包含系统负载信息。
-
系统内存信息:/proc/meminfo 文件包含系统内存的详细信息,其中显示物理内存的数量、可用交换空间的数量,以及空闲内存的数量等。
$ touch cpu.py $ gedit cpu.py
#!/usr/bin/env python from __future__ import print_function from collections import OrderedDict import pprint def CPUinfo(): ''' Return the information in /proc/CPUinfo as a dictionary in the following format: CPU_info['proc0']={...} CPU_info['proc1']={...} ''' CPUinfo = OrderedDict() procinfo = OrderedDict() nprocs = 0 with open('/proc/cpuinfo') as f: for line in f: if not line.strip(): # end of one processor CPUinfo['proc%s' % nprocs] = procinfo nprocs = nprocs + 1 # Reset procinfo = OrderedDict() else: if len(line.split(':')) == 2: procinfo[line.split(':')[0].strip()] = line.split(':')[1].strip() else: procinfo[line.split(':')[0].strip()] = '' return CPUinfo if __name__ == '__main__': CPUinfo = CPUinfo() for processor in CPUinfo.keys(): print(CPUinfo[processor]['model name'])
-
$ python cpu.py
程序简要解析:
读取
/proc/CPUinfo
中的信息,返回list
,每核心一个dict
。其中
list
是一个使用方括号括起来的有序元素集合。list
可以作为以 0 下标开始的数组。dict
是 Python 的内置数据类型之一,它定义了键和值之间一对一的关系。OrderedDict
是一个字典子类,可以记住其内容增加的顺序。常规dict
并不跟踪插入顺序,迭代处理时会根据键在散列表中存储的顺序来生成值。在OrderedDict
中则相反,它会记住元素插入的顺序,并在创建迭代器时使用这个顺序。
建立 sys_load.py, 并写入以下代码:
$ touch sys_load.py
$ gedit sys_load.py
#!/usr/bin/env python
import os
def load_stat():
loadavg = {}
f = open("/proc/loadavg")
con = f.read().split()
f.close()
loadavg['lavg_1'] = con[0]
loadavg['lavg_5'] = con[1]
loadavg['lavg_15'] = con[2]
loadavg['nr'] = con[3]
loadavg['last_pid'] = con[4]
return loadavg
print "loadavg", load_stat()['lavg_15']
$ python sys_load.py
程序简要解析:
从/proc/loadavg
中获取当前负载的信息
import os
:Python 中 import
用于导入不同的模块,包括系统提供和自定义的模块。其基本形式为:import 模块名 [as 别名]
,如果只需要导入模块中的部分或全部内容可以用形式:from 模块名 import *
来导入相应的模块。OS
模块 os
模块提供了一个统一的操作系统接口函数,os
模块能在不同操作系统平台如 nt
,posix
中的特定函数间自动切换,从而实现跨平台操作。
建立 mem.py,并写入以下代码:
$ touch mem.py
$ gedit mem.py
代码如下:
#!/usr/bin/env python
from __future__ import print_function
from collections import OrderedDict
def meminfo():
''' Return the information in /proc/meminfo
as a dictionary '''
meminfo = OrderedDict()
with open('/proc/meminfo') as f:
for line in f:
meminfo[line.split(':')[0]] = line.split(':')[1].strip()
return meminfo
if __name__ == '__main__':
# print(meminfo())
meminfo = meminfo()
print('Total memory: {0}'.format(meminfo['MemTotal']))
print('Free memory: {0}'.format(meminfo['MemFree']))
$ Python mem.py
代码简要解析:
读取proc/meminfo
中的信息, Python 字符串的split
方法是用的频率还是比较多的。比如我们需要存储一个很长的数据,并且按照有结构的方法存储,方便以后取数据进行处理。当然可以用json
的形式,但是也可以把数据存储到一个字段里面,然后有某种标示符来分割。Python 中的strip
用于去除字符串的首位字符,最后打印出内存总数和空闲数。
建立 net.py,并写入以下代码:
$ touch net.py
$ gedit net.py
代码如下:
#!/usr/bin/env python
import time
import sys
if len(sys.argv) > 1:
INTERFACE = sys.argv[1]
else:
INTERFACE = 'eth0'
STATS = []
print 'Interface:', INTERFACE
def rx():
ifstat = open('/proc/net/dev').readlines()
for interface in ifstat:
if INTERFACE in interface:
stat = float(interface.split()[1])
STATS[0:] = [stat]
def tx():
ifstat = open('/proc/net/dev').readlines()
for interface in ifstat:
if INTERFACE in interface:
stat = float(interface.split()[9])
STATS[1:] = [stat]
print 'In Out'
rx()
tx()
while True:
time.sleep(1)
rxstat_o = list(STATS)
rx()
tx()
RX = float(STATS[0])
RX_O = rxstat_o[0]
TX = float(STATS[1])
TX_O = rxstat_o[1]
RX_RATE = round((RX - RX_O) / 1024 / 1024, 3)
TX_RATE = round((TX - TX_O) / 1024 / 1024, 3)
print RX_RATE, 'MB ', TX_RATE, 'MB'
代码简要解析:
读取/proc/net/dev
中的信息,Python 中文件操作可以通过 open
函数,这的确很像 C 语言中的 fopen
。通过 open
函数获取一个 file object
,然后调用 read()
,write()
等方法对文件进行读写操作。
另外, Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: read()
、readline()
和 readlines()
。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。
.read()
每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而.read()
生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。
.readline()
和 .readlines()
之间的差异是后者一次读取整个文件,像 .read()
一样。.readlines()
自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for … in …
结构进行处理。
另一方面,.readline()
每次只读取一行,通常比 .readlines()
慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()
。
最后清单是打印出网络接口的输入和输出情况。