Python腳本如何實(shí)現(xiàn)監(jiān)控服務(wù)器日志異常并通過(guò)釘釘推送告警?
前言
服務(wù)器出問(wèn)題時(shí),最怕的不是故障本身,而是沒(méi)人第一時(shí)間知道。磁盤(pán)寫(xiě)滿、服務(wù)報(bào)錯(cuò)、日志瘋狂刷異常,如果只能靠人工定時(shí)登錄檢查,往往等發(fā)現(xiàn)問(wèn)題時(shí),業(yè)務(wù)已經(jīng)受影響很久了。
對(duì)于很多個(gè)人服務(wù)器、家庭NAS、測(cè)試機(jī)或中小團(tuán)隊(duì)內(nèi)網(wǎng)主機(jī)來(lái)說(shuō),上完整的商業(yè)監(jiān)控平臺(tái)有些重,接入成本和維護(hù)成本都不低。但完全不做告警,又會(huì)讓機(jī)器變成“沉默設(shè)備”:平時(shí)看起來(lái)穩(wěn)定,一旦異常,只能等用戶反饋或服務(wù)徹底不可用。
其實(shí)很多問(wèn)題都會(huì)先出現(xiàn)在日志里。比如no space left on device、failed、exception、error這些關(guān)鍵詞,往往已經(jīng)足夠提示系統(tǒng)出現(xiàn)風(fēng)險(xiǎn)。用一個(gè)輕量Python腳本持續(xù)讀取指定日志文件,再通過(guò)釘釘機(jī)器人推送告警,就能先搭出一套低成本、可落地的異常提醒機(jī)制。
這套方案的價(jià)值在于簡(jiǎn)單直接:日志里出現(xiàn)異常關(guān)鍵詞,腳本立即識(shí)別并組裝告警信息,釘釘群或手機(jī)端馬上收到提醒。對(duì)于磁盤(pán)空間不足、服務(wù)啟動(dòng)失敗、容器異常、應(yīng)用報(bào)錯(cuò)等場(chǎng)景,已經(jīng)可以覆蓋不少基礎(chǔ)運(yùn)維需求。
本文將從釘釘機(jī)器人Webhook和加簽配置開(kāi)始,編寫(xiě)Python日志監(jiān)控腳本,完成依賴安裝、測(cè)試觸發(fā)、后臺(tái)運(yùn)行和systemd開(kāi)機(jī)自啟。最后再通過(guò) cpolar 配置SSH公網(wǎng)TCP地址,讓你收到告警后可以遠(yuǎn)程登錄內(nèi)網(wǎng)服務(wù)器,形成“發(fā)現(xiàn)問(wèn)題—收到告警—遠(yuǎn)程處理”的完整閉環(huán)。

1.測(cè)試效果
效果預(yù)覽
當(dāng)你的/var/log/syslog或應(yīng)用日志中出現(xiàn):
May 08 15:30:01 server cpolar[1234]: Failed to write log: no space left on device
你將在釘釘群收到如下消息
【服務(wù)器告警】
主機(jī):Z4S-VJFL
時(shí)間:2026-05-08 15:30:01
日志路徑:/var/log/cpolar/access.log.20260508
內(nèi)容:Failed to write log: no space left on device
磁盤(pán)空間不足!請(qǐng)立即處理!
通過(guò)這個(gè)Python腳本,你實(shí)現(xiàn)了
實(shí)時(shí)監(jiān)控任意日志文件
關(guān)鍵詞觸發(fā)精準(zhǔn)告警
釘釘消息秒級(jí)觸達(dá)手機(jī)
低資源占用,適合嵌入式設(shè)備
零依賴復(fù)雜框架,純標(biāo)準(zhǔn)庫(kù) + requests
延伸場(chǎng)景:監(jiān)控Nginx錯(cuò)誤日志 → 發(fā)現(xiàn)攻擊行為
監(jiān)控?cái)?shù)據(jù)庫(kù)慢查詢?nèi)罩?→ 優(yōu)化SQL
監(jiān)控Docker容器日志 → 異常自動(dòng)重啟
讓機(jī)器替你“盯屏”,你只管睡覺(jué)!
2.獲取釘釘Webhook和Secret
打開(kāi)釘釘群 → 點(diǎn)擊右上角設(shè)置:

