使用Python寫個小監(jiān)控
1.入門
首先你得用過C/C++、java、Javascript等的一種,編程小白估計比較艱難,有一定編程經(jīng)驗的python小白相對簡單些。
1.1 Hello World!
Python安裝比較簡單,到官網(wǎng)上下載安裝包,一路下一步就可以了。因為我的服務(wù)器上安裝的是2.6.6,所以我也下了這個版本。話說2.x的差別不是很大,如果想用3.x,可能下面的代碼直接運行不過,不過也差不多,稍微改改即可。
新建一個文件,命名為hello.py。使用python的IDLE打開hello.py,寫入以下代碼:
print "Hello World!"
按F5,就可以看見輸出結(jié)果了。
1.2 基本語法
每一行是一條語句。C語言是通過分號”;“;
通過縮進來組織代碼塊。C語言是通過大括號”{}“;
注釋使用井號”#“。
1.3 數(shù)據(jù)類型、運算符、數(shù)據(jù)結(jié)構(gòu)
運算符和C語言差不多,C語言有的基本上直接用就可以。
數(shù)據(jù)類型有數(shù)值型,字符串。數(shù)據(jù)結(jié)構(gòu)有 list, tuple, dict, set。介紹一下tuple, 不能修改,通過索引進行查找。dict類似于map,存放鍵值對。來看例子,看看tuple使用:
>>> t=(1,2,[1,2]) >>> t[2] [1, 2]
1.4 流程控制
Python中可以使用if elif else、for和 while 來實現(xiàn)流程控制。同樣有 break 和 continue。有一點和C不同,如果有一個分支什么都不做,要使用 pass。例如
list=[0, 1, 2, 3, 4, 5]
for item in list:
if item == 1:
print item
elif item in (2, 3, 4, 5):
print "aha " + str(item)
else:
pass
運行結(jié)果是:
1
aha 2
aha 3
aha 4
aha 5
1.5 模塊組織
有方法和類。
方法這樣定義
def func(var): some code here
類和C++等有些不同
class MyClass(object):
common = 1
def __init__(self):
self.myvariable = 5
def myfunction(self, arg1, arg2):
return self.myvariable
common變量相當于C++中用 static 修飾的變量,所有類通用;繼承也非常簡單,可以看看開始推薦的那篇文章。
1.6 異常處理
異常處理非常簡單,直接貼代碼了:
def some_function():
try:
# Division by zero raises an exception
10 / 0
except ZeroDivisionError:
print "Oops, invalid."
else:
# Exception didn't occur, we're good.
pass
finally:
# This is executed after the code block is run
# and all exceptions have been handled, even
# if a new exception is raised while handling.
print "We're done with that."
1.7 工程組織
直接引用庫,或者從庫中引入某一個方法或變量。
import random from time import clock
2. 數(shù)據(jù)庫查詢
既然是監(jiān)控,免不了和數(shù)據(jù)庫打交道。我使用的是PostgreSQL,所以就介紹一下python怎么調(diào)用postgres。
連接postgres首先要安裝一個庫psycopg2,Windows下直接下載安裝即可,注意選對版本。我的服務(wù)器是CentOS,安裝直接運行
yum install python-psycopg2
就OK了。
2.1 首先創(chuàng)建數(shù)據(jù)庫連接
#get database connect def get_con(): host = '127.0.0.1' port = "5432" database = 'platform' user = 'postgres' password = 'postgres' conn = psycopg2.connect(database=database, user=user, password=password, host=host, port=port) return conn
2.2 執(zhí)行SQL語句
#執(zhí)行sql查詢 def query(conn, sql): cursor = conn.cursor() cursor.execute(sql) results = cursor.fetchall() #close cursor cursor.close() return results
2.3 然后就可以寫具體業(yè)務(wù)了
def getUsers():
conn = get_con()#open connect
sql = """select *
from t_user
order by intime DESC
limit 5"""
items = query(conn , sql)
print str(items)
conn.close() #close connect
注意3個引號”””,就是普通字符串,不過可以換行。
3. 發(fā)送郵件
查詢到數(shù)據(jù)之后不能及時通知管理員的話監(jiān)控就沒有意義了。所以我們通過郵件來通知,直接使用python的標準庫 smtplib 就可以了。寫個發(fā)送郵件的函數(shù):
#發(fā)送郵件
def send_email(subject, content):
sender = "yourmail@***.com"
password = "******" #密碼是看不見的哦
receivers = [tq8117179#163.com] #本人真實郵箱,歡迎發(fā)郵件討論技術(shù)問題
host = "smtp.exmail.qq.com"
port = 465
msg = MIMEText(content,'html','utf-8')
msg['From'] = sender
msg['To'] = ",".join(receivers)
msg['Subject'] = Header(subject, 'utf-8')
try:
smtp = smtplib.SMTP_SSL(host, port)
smtp.login(sender, password)
smtp.sendmail(sender, receivers, msg.as_string())
except Exception, e:
logger.error(e)
logger.info(content)
4.日志
發(fā)送郵件時我們使用了logger,這個logger是怎么來的呢?新建一個log.py,代碼如下
# coding=utf-8
import logging
import logging.handlers
logger = logging.getLogger('monitor')
logger.setLevel(logging.DEBUG)
filehandler = logging.handlers.TimedRotatingFileHandler(
"/mnt/log/monitor/monitor_log", 'midnight', 1, 7)
# 設(shè)置文件后綴名稱
filehandler.suffix = "%Y%m%d.log"
formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s: %(message)s')
filehandler.setFormatter(formatter)
logger.addHandler(filehandler)
通過logging.getLogger(‘monitor')生成一個logger,然后配置一個文件處理器。
然后在我們監(jiān)控程序中引用即可:
from log import logger
5. 把可配置信息放到配置文件中
如果我們添加一個管理員怎么辦?如果我們的郵箱密碼變了怎么辦?直接修改python文件啊,哈哈。python不用編譯直接改代碼就好了,可是我們的程序以后要打包呢,所以最好寫個配置文件,python的配置文件讀取非常簡單,使用python庫 ConfigParser 即可:
config = None
#get config
def getConfig():
global config
if config is None:
config = ConfigParser.ConfigParser()
config.read("monitor.ini")
return config
然后這樣使用:
#get database connect
def get_con():
host = getConfig().get('db', 'host')
port = getConfig().get('db', 'port')
database = getConfig().get('db', 'database')
user = getConfig().get('db', 'user')
password = getConfig().get('db', 'password')
conn = psycopg2.connect(database=database, user=user, password=password, host=host, port=port)
return conn
#發(fā)送郵件
def send_email(subject, content):
sender = getConfig().get('mail', 'sender')
password = getConfig().get('mail', 'password')
receivers = getConfig().get('mail', 'receivers').split(",")
host = getConfig().get('mail', 'host')
port = getConfig().getint('mail', 'port')
msg = MIMEText(content,'html','utf-8')
msg['From'] = sender
msg['To'] = ",".join(receivers)
msg['Subject'] = Header(subject, 'utf-8')
try:
smtp = smtplib.SMTP_SSL(host, port)
smtp.login(sender, password)
smtp.sendmail(sender, receivers, msg.as_string())
except:
logger.exception("Exception: ")
logger.info(content)
配置文件是monitor.ini,內(nèi)容如下:
#數(shù)據(jù)庫配置 [db] host = 127.0.0.1 port = 5432 database = platform user = postgres password = postgres #郵件配置 [mail] sender = yourmail@XXX.com password = ****** #多個聯(lián)系人用英文逗號隔開 receivers = tq8117179#163.com host = smtp.exmail.qq.com port = 465
6. 加點控制
我們每5分鐘查一下數(shù)據(jù),可是業(yè)務(wù)sql只能查詢最近的幾條,所以要加個時間段限制,弄個開始、結(jié)束時間。
start_time = "2015-10-1 16:24:24"
end_time = None
#update end_time, invoke before get new data
def update_end_time():
global end_time
now = time.mktime(datetime.now().timetuple())
end_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(now))
return end_time
#update end_time, invoke after get new data
def update_start_time():
global start_time
global end_time
start_time = end_time
return start_time
getUsers可以改寫成:
def getUsers (conn):
global start_time
global end_time
sql = """select *
from t_user
where intime>=""" +"'"+start_time+"' and intime<"+"'"+end_time+"';"
items = query(conn, sql)
if items is not None and len(items)>0:
count = len(items)
tip = "又有"+str(count)+"個用戶已經(jīng)注冊了。"+end_time
send_email(tip, tip+"\n"+str(items))
然后寫個統(tǒng)一的調(diào)度:
def task():
#init end_time and start_time, must init end_time first!!!
end_time = update_end_time()
start_time = update_start_time()
#init config
getConfig()
while True:
conn = get_con() #open connect
end_time = update_end_time()
############## process ##############
logger.info("query: "+end_time)
getUsers (conn)
#do some task else here
## end
update_start_time()
conn.close()#close connect
time.sleep(5*60)
#end of while
def run_monitor():
monitor = threading.Thread(target=task)
monitor.start()
if __name__ == "__main__":
run_monitor()
在task這個函數(shù)的while中,首先更新end_time,也就是當前時間;執(zhí)行完再把start_time更新成剛剛的end_time,這樣就不會有漏網(wǎng)之魚了。還有一個需要注意的地方,關(guān)鍵字global。 在python中,使用全局變量是需要global關(guān)鍵字進行聲明的,否則會出問題。
7. 運行
打開linux 控制臺,直接運行python monitor.py是可以運行的,可是shell一旦退出,任務(wù)也就停止了。于是我就選擇了一個進程管理工具:Supervisor。Supervisor 在進程中斷時還能自動重啟。
7.1. 安裝supervisor
首先安裝python-setuptools
yum install python-setuptools
安裝supervisor
easy_install supervisor
生成supervisor配置文件
echo_supervisord_conf > /etc/supervisord.conf
然后在/etc/supervisord.conf添加:
[program:monitor] command = python /usr/monitor/monitor.py directory = /usr/monitor user = root
7.2. 運行監(jiān)控
然后在終端中運行supervisord啟動supervisor。
在終端中運行supervisorctl,進入shell,運行status查看腳本的運行狀態(tài)。
7.3. 關(guān)閉監(jiān)控 以及常用命令
以下命令全部在supervisorctl的shell中執(zhí)行。
- shutdown 停止Supervisor(子進程也會被停止) ;
- start monitor 開啟monitor進程服務(wù)(一旦monitor進程退出,會自啟動) ;
- stop monitor 關(guān)閉monitor進程服務(wù) ;
- restart monitor 關(guān)閉正在運行的monitor進程,并且重新啟動monitor進程服務(wù) ;
- reload 重新加載supervisor配置文件 ;
- exit 退出supervisorctl的shell。
程序基本上就寫完了,也可以跑起來了,是不是很酷,大家快點動手實踐一下吧!
- 寫了個監(jiān)控nginx進程的Python腳本
- python動態(tài)監(jiān)控日志內(nèi)容的示例
- python操作攝像頭截圖實現(xiàn)遠程監(jiān)控的例子
- python實現(xiàn)監(jiān)控windows服務(wù)并自動啟動服務(wù)示例
- python監(jiān)控網(wǎng)卡流量并使用graphite繪圖的示例
- 使用Python的Supervisor進行進程監(jiān)控以及自動啟動
- python實現(xiàn)監(jiān)控linux性能及進程消耗性能的方法
- Python寫的服務(wù)監(jiān)控程序?qū)嵗?/a>
- Python腳本實現(xiàn)網(wǎng)卡流量監(jiān)控
- Python中使用Inotify監(jiān)控文件實例
相關(guān)文章
10個Python常用的損失函數(shù)及代碼實現(xiàn)分享
損失函數(shù)是一種衡量模型與數(shù)據(jù)吻合程度的算法。損失函數(shù)測量實際測量值和預(yù)測值之間差距的一種方式。本文為大家總結(jié)了10個常用的損失函數(shù)及Python代碼實現(xiàn),需要的可以參考一下2022-09-09
Python中關(guān)于列表的常規(guī)操作范例以及介紹
列表是一種有序的集合,可以隨時添加和刪除其中的元素。在python中使用的頻率非常高,本篇文章對大家的學(xué)習(xí)或工作具有一定的價值,需要的朋友可以參考下2021-09-09
Python虛擬環(huán)境virtualenv是如何使用的
今天給大家?guī)淼氖顷P(guān)于Python虛擬環(huán)境的相關(guān)知識,文章圍繞著Python虛擬環(huán)境virtualenv是如何使用的展開,文中有非常詳細的解釋及代碼示例,需要的朋友可以參考下2021-06-06
基于Python+Tkinter實現(xiàn)一個簡易計算器
Tkinter作為Python的標準庫,是非常流行的Python GUI工具,同時也是非常容易學(xué)習(xí)的。本文將利用Tkinter繪制一個簡單的計算器,感興趣的可以試一試2022-01-01

