286 lines
No EOL
21 KiB
HTML
286 lines
No EOL
21 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="tool" content="leanote-desktop-app">
|
||
<title>监控系统</title>
|
||
<style>
|
||
|
||
*{font-family:"lucida grande","lucida sans unicode",lucida,helvetica,"Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;}
|
||
|
||
body {
|
||
margin: 0;
|
||
}
|
||
|
||
/*公用文字样式*/
|
||
h1{font-size:30px}h2{font-size:24px}h3{font-size:18px}h4{font-size:14px}
|
||
.note-container{
|
||
width:850px;
|
||
margin:auto;
|
||
padding: 10px 20px;
|
||
box-shadow: 1px 1px 10px #eee;
|
||
}
|
||
#title {
|
||
margin: 0;
|
||
}
|
||
table {
|
||
margin-bottom: 16px;
|
||
border-collapse: collapse;
|
||
}
|
||
table th, table td {
|
||
padding: 6px 13px;
|
||
border: 1px solid #ddd;
|
||
}
|
||
table th {
|
||
font-weight: bold;
|
||
}
|
||
|
||
table tr {
|
||
background-color: none;
|
||
border-top: 1px solid #ccc;
|
||
}
|
||
table tr:nth-child(2n) {
|
||
background-color: rgb(247, 247, 249);
|
||
}
|
||
.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption {
|
||
border: 1px solid #ddd;
|
||
border-collapse: collapse;
|
||
padding: 6px 13px;
|
||
}
|
||
blockquote {
|
||
border-left-width:10px;
|
||
background-color:rgba(128,128,128,0.05);
|
||
border-top-right-radius:5px;
|
||
border-bottom-right-radius:5px;
|
||
padding:15px 20px;
|
||
border-left:5px solid rgba(128,128,128,0.075);
|
||
}
|
||
blockquote p {
|
||
margin-bottom:1.1em;
|
||
font-size:1em;
|
||
line-height:1.45
|
||
}
|
||
blockquote ul:last-child,blockquote ol:last-child {
|
||
margin-bottom:0
|
||
}
|
||
pre {
|
||
padding: 18px;
|
||
background-color: #f7f7f9;
|
||
border: 1px solid #e1e1e8;
|
||
border-radius: 3px;
|
||
display: block;
|
||
}
|
||
code {
|
||
padding: 2px 4px;
|
||
font-size: 90%;
|
||
color: #c7254e;
|
||
white-space: nowrap;
|
||
background-color: #f9f2f4;
|
||
border-radius: 4px;
|
||
}
|
||
.footnote {
|
||
vertical-align: top;
|
||
position: relative;
|
||
top: -0.5em;
|
||
font-size: .8em;
|
||
}
|
||
|
||
hr {
|
||
margin:2em 0
|
||
}
|
||
img {
|
||
max-width:100%
|
||
}
|
||
pre {
|
||
word-break:break-word
|
||
}
|
||
p,pre,pre.prettyprint,blockquote {
|
||
margin:0 0 1.1em
|
||
}
|
||
hr {
|
||
margin:2em 0
|
||
}
|
||
img {
|
||
max-width:100%
|
||
}
|
||
.sequence-diagram,.flow-chart {
|
||
text-align:center;
|
||
margin-bottom:1.1em
|
||
}
|
||
.sequence-diagram text,.flow-chart text {
|
||
font-size:15px !important;
|
||
font-family:"Source Sans Pro",sans-serif !important
|
||
}
|
||
.sequence-diagram [fill="#ffffff"],.flow-chart [fill="#ffffff"] {
|
||
fill:#f6f6f6
|
||
}
|
||
.sequence-diagram [stroke="#000000"],.flow-chart [stroke="#000000"] {
|
||
stroke:#3f3f3f
|
||
}
|
||
.sequence-diagram text[stroke="#000000"],.flow-chart text[stroke="#000000"] {
|
||
stroke:none
|
||
}
|
||
.sequence-diagram [fill="#000"],.flow-chart [fill="#000"],.sequence-diagram [fill="#000000"],.flow-chart [fill="#000000"],.sequence-diagram [fill="black"],.flow-chart [fill="black"] {
|
||
fill:#3f3f3f
|
||
}
|
||
ul,ol {
|
||
margin-bottom:1.1em
|
||
}
|
||
ul ul,ol ul,ul ol,ol ol {
|
||
margin-bottom:1.1em
|
||
}
|
||
kbd {
|
||
padding:.1em .6em;
|
||
border:1px solid rgba(63,63,63,0.25);
|
||
-webkit-box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||
box-shadow:0 1px 0 rgba(63,63,63,0.25);
|
||
font-size:.7em;
|
||
font-family:sans-serif;
|
||
background-color:#fff;
|
||
color:#333;
|
||
border-radius:3px;
|
||
display:inline-block;
|
||
margin:0 .1em;
|
||
white-space:nowrap
|
||
}
|
||
.toc ul {
|
||
list-style-type:none;
|
||
margin-bottom:15px
|
||
}
|
||
</style>
|
||
<!-- 该css供自定义样式 -->
|
||
<link href="../leanote-html.css" rel="stylesheet">
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<div class="note-container">
|
||
<h1 class="title" id="leanote-title">监控系统</h1>
|
||
<div class="content-html" id="leanote-content"><p>工作原理:基于/proc 文件系统<br></p><p>Linux 系统为管理员提供了非常好的方法,使其可以在系统运行时更改内核,而不需要重新引导内核系统,这是通过/proc 虚拟文件系统实现的。/proc 文件虚拟系统是一种内核和内核模块用来向进程(process)发送信息的机制(所以叫做“/proc”),这个伪文件系统允许与内核内部数据结构交互,获取有关进程的有用信息,在运行中(on the fly)改变设置(通过改变内核参数)。与其他文件系统不同,/proc 存在于内存而不是硬盘中。proc 文件系统提供的信息如下:</p><ul><li>进程信息:系统中的任何一个进程,在 proc 的子目录中都有一个同名的进程 ID,可以找到 cmdline、mem、root、stat、statm,以及 status。某些信息只有超级用户可见,例如进程根目录。每一个单独含有现有进程信息的进程有一些可用的专门链接,系统中的任何一个进程都有一个单独的自链接指向进程信息,其用处就是从进程中获取命令行信息。</li><li>系统信息:如果需要了解整个系统信息中也可以从/proc/stat 中获得,其中包括 CPU 占用情况、磁盘空间、内存对换、中断等。</li><li>CPU 信息:利用/proc/CPUinfo 文件可以获得中央处理器的当前准确信息。</li><li>负载信息:/proc/loadavg 文件包含系统负载信息。</li><li>系统内存信息:/proc/meminfo 文件包含系统内存的详细信息,其中显示物理内存的数量、可用交换空间的数量,以及空闲内存的数量等。</li></ul><p><strong>表 1 是 /proc 目录中的主要文件的说明:</strong></p><table border="1" cellspacing="0" cellpadding="2"><thead><tr><th><code>文件或目录名称</code></th><th><code>描 述</code></th></tr></thead><tbody><tr><td><code>apm</code></td><td><code>高级电源管理信息</code></td></tr><tr><td><code>cmdline</code></td><td><code>这个文件给出了内核启动的命令行</code></td></tr><tr><td><code>CPU</code><code>info</code></td><td><code>中央处理器信息</code></td></tr><tr><td><code>devices</code></td><td><code>可以用到的设备(块设备/字符设备)</code></td></tr><tr><td><code>dma</code></td><td><code>显示当前使用的 DMA 通道</code></td></tr><tr><td><code>filesystems</code></td><td><code>核心配置的文件系统</code></td></tr><tr><td><code>ioports</code></td><td><code>当前使用的 I/O 端口</code></td></tr><tr><td><code>interrupts</code></td><td><code>这个文件的每一行都有一个保留的中断</code></td></tr><tr><td><code>kcore</code></td><td><code>系统物理内存映像</code></td></tr><tr><td><code>kmsg</code></td><td><code>核心输出的消息,被送到日志文件</code></td></tr><tr><td><code>mdstat</code></td><td><code>这个文件包含了由 md 设备驱动程序控制的 RAID 设备信息</code></td></tr><tr><td><code>loadavg</code></td><td><code>系统平均负载均衡</code></td></tr><tr><td><code>meminfo</code></td><td><code>存储器使用信息,包括物理内存和交换内存</code></td></tr><tr><td><code>modules</code></td><td><code>这个文件给出可加载内核模块的信息。lsmod 程序用这些信息显示有关模块的名称,大小,使用数目方面的信息</code></td></tr><tr><td><code>net</code></td><td><code>网络协议状态信息</code></td></tr><tr><td><code>partitions</code></td><td><code>系统识别的分区表</code></td></tr><tr><td><code>pci</code></td><td><code>pci 设备信息</code></td></tr><tr><td><code>scsi</code></td><td><code>scsi 设备信息</code></td></tr><tr><td><code>self</code></td><td><code>到查看/proc 程序进程目录的符号连接</code></td></tr><tr><td><code>stat</code></td><td><code>这个文件包含的信息有 CPU 利用率,磁盘,内存页,内存对换,全部中断,接触开关以及赏赐自举时间</code></td></tr><tr><td><code>swaps</code></td><td><code>显示的是交换分区的使用情况</code></td></tr><tr><td><code>uptime</code></td><td><code>这个文件给出自从上次系统自举以来的秒数,以及其中有多少秒处于空闲</code></td></tr><tr><td><code>version</code></td><td><code>这个文件只有一行内容,说明正在运行的内核版本。可以用标准的编程方法进行分析获得所需的系统信息</code></td></tr></tbody></table><p><code>下面本文的几个例子都是使用</code><code> Python 脚本</code><code>读取</code>/proc 目录中的主要文件来实现<code>实现对 Linux 服务器的监控的 。</code></p><h3>使用 Python 脚本实现对 Linux 服务器的监控</h3><h3>对于 CPU(中央处理器)监测</h3><p>脚本 1 名称 CPU1.py,作用获取 CPU 的信息。</p><h5>清单 1.获取 CPU 的信息</h5><div><pre id="leanote_ace_1479795465858_0" class="ace-tomorrow">#!/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'])</pre></div><p>简单说明一下清单 1,读取/proc/CPUinfo 中的信息,返回 list,每核心一个 dict。其中 list 是一个使用方括号括起来的有序元素集合。List 可以作为以 0 下标开始的数组。Dict 是 Python 的内置数据类型之一, 它定义了键和值之间一对一的关系。OrderedDict 是一个字典子类,可以记住其内容增加的顺序。常规 dict 并不跟踪插入顺序,迭代处理时会根据键在散列表中存储的顺序来生成值。在 OrderedDict 中则相反,它会记住元素插入的顺序,并在创建迭代器时使用这个顺序。</p><p>可以使用 Python 命令运行脚本 CPU1.py 结果见图 1</p><div><pre id="leanote_ace_1479795465891_0" class="ace-tomorrow"># Python CPU1.py
|
||
Intel(R) Celeron(R) CPU E3200 @ 2.40GHz</pre></div><h5>图 1.运行清单 1</h5><p><img id="__LEANOTE_D_IMG_1479695228452" src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c6" alt="运行清单 1" width="577" data-media-type="image" data-attr-org-src-id="249D327C535C491D9109A04A77D41767" data-attr-org-img-file="file:///C:/Users/Administrator/AppData/Local/YNote/data/hongxiutianmo@163.com/74f667dd5f564a049d350ab49ba55fa7/image002.png" data-mce-src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c6"></p><p>也可以使用 chmod 命令添加权限收直接运行 CPU1.py</p><div><pre id="leanote_ace_1479795465903_0" class="ace-tomorrow">#chmod +x CPU1.py
|
||
# ./CPU1.py</pre></div><h3>对于系统负载监测</h3><p>脚本 2 名称 CPU2.py,作用获取系统的负载信息</p><h5>清单 2 获取系统的负载信息</h5><div><pre id="leanote_ace_1479795465915_0" class="ace-tomorrow">#!/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']</pre></div><p>简单说明一下清单 2:清单 2 读取/proc/loadavg 中的信息,import os :Python 中 import 用于导入不同的模块,包括系统提供和自定义的模块。其基本形式为:import 模块名 [as 别名],如果只需要导入模块中的部分或全部内容可以用形式:from 模块名 import *来导入相应的模块。OS 模块 os 模块提供了一个统一的操作系统接口函数,os 模块能在不同操作系统平台如 nt,posix 中的特定函数间自动切换,从而实现跨平台操作。</p><p>可以使用 Python 命令运行脚本 CPU1.py 结果见图 2 # Python CPU2.py</p><h5>图 2.运行清单 2</h5><p><img id="__LEANOTE_D_IMG_1479695228453" src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c7" alt="运行清单 2" width="536" data-media-type="image" data-attr-org-src-id="F78DA48D0DBA49948F2455E139D587A0" data-attr-org-img-file="file:///C:/Users/Administrator/AppData/Local/YNote/data/hongxiutianmo@163.com/e23e7327898848ac96a61cdd9577fab2/image004.png" data-mce-src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c7"></p><h3>对于内存信息的获取</h3><p>脚本 3 名称 mem.py,作用是获取内存使用情况信息</p><h5>清单 3 获取内存使用情况</h5><div><pre id="leanote_ace_1479795465925_0" class="ace-tomorrow">#!/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']))</pre></div><p>简单说明一下清单 3:清单 3 读取 proc/meminfo 中的信息,Python 字符串的 split 方法是用的频率还是比较多的。比如我们需要存储一个很长的数据,并且按照有结构的方法存储,方便以后取数据进行处理。当然可以用 json 的形式。但是也可以把数据存储到一个字段里面,然后有某种标示符来分割。 Python 中的 strip 用于去除字符串的首位字符,最后清单 3 打印出内存总数和空闲数。</p><p>可以使用 Python 命令运行脚本 mem.py 结果见图 3。 # Python mem.py</p><h5>图 3.运行清单 3</h5><p><img id="__LEANOTE_D_IMG_1479695228454" src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c8" alt="运行清单 3" width="555" data-media-type="image" data-attr-org-src-id="126A3E91237B4944B9A27D0C317160B3" data-attr-org-img-file="file:///C:/Users/Administrator/AppData/Local/YNote/data/hongxiutianmo@163.com/e4f4bf1a57f84161b193f975291f9665/image006.png" data-mce-src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c8"></p><h3>对于网络接口的监测</h3><p>脚本 4 名称是 net.py,作用获取网络接口的使用情况。</p><h5>清单 4 net.py 获取网络接口的输入和输出</h5><div><pre id="leanote_ace_1479795465935_0" class="ace-tomorrow">#!/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'</pre></div><p>简单说明一下清单 4:清单 4 读取/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()。最后清单 4 打印出网络接口的输入和输出情况。</p><p>可以使用 Python 命令运行脚本 net.py 结果见图 4 #Python net.py</p><h5>图 4.运行清单 4</h5><p><img id="__LEANOTE_D_IMG_1479695228455" src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c9" alt="运行清单 4" width="555" data-media-type="image" data-attr-org-src-id="656E3AA946F34A719666439915212D8E" data-attr-org-img-file="file:///C:/Users/Administrator/AppData/Local/YNote/data/hongxiutianmo@163.com/dcb6645208794f33963869d8b1e5881c/image008.png" data-mce-src="http://192.168.56.4:9000/api/file/getImage?fileId=5833f84623eeeb0f8f0000c9"></p><h3>监控 Apache 服务器进程的 Python 脚本</h3><p>Apache 服务器进程可能会因为系统各种原因而出现异常退出,导致 Web 服务暂停。所以笔者写一个 Python 脚本文件:</p><h5>清单 5 crtrl.py 监控 Apache 服务器进程的 Python 脚本</h5><div><pre id="leanote_ace_1479795465947_0" class="ace-tomorrow">#!/usr/bin/env Python
|
||
import os, sys, time
|
||
|
||
while True:
|
||
time.sleep(4)
|
||
try:
|
||
ret = os.popen('ps -C apache -o pid,cmd').readlines()
|
||
if len(ret) < 2:
|
||
print "apache 进程异常退出, 4 秒后重新启动"
|
||
time.sleep(3)
|
||
os.system("service apache2 restart")
|
||
except:
|
||
print "Error", sys.exc_info()[1]</pre></div><p>设置文件权限为执行属性(使用命令 chmod +x crtrl.py),然后加入到/etc/rc.local 即可,一旦 Apache 服务器进程异常退出,该脚本自动检查并且重启。 简单说明一下清单 5 这个脚本不是基于/proc 伪文件系统的,是基于 Python 自己提供的一些模块来实现的 。这里使用的是 Python 的内嵌 time 模板,time 模块提供各种操作时间的函数。</p></div>
|
||
</div>
|
||
|
||
<!-- 该js供其它处理 -->
|
||
<script src="../leanote-html.js"></script>
|
||
</body>
|
||
</html> |