找到智能群助手 → 添加機(jī)器人:


添加自定義機(jī)器人:

點(diǎn)擊添加:

給機(jī)器人起個(gè)名字,我這里是“服務(wù)器告警”:

設(shè)置發(fā)消息關(guān)鍵詞,因?yàn)楝F(xiàn)在釘釘對(duì)安全嚴(yán)格,所以需要設(shè)置限制,,也可以設(shè)置加簽或者IP地址:

點(diǎn)擊“加簽”,復(fù)制生成的秘鑰,留著備用:

點(diǎn)擊完成后,復(fù)制生成的Webhook,留著備用:

3.編寫(xiě)Python監(jiān)控腳本
創(chuàng)建要監(jiān)控的日志文件:
mkdir /var/log/ceshi/ touch /var/log/ceshi/access.log.20260508
創(chuàng)建文件log_monitor.py:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import time
import json
import hmac
import hashlib
import base64
import urllib.parse
from datetime import datetime
from pathlib import Path
import requests
# ====== 配置區(qū)(請(qǐng)按需修改)======
LOG_FILE = "/var/log/ceshi/access.log.20260508" # 要監(jiān)控的日志文件
KEYWORDS = ["error", "failed", "exception", "no space left on device", "disk full"]
HOSTNAME = os.uname().nodename # 自動(dòng)獲取主機(jī)名
# 釘釘機(jī)器人配置(從釘釘后臺(tái)獲?。?
DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=dbf63c2e3c2f2dd"
DINGTALK_SECRET = "SEC8bb4d908c1039a4"
# ====== 釘釘簽名函數(shù) ======
def get_dingtalk_sign():
timestamp = str(round(time.time() * 1000))
secret_enc = DINGTALK_SECRET.encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, DINGTALK_SECRET)
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
return timestamp, sign
# ====== 發(fā)送釘釘消息 ======
def send_dingtalk_alert(message):
timestamp, sign = get_dingtalk_sign()
webhook_url = f"{DINGTALK_WEBHOOK}×tamp={timestamp}&sign={sign}"
data = {
"msgtype": "markdown",
"markdown": {
"title": "【服務(wù)器告警】",
"text": message
}
}
try:
response = requests.post(webhook_url, json=data, timeout=10)
if response.status_code != 200:
print(f"[!] 釘釘發(fā)送失敗: {response.text}")
except Exception as e:
print(f"[!] 釘釘請(qǐng)求異常: {e}")
# ====== 監(jiān)控日志主函數(shù) ======
def monitor_log():
log_path = Path(LOG_FILE)
if not log_path.exists():
print(f"[!] 日志文件不存在: {LOG_FILE}")
return
# 獲取文件初始大?。ㄓ糜跀帱c(diǎn)續(xù)讀)
file_size = log_path.stat().st_size
print(f"[+] 開(kāi)始監(jiān)控日志: {LOG_FILE} (初始大小: {file_size} bytes)")
while True:
try:
current_size = log_path.stat().st_size
if current_size < file_size:
# 日志被輪轉(zhuǎn)(如 logrotate),重置位置
print("[+] 檢測(cè)到日志輪轉(zhuǎn),重新開(kāi)始讀取")
file_size = 0
if current_size > file_size:
with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f:
f.seek(file_size) # 從上次位置讀起
lines = f.readlines()
file_size = current_size # 更新已讀位置
for line in lines:
line_lower = line.lower()
for keyword in KEYWORDS:
if keyword in line_lower:
# 構(gòu)建告警消息
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
msg = (
f"## ?? **【服務(wù)器告警】**\n\n"
f"- **主機(jī)**: `{HOSTNAME}`\n"
f"- **時(shí)間**: `{now}`\n"
f"- **日志路徑**: `{LOG_FILE}`\n"
f"- **內(nèi)容**: `{line.strip()}`\n\n"
f"> ?? **檢測(cè)到關(guān)鍵詞: `{keyword}`**"
)
print(f"[ALERT] {line.strip()}")
send_dingtalk_alert(msg)
break # 避免重復(fù)告警同一行
time.sleep(1) # 每秒檢查一次
except KeyboardInterrupt:
print("\n[+] 監(jiān)控已停止")
break
except Exception as e:
print(f"[!] 監(jiān)控異常: {e}")
time.sleep(5)
if __name__ == "__main__":
monitor_log()
4.安裝依賴 & 賦予執(zhí)行權(quán)限
進(jìn)入你的項(xiàng)目目錄:
cd /root/ceshi
創(chuàng)建虛擬環(huán)境(Python 3.6+ 自帶 venv)
python3 -m venv venv
激活虛擬環(huán)境:
source venv/bin/activate
此時(shí)提示符會(huì)變成 (venv),再安裝包
pip install requests

