項(xiàng)目維護(hù)中服務(wù)會(huì)不定時(shí)的出現(xiàn)異常涮瞻,比如502鲤拿、404、101等等署咽,當(dāng)工作任務(wù)繁重時(shí)又不能實(shí)時(shí)監(jiān)測(cè)近顷,而linux的運(yùn)維者,逃脫不了定時(shí)任務(wù)的命題艇抠,最常用和快捷簡(jiǎn)單的是crontab幕庐,在少量機(jī)器的情況下久锥,crontab效率還是比較高和比較便捷家淤。但當(dāng)機(jī)器越多、應(yīng)用越多的情況下瑟由,繼續(xù)使用crontab進(jìn)行定時(shí)任務(wù)的管理配置絮重,那嚴(yán)重影響工作效率。但crontab執(zhí)行后結(jié)果如何如果不登錄服務(wù)器一般不能實(shí)施感知歹苦,此時(shí)我們可以借助python的郵件機(jī)制進(jìn)行實(shí)時(shí)通知也可以定時(shí)監(jiān)測(cè)服務(wù)發(fā)出告警信息以便及時(shí)處理青伤。
郵件機(jī)制相關(guān)知識(shí)簡(jiǎn)介
SMTP (Simple Mail Transfer Protocol)
郵件傳送代理 (Mail Transfer Agent,MTA) 程序使用SMTP協(xié)議來發(fā)送電郵到接收者的郵件服務(wù)器殴瘦。SMTP協(xié)議只能用來發(fā)送郵件狠角,不能用來接收郵件。大多數(shù)的郵件發(fā)送服務(wù)器 (Outgoing Mail Server) 都是使用SMTP協(xié)議蚪腋。SMTP協(xié)議的默認(rèn)TCP端口號(hào)是25丰歌。
SMTP協(xié)議的一個(gè)重要特點(diǎn)是它能夠接力傳送郵件。它工作在兩種情況下:一是電子郵件從客戶機(jī)傳輸?shù)椒?wù)器屉凯;二是從某一個(gè)服務(wù)器傳輸?shù)搅硪粋€(gè)服務(wù)器立帖。
POP3 (Post Office Protocol) & IMAP (Internet Message Access Protocol)
POP協(xié)議和IMAP協(xié)議是用于郵件接收的最常見的兩種協(xié)議。幾乎所有的郵件客戶端和服務(wù)器都支持這兩種協(xié)議悠砚。
POP3協(xié)議為用戶提供了一種簡(jiǎn)單晓勇、標(biāo)準(zhǔn)的方式來訪問郵箱和獲取電郵。使用POP3協(xié)議的電郵客戶端通常的工作過程是:連接服務(wù)器灌旧、獲取所有信息并保存在用戶主機(jī)绑咱、從服務(wù)器刪除這些消息然后斷開連接。POP3協(xié)議的默認(rèn)TCP端口號(hào)是110枢泰。
IMAP協(xié)議也提供了方便的郵件下載服務(wù)描融,讓用戶能進(jìn)行離線閱讀。使用IMAP協(xié)議的電郵客戶端通常把信息保留在服務(wù)器上直到用戶顯式刪除宗苍。這種特性使得多個(gè)客戶端可以同時(shí)管理一個(gè)郵箱稼稿。IMAP協(xié)議提供了摘要瀏覽功能薄榛,可以讓用戶在閱讀完所有的郵件到達(dá)時(shí)間、主題让歼、發(fā)件人敞恋、大小等信息后再?zèng)Q定是否下載。IMAP協(xié)議的默認(rèn)TCP端口號(hào)是143谋右。
郵件格式 (RFC 2822)
每封郵件都有兩個(gè)部分:郵件頭和郵件體硬猫,兩者使用一個(gè)空行分隔。
郵件頭每個(gè)字段 (Field) 包括兩部分:字段名和字段值改执,兩者使用冒號(hào)分隔啸蜜。有兩個(gè)字段需要注意:From和Sender字段。From字段指明的是郵件的作者辈挂,Sender字段指明的是郵件的發(fā)送者衬横。如果From字段包含多于一個(gè)的作者,必須指定Sender字段终蒂;如果From字段只有一個(gè)作者并且作者和發(fā)送者相同蜂林,那么不應(yīng)該再使用Sender字段,否則From字段和Sender字段應(yīng)該同時(shí)使用拇泣。
郵件體包含郵件的內(nèi)容噪叙,它的類型由郵件頭的Content-Type字段指明。RFC 2822定義的郵件格式中霉翔,郵件體只是單純的ASCII編碼的字符序列睁蕾。
MIME (Multipurpose Internet Mail Extensions) (RFC 1341)
MIME擴(kuò)展郵件的格式,用以支持非ASCII編碼的文本债朵、非文本附件以及包含多個(gè)部分 (multi-part) 的郵件體等子眶。
Python郵件處理機(jī)制
Python smtplib模塊
該模塊定義了一個(gè)SMTP客戶端會(huì)話對(duì)象,可用于使用SMTP或ESMTP偵聽器守護(hù)程序向任何互聯(lián)網(wǎng)機(jī)器發(fā)送郵件葱弟。
用來創(chuàng)建一個(gè)SMTP對(duì)象壹店,稍后將演示如何用它來發(fā)送電子郵件
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
這里是上面語法的參數(shù)細(xì)節(jié)
- host - 這是運(yùn)行SMTP服務(wù)器的主機(jī)≈ゼ樱可以指定主機(jī)的IP地址或類似yiibai.com的域名硅卢。這是一個(gè)可選參數(shù)。
- port - 如果提供主機(jī)參數(shù)藏杖,則需要指定SMTP服務(wù)器正在偵聽的端口将塑。通常這個(gè)端口默認(rèn)值是:25。
- local_hostname - 如果SMTP服務(wù)器在本地計(jì)算機(jī)上運(yùn)行蝌麸,那么可以只指定localhost選項(xiàng)点寥。
- SMTP對(duì)象有一個(gè)sendmail的實(shí)例方法,該方法通常用于執(zhí)行郵件發(fā)送的工作来吩。它需要三個(gè)參數(shù)
- sender - 具有發(fā)件人地址的字符串敢辩。
- receivers - 字符串列表蔽莱,每個(gè)收件人一個(gè)。
- message - 作為格式如在各種RFC中指定的字符串戚长。
Python email模塊
- class email.message.Message
getitem盗冷,setitem實(shí)現(xiàn)obj[key]形式的訪問。
Msg.attach(playload): 向當(dāng)前Msg添加playload同廉。
Msg.set_playload(playload): 把整個(gè)Msg對(duì)象的郵件體設(shè)成playload仪糖。
Msg.add_header(_name, _value, **_params): 添加郵件頭字段。- class email.mime.base.MIMEBase(_maintype, _subtype, **_params)
所有MIME類的基類迫肖,是email.message.Message類的子類锅劝。- class email.mime.multipart.MIMEMultipart()
在3.0版本的email模塊 (Python 2.3-Python 2.5) 中,這個(gè)類位于 email.MIMEMultipart.MIMEMultipart蟆湖。
這個(gè)類是MIMEBase的直接子類故爵,用來生成包含多個(gè)部分的郵件體的MIME對(duì)象。- class email.mime.text.MIMEText(_text)
使用字符串_text來生成MIME對(duì)象的主體文本帐姻。
郵件發(fā)送實(shí)例
# -*- coding=utf-8 -*-
from email.mime.text import MIMEText
from email.header import Header
from smtplib import SMTP_SSL
#163smtp服務(wù)器,需要設(shè)置POP3端口并設(shè)置授權(quán)碼
host_server = 'smtp.163.com'
#sender_user為發(fā)件人郵箱號(hào)
sender_user = 'xxx@163.com'
#pwd為發(fā)件人郵箱的授權(quán)碼
pwd = 'xxxx'
#發(fā)件人的郵箱
sender_user_mail = 'xxx@163.com'
#收件人郵箱
receiver = 'xxx@qq.com'
#郵件的正文內(nèi)容
mail_content = '你好稠集,這是使用python登錄并驗(yàn)證mail模塊功能發(fā)郵件的測(cè)試'
#郵件標(biāo)題
mail_title = 'TEST郵件'
#ssl登錄
def send_mail(mail_content,mail_tile):
smtp = SMTP_SSL(host_server)
#set_debuglevel()是用來調(diào)試的奶段。參數(shù)值為1表示開啟調(diào)試模式饥瓷,參數(shù)值為0關(guān)閉調(diào)試模式
smtp.ehlo(host_server)
smtp.login(sender_user, pwd)
msg = MIMEText(mail_content, "plain", 'utf-8')
msg["Subject"] = Header(mail_title, 'utf-8')
msg["From"] = sender_user_mail
msg["To"] = receiver
smtp.sendmail(sender_user_mail, receiver, msg.as_string())
smtp.quit()
檢測(cè)服務(wù)是否正常實(shí)例
def test_server_status():
apiUrl = 'www.baidu.com'
try :
# message = "OK"
res = requests.get(apiUrl, verify = False)
return str(res.status_code),str(res.content.decode("utf-8"))
except Exception as e:
import re
m = re.search(r'(\[*[0-9]+\])', str(e), re.M | re.I)
if m:
status_code = m.group().split(']')[0]
return status_code,e
crontab 定時(shí)監(jiān)測(cè)任務(wù)
添加定時(shí)任務(wù),實(shí)時(shí)監(jiān)測(cè)服務(wù)狀態(tài)痹籍,當(dāng)服務(wù)狀態(tài)出現(xiàn)錯(cuò)誤時(shí)呢铆,發(fā)送郵件并告知維護(hù)人員簡(jiǎn)單信息。至此一個(gè)簡(jiǎn)單的定時(shí)監(jiān)測(cè)服務(wù)告警任務(wù)就大功告成了蹲缠。