?作用:在服務器CPU高負載時發送郵件通知
目錄
一、功能代碼
二、配置開機自啟動該監控腳本
1,配置自啟腳本
2,啟動
三、功能測試
一、功能代碼
功能:在CPU負載超過預設置的90%閾值時就發送郵件通知!郵件內容顯示服務器的公網IP、CPU邏輯核心數及每個邏輯核心數的負載詳情
import psutil
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import requests
import time# 閾值設置
threshold = 90# 郵件服務器配置
smtp_server = 'smtp.qq.com'
smtp_port = 587 # QQ郵箱的端口號為587
# 發送方郵箱賬號和密碼
sender_email = 'xxxxxxx@qq.com'
sender_password = 'yxamfeswlsnijaie'
# 接收方郵箱地址
receiver_email = 'xxxxx@qq.com'# 全局變量
cpu_usage = None # 每個邏輯處理器的負載def get_server_ip():server_ip = '未獲取到公網ip'try:response1 = requests.get('https://ip.3322.net/', timeout=5)if response1.text:server_ip = response1.textexcept:passtry:response2 = requests.get('https://myip.ipip.net', timeout=5)if response2.text:unformat_server_ip = response2.textserver_ip = unformat_server_ip.split(':')[1]except:passtry:response3 = requests.get('https://ddns.oray.com/checkip', timeout=5)if response3.text:unformat_server_ip = response3.textserver_ip = unformat_server_ip.split(':')[1]except:passreturn server_ip# 監測CPU負載并發送郵件通知
def monitor_cpu_load():# 初始化標志變量last_email_sent = Nonewhile True:global cpu_usagetime.sleep(3) # 這里睡眠3秒是因為服務器在重啟開機時的瞬間cpu負載是比較高的,所以并不準確,等待3秒更準確cpu_usage = psutil.cpu_percent(interval=1, percpu=True) # 每個邏輯處理器的負載if all(usage >= threshold for usage in cpu_usage) and last_email_sent != "high":subject = "CPU負載過高警告"body = '服務器公網IP:{0}\n CPU邏輯核心數:{1}\n CPU每個邏輯核心負載均已超90%,請登錄服務器查看詳情\n CPU核心負載詳情:\n'send_email(subject, body)last_email_sent = "high"elif all(usage < threshold for usage in cpu_usage) and last_email_sent != "normal":subject = "CPU負載恢復正常通知"body = '服務器公網IP:{0}\n CPU邏輯核心數:{1}\n CPU已恢復正常。\n CPU核心負載詳情:\n'send_email(subject, body)last_email_sent = "normal"# 發送郵件通知
def send_email(subject, body):# 創建郵件內容global cpu_usagecpu_count = psutil.cpu_count(logical=True) # cpu邏輯核心數server_ip = get_server_ip() # 獲取公網ipfor i in range(cpu_count):body += "\t{%d}%%\n" % (i + 2)body = body.format(server_ip, cpu_count, *cpu_usage)message = MIMEMultipart()message['From'] = sender_emailmessage['To'] = receiver_emailmessage['Subject'] = subject# 添加郵件正文# MIMEText有三個參數第一個為文本內容,第二個 plain 設置文本格式,第三個 utf-8 設置編碼可不填message.attach(MIMEText(body, 'plain'))# 發送郵件try:print("正在發送郵件...")smtp = smtplib.SMTP(smtp_server, smtp_port)smtp.starttls() # 開啟TLS加密連接smtp.login(sender_email, sender_password)smtp.sendmail(sender_email, receiver_email, message.as_string())print("郵件發送成功!")except smtplib.SMTPException as e:print("郵件發送失敗:", e)finally:print("正在退出")smtp.quit()if __name__ == "__main__":monitor_cpu_load()
sender_email和receiver_email 填寫自己的郵箱地址
sender_password 是登錄QQ郵箱的授權碼
詳情參考:https://itutd.blog.csdn.net/article/details/131810368?spm=1001.2014.3001.5502
二、配置開機自啟動該監控腳本
1,配置自啟腳本
在服務器/usr/lib/systemd/system目錄下創建一個新的.service文件
vi /usr/lib/systemd/system/autorun_python.service
寫入以下內容
[Unit]
Description=python_script - monitor cpu
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=simple
ExecStart=/root/.virtualenvs/qubian/bin/python3 /home/monitor_cpu.py
Restart=always
[Install]
WantedBy=multi-user.target
?修改配置后可能需要運行以下命令重新加載
systemctl daemon-reload
?參數解釋:
-
[Unit]
:這個部分主要用于定義服務單元的基本信息,包括服務的描述和啟動順序等。Description
:描述這個服務的作用,通常是一個簡短的描述。After
:指定在啟動這個服務之前需要先啟動的其他服務單元。在本例中,指定了在啟動這個服務之前需要先啟動的服務有?network.target
、remote-fs.target
?和?nss-lookup.target
。
-
[Service]
:這個部分定義了服務運行時的相關參數。Type
:指定服務的類型,有 simple、forking、oneshot、dbus、notify 等類型。在這里,Type=simple
?表示這是一個簡單類型的服務。ExecStart
:定義服務啟動時執行的命令或腳本。在這個例子中,指定了使用指定的 Python 虛擬環境中的 Python 解釋器執行?/home/monitor_cpu.py
?腳本。
-
Restart
:指定服務異常退出時的重啟策略,always
?表示始終重啟。
-
[Install]
:指定服務的安裝相關信息。WantedBy
:指定服務所屬的 target,即服務啟動的目標。在這里,multi-user.target
?表示這個服務是為了多用戶模式下運行的。
對于Type參數的值有以下:
-
Type=forking
:表示服務將以分叉(forking)方式運行,即服務會創建一個子進程來運行主要的服務進程。當主進程退出時,服務就會被認為是已經停止。但是,它還支持在主進程退出后,Systemd會等待一段時間,以便子進程可以執行一些清理工作。 -
Type=simple:
它表示這個服務是一個簡單的服務,即它只有一個主進程,當這個主進程退出時,服務就會被認為是已經停止。 -
Type=oneshot
:這種類型的服務是指它只需要在啟動時運行一次。當主進程退出時,服務就會被認為是已經停止。 -
Type=dbus
:這種類型的服務是指它需要一個D-Bus名稱,以便Systemd可以監控它。 -
Type=notify
:這種類型的服務是指它會在主進程準備好接受請求時,發送一個通知給Systemd。當Systemd接收到這個通知時,它就會認為服務已經啟動。 -
Type=idle
:這種類型的服務是指它會在所有其他類型的服務都已經啟動后,才會啟動。
2,啟動
# 設置開機自啟動
systemctl enable autorun_python.service
# 運行服務
systemctl start autorun_python.service
# 查看服務運行狀態
systemctl status autorun_python.service
?查看服務運行狀態,顯示active(running)正在運行中...
更多相關命令
# 關閉開機自啟
systemctl disable autorun_python.service
# 停止運行服務
systemctl stop autorun_python.service
# 重啟服務
systemctl restart autorun_python.service
三、功能測試
寫一個讓CPU滿載的程序測試上面監控CPU的代碼功能是否能正常工作
from multiprocessing import cpu_count
from multiprocessing import Processdef func(): # 死循環函數,讓cpu滿載while True:passif __name__ == '__main__':p_lst = [] # 定義一個列表core_count = cpu_count() # CPU核心數for i in range(core_count):p = Process(target=func) # 子進程調用函數p.start() # 啟動子進程p_lst.append(p) # 將所有進程寫入列表中for p in p_lst:p.join() # 檢測p是否結束,如果沒有結束就阻塞直到結束,否則不阻塞print('結束')
使用htop命令查看cpu的負載狀態
?這時四個核心全被干滿了!
也收到了超負載的郵件通知
當CPU負載恢復正常時也收到了相應的郵件
?