5.測(cè)試運(yùn)行
運(yùn)行你的腳本:
python log_monitor.py

編輯/var/log/ceshi/access.log.20260508監(jiān)控文件:
vi access.log.20260508
May 08 15:30:01 server cpolar[1234]: Failed to write log: no space left on device

釘釘成功發(fā)送告警:

6.運(yùn)行 & 開(kāi)機(jī)自啟
方式 1:使用nohup臨時(shí)運(yùn)行
nohup python3 /path/to/log_monitor.py > /var/log/log_monitor.log 2>&1 &
方式 2:創(chuàng)建systemd服務(wù)(推薦,支持開(kāi)機(jī)自啟)
創(chuàng)建服務(wù)文件:
sudo vim /etc/systemd/system/log-monitor.service
[Unit] Description=Log Monitor for Server Alerts After=network.target [Service] Type=simple User=root ExecStart=/usr/bin/python3 /ceshi/log_monitor.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
啟動(dòng)服務(wù):
sudo systemctl daemon-reload sudo systemctl enable --now log-monitor.service sudo systemctl status log-monitor

在現(xiàn)實(shí)運(yùn)維中,很多開(kāi)發(fā)者、創(chuàng)客甚至中小企業(yè)都把關(guān)鍵服務(wù)部署在家庭NAS、老舊服務(wù)器或內(nèi)網(wǎng)測(cè)試機(jī)上——它們沒(méi)有固定公網(wǎng)IP,藏在路由器后面,平時(shí)靠cpolar暴露個(gè)Web界面勉強(qiáng)夠用。可一旦半夜磁盤(pán)爆滿、Docker容器崩潰、系統(tǒng)日志里刷出“no space left on device”或“cpolar failed to reconnect”,你卻遠(yuǎn)在千里之外出差、旅游,甚至正在熟睡。這時(shí)候,人工巡檢毫無(wú)意義,而商業(yè)監(jiān)控平臺(tái)又太重、太貴。
但如果你提前做了兩件事:
第一,在服務(wù)器上跑一個(gè)輕量Python腳本,持續(xù)掃描 /var/log/cpolar/ 或系統(tǒng)日志,一旦發(fā)現(xiàn)關(guān)鍵詞就通過(guò)釘釘機(jī)器人推送告警到手機(jī);
第二,用cpolar配置一條TCP隧道,把本地22端口(SSH)映射到公網(wǎng),哪怕只是臨時(shí)分配的地址。
那么當(dāng)故障發(fā)生時(shí),你的手機(jī)會(huì)立刻收到釘釘消息:“【告警Z4S主機(jī)磁盤(pán)已滿!建議通過(guò) cpolar SSH登錄清理”。你只需打開(kāi)終端,輸入ssh -p 22222 root@192.xxx.xxx.xxx,就能像坐在機(jī)器前一樣,刪日志、重啟服務(wù)、查進(jìn)程——整個(gè)過(guò)程不到五分鐘,無(wú)需回家,不用求人。這不僅是技術(shù)組合,更是對(duì)“運(yùn)維最后一公里”的真實(shí)補(bǔ)全:讓每一臺(tái)沉默的內(nèi)網(wǎng)設(shè)備,都能在危急時(shí)刻主動(dòng)呼救,并為你留一扇隨時(shí)可進(jìn)的門。 尤其對(duì)于用極空間、樹(shù)莓派、舊筆記本搭建家庭實(shí)驗(yàn)室的人來(lái)說(shuō),這套方案成本近乎為零,卻能極大提升系統(tǒng)的可靠性和你的安心感。
7.安裝cpolar實(shí)現(xiàn)隨時(shí)隨地開(kāi)發(fā)
7.1 什么是cpolar?
cpolar是一款安全高效的內(nèi)網(wǎng)穿透工具,無(wú)需公網(wǎng)IP或復(fù)雜配置,只需一條命令,即可將本地服務(wù)器、Web服務(wù)或任意端口映射到公網(wǎng),讓你隨時(shí)隨地遠(yuǎn)程訪問(wèn)內(nèi)網(wǎng)應(yīng)用,特別適合開(kāi)發(fā)調(diào)試、遠(yuǎn)程運(yùn)維和應(yīng)急部署等場(chǎng)景。
7.2 部署cpolar
cpolar 可以將你本地電腦中的服務(wù)(如 SSH、Web、數(shù)據(jù)庫(kù))映射到公網(wǎng)。即使你在家里或外出時(shí),也可以通過(guò)公網(wǎng)地址連接回本地運(yùn)行的開(kāi)發(fā)環(huán)境。
??以下是安裝cpolar步驟:
使用一鍵腳本安裝命令:
sudo curl https://get.cpolar.sh | sh

安裝完成后,執(zhí)行下方命令查看cpolar服務(wù)狀態(tài):(如圖所示即為正常啟動(dòng))
sudo systemctl status cpolar

Cpolar安裝和成功啟動(dòng)服務(wù)后,在瀏覽器上輸入虛擬機(jī)主機(jī)IP加9200端口即:【http://ip:9200】訪問(wèn)Cpolar管理界面,使用Cpolar官網(wǎng)注冊(cè)的賬號(hào)登錄,登錄后即可看到cpolar web 配置界面,接下來(lái)在web 界面配置即可:
打開(kāi)瀏覽器訪問(wèn)本地9200端口,使用cpolar賬戶密碼登錄即可,登錄后即可對(duì)隧道進(jìn)行管理。

8.配置公網(wǎng)地址
通過(guò)配置,你可以在本地WSL或Linux系統(tǒng)上運(yùn)行SSH服務(wù),并通過(guò)Cpolar將其映射到公網(wǎng),從而實(shí)現(xiàn)從任意設(shè)備遠(yuǎn)程連接開(kāi)發(fā)環(huán)境的目的。
- 隧道名稱:可自定義,本例使用了:ssh,注意不要與已有的隧道名稱重復(fù)
- 協(xié)議:tcp
- 本地地址:22
- 端口類型:隨機(jī)臨時(shí)TCP端口
- 地區(qū):China Top

創(chuàng)建成功后,打開(kāi)左側(cè)在線隧道列表,可以看到剛剛通過(guò)創(chuàng)建隧道生成了公網(wǎng)地址,接下來(lái)就可以在其他電腦或者移動(dòng)端設(shè)備(異地)上,使用任意一個(gè)地址在終端中訪問(wèn)即可。
tcp 表示使用的協(xié)議類型
2.tcp.cpolar.top是 Cpolar 提供的域名
12178是隨機(jī)分配的公網(wǎng)端口號(hào)

通過(guò)Cpolar提供的公網(wǎng)地址和端口,就可以進(jìn)行遠(yuǎn)程部署啦!
ssh -p 12178 root@2.tcp.cpolar.top

9.保留固定TCP公網(wǎng)地址
使用cpolar為其配置TCP地址,該地址為固定地址,不會(huì)隨機(jī)變化。

選擇區(qū)域和描述:有一個(gè)下拉菜單,當(dāng)前選擇的是“China VIP”。
右側(cè)輸入框,用于填寫(xiě)描述信息。
保留按鈕:在右側(cè)有一個(gè)橙色的“保留”按鈕,點(diǎn)擊該按鈕可以保留所選的TCP地址。
列表中顯示了一條已保留的TCP地址記錄。
地區(qū):顯示為“China Top”。
地址:顯示為“ 16.tcp.cpolar.top:14775”。

登錄cpolar web UI管理界面,點(diǎn)擊左側(cè)儀表盤(pán)的隧道管理——隧道列表,找到所要配置的隧道ssh,點(diǎn)擊右側(cè)的編輯。

修改隧道信息,將保留成功的TCP端口配置到隧道中。
- 端口類型:選擇固定TCP端口
- 預(yù)留的TCP地址:填寫(xiě)保留成功的TCP地址
點(diǎn)擊更新。

創(chuàng)建完成后,打開(kāi)在線隧道列表,此時(shí)可以看到隨機(jī)的公網(wǎng)地址已經(jīng)發(fā)生變化,地址名稱也變成了保留和固定的TCP地址。

這樣我們連接到目標(biāo)主機(jī)就沒(méi)有任何的阻礙啦!
總結(jié)
完成配置后,這套Python日志監(jiān)控腳本就可以持續(xù)守在服務(wù)器旁邊。它不需要復(fù)雜平臺(tái),也不需要額外數(shù)據(jù)庫(kù),只要目標(biāo)日志文件里出現(xiàn)指定關(guān)鍵詞,就能通過(guò)釘釘機(jī)器人把異常內(nèi)容推送出來(lái)。
這種方案特別適合輕量場(chǎng)景。比如家庭NAS、樹(shù)莓派、舊電腦服務(wù)器、測(cè)試環(huán)境、內(nèi)網(wǎng)應(yīng)用或個(gè)人項(xiàng)目,不一定值得部署一整套監(jiān)控平臺(tái),但又確實(shí)需要在關(guān)鍵異常出現(xiàn)時(shí)及時(shí)收到提醒。
配置 cpolar 后,告警后的處理鏈路也能補(bǔ)上。收到釘釘消息后,可以通過(guò)固定TCP公網(wǎng)地址遠(yuǎn)程SSH登錄內(nèi)網(wǎng)主機(jī),查看日志、清理磁盤(pán)、重啟服務(wù)或排查進(jìn)程,不必等回到現(xiàn)場(chǎng)再處理。
需要注意的是,腳本里的釘釘Webhook和Secret不要寫(xiě)進(jìn)公開(kāi)倉(cāng)庫(kù),也不要在文章截圖中暴露真實(shí)值。SSH公網(wǎng)訪問(wèn)同樣要謹(jǐn)慎,建議使用強(qiáng)密碼或密鑰登錄,限制root直接登錄,并定期檢查隧道和服務(wù)器登錄記錄。
Python腳本負(fù)責(zé)發(fā)現(xiàn)異常,釘釘機(jī)器人負(fù)責(zé)及時(shí)通知,cpolar負(fù)責(zé)留下遠(yuǎn)程處理入口。當(dāng)這三部分組合起來(lái)以后,一臺(tái)原本只能被動(dòng)等待人工巡檢的內(nèi)網(wǎng)服務(wù)器,就具備了主動(dòng)呼救和遠(yuǎn)程修復(fù)的基礎(chǔ)能力。
到此這篇關(guān)于Python腳本如何實(shí)現(xiàn)監(jiān)控服務(wù)器日志異常并通過(guò)釘釘推送告警?的文章就介紹到這了,更多相關(guān)Python和釘釘監(jiān)控服務(wù)器日志內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- docker-compose搭建prometheus+grafana+釘釘告警
- zabbix?6.0?使用?JavaScript?發(fā)出釘釘告警的方法
- SpringBoot-Admin實(shí)現(xiàn)微服務(wù)監(jiān)控+健康檢查+釘釘告警
- Zabbix 配置釘釘告警功能的實(shí)現(xiàn)代碼
- Python腳本構(gòu)建輕量級(jí)監(jiān)控告警體系(郵件/釘釘/企業(yè)微信)
- SpringBoot AOP實(shí)現(xiàn)釘釘+企業(yè)微信雙渠道異常告警
- C#調(diào)用釘釘API發(fā)送通知的實(shí)現(xiàn)示例
- Java對(duì)接釘釘考勤記錄的完整步驟
- Python實(shí)現(xiàn)釘釘自動(dòng)化完整指南
- 基于Python實(shí)現(xiàn)開(kāi)發(fā)釘釘通知機(jī)器人
- Golang接入釘釘通知的示例代碼
相關(guān)文章
HTTP與HTTP協(xié)作的Web服務(wù)器訪問(wèn)流程圖解
記得以前剛接觸網(wǎng)站的時(shí)候,很奇怪一臺(tái)服務(wù)器上可以放很多個(gè)網(wǎng)站,不用的域名就可以訪問(wèn)不同的目錄,今天看起來(lái)的理所當(dāng)然以前真是不可思議,今天剛好看到了這篇文章就為大家分享一下2018-10-10
游戲服務(wù)器開(kāi)發(fā)的基本體系與服務(wù)器端開(kāi)發(fā)的一些建議
剛開(kāi)始時(shí)以為做游戲服務(wù)器和做web差不多,但是經(jīng)過(guò)一段時(shí)間之后,才發(fā)現(xiàn)代碼太多,太亂了,一看代碼都想重構(gòu),都是踩著坑往前走。這里我把一些游戲開(kāi)發(fā)方面的東西整理一下,希望能對(duì)那些想做游戲服務(wù)器開(kāi)發(fā)的朋友有所幫助2017-07-07
服務(wù)器錯(cuò)誤碼500 501 502 503 504 505 詳解
這篇文章主要介紹了服務(wù)器錯(cuò)誤碼500 501 502 503 504 505 詳解,需要的朋友可以參考下2015-07-07
curl.exe安裝使用的最全參數(shù)詳解以及常用命令匯總
Curl是一個(gè)功能強(qiáng)大的命令行工具,可以看做是命令行瀏覽器,用于與服務(wù)器進(jìn)行數(shù)據(jù)交互,支持多種數(shù)據(jù)傳輸協(xié)議,如HTTP、HTTPS、FTP等,它支持文件的上傳和下載,它是一款開(kāi)源軟件,在多個(gè)操作系統(tǒng)上均可運(yùn)行,包括Windows、Linux、macOS等2024-04-04
虛擬主機(jī)應(yīng)該如何解決電信網(wǎng)通間互聯(lián)互通
電信和網(wǎng)通兩大基礎(chǔ)網(wǎng)絡(luò),人為地割裂了整個(gè)中國(guó)的網(wǎng)絡(luò)。無(wú)論是選擇把網(wǎng)站托管在電信、還是網(wǎng)通,都等于是在拒絕處于另外一個(gè)網(wǎng)絡(luò)中的客戶,因?yàn)閷?shí)在太慢了2011-10-